diff --git a/src/app/components.d.ts b/src/app/components.d.ts index be12a63384b6d68e8883778613f7f2343e6768b6..0cde006fd1bc6d43e96ae235e9198204515cae20 100644 --- a/src/app/components.d.ts +++ b/src/app/components.d.ts @@ -13,7 +13,6 @@ declare module 'vue' { App: typeof import('./App.vue')['default'] AuthorizationForm: typeof import('./../modules/authorization/AuthorizationForm.vue')['default'] BaseLoader: typeof import('./../shared/BaseLoader.vue')['default'] - BaseSidebarMenu: typeof import('./../modules/BaseSidebarMenu.vue')['default'] Button: typeof import('./../shared/ui/Button.vue')['default'] CloseCircle: typeof import('./../shared/icons/CloseCircle.vue')['default'] CreateEntityMenu: typeof import('./../components/CreateEntityMenu.vue')['default'] @@ -21,7 +20,6 @@ declare module 'vue' { DashedIcon: typeof import('./../shared/icons/DashedIcon.vue')['default'] Divider: typeof import('./../shared/ui/Divider.vue')['default'] DividerItem: typeof import('./../modules/entities/DividerItem.vue')['default'] - DividerMenu: typeof import('./../modules/entities/settings/DividerMenu.vue')['default'] DividerSettings: typeof import('./../components/entities/settings/DividerSettings.vue')['default'] DottedIcon: typeof import('./../shared/icons/DottedIcon.vue')['default'] Drawer: typeof import('./../shared/ui/Drawer.vue')['default'] @@ -35,7 +33,6 @@ declare module 'vue' { HorizontalLineIcon: typeof import('./../shared/icons/HorizontalLineIcon.vue')['default'] ImageIcon: typeof import('./../shared/icons/ImageIcon.vue')['default'] ImageItem: typeof import('./../modules/entities/ImageItem.vue')['default'] - ImageMenu: typeof import('./../components/entities/settings/ImageMenu.vue')['default'] ImagePositionMenu: typeof import('./../components/entities/image/ImagePositionMenu.vue')['default'] ImageSettings: typeof import('./../components/entities/settings/ImageSettings.vue')['default'] ImageSettingsList: typeof import('./../components/entities/settings/lists/ImageSettingsList.vue')['default'] @@ -43,7 +40,6 @@ declare module 'vue' { ImageStateMenu: typeof import('./../components/entities/image/ImageStateMenu.vue')['default'] LogoAndLabel: typeof import('./../components/LogoAndLabel.vue')['default'] MenuDial: typeof import('./../shared/ui/MenuDial.vue')['default'] - MenuHeader: typeof import('./../components/MenuHeader.vue')['default'] Modal: typeof import('./../shared/ui/Modal.vue')['default'] NavigationIcon: typeof import('./../shared/icons/NavigationIcon.vue')['default'] PageBackgroundMenu: typeof import('./../modules/PageBackgroundMenu.vue')['default'] @@ -68,9 +64,7 @@ declare module 'vue' { TableIcon: typeof import('./../shared/icons/TableIcon.vue')['default'] TelegramSection: typeof import('./../modules/TelegramSection.vue')['default'] TextFontMenu: typeof import('./../components/entities/share/TextFontMenu.vue')['default'] - TextItem: typeof import('./../modules/entities/TextItem.vue')['default'] TextPositionMenu: typeof import('./../components/entities/text/TextPositionMenu.vue')['default'] - TextSettings: typeof import('./../components/entities/settings/TextSettings.vue')['default'] TextStateMenu: typeof import('./../components/entities/text/TextStateMenu.vue')['default'] ToggleButton: typeof import('./../shared/ui/ToggleButton.vue')['default'] ToggleSwitch: typeof import('./../shared/ui/ToggleSwitch.vue')['default'] diff --git a/src/app/helpers/images.ts b/src/app/helpers/images.ts index df8889732a52ee6392ea610cbc4b8c83df855c19..7d55e9228f537fba500d6a80016ac9415577e4fc 100644 --- a/src/app/helpers/images.ts +++ b/src/app/helpers/images.ts @@ -3,6 +3,7 @@ import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; import type { IImage } from '@/app/interfaces/entities'; import { useWebsocketStore } from '@/app/stores/websocket'; import { useInterfaceStore } from '@/app/stores/interface'; +import { editEntity } from '@/app/helpers/index'; export const setDefaultPageBackground = () => { const interfaceStore = useInterfaceStore(); @@ -57,24 +58,86 @@ export const cropImage = async (newUrl: string, entity: IImage) => { websocketStore.sendData(data); }; +export const getImageScalesToRemove = (entity: IImage) => { + const valuesToRemove = []; + let scale = entity.image_scale; + if (scale[0] === 'x') scale = scale.slice(1); + const initialImageWidth = Math.ceil(+entity.image_width / +scale); + const initialImageHeight = Math.ceil(+entity.image_height / +scale); + console.log(initialImageWidth, initialImageHeight); + if (initialImageWidth <= 400 || initialImageHeight <= 400) { + valuesToRemove.push('x0.25'); + if ( + initialImageWidth <= 200 || + initialImageHeight <= 200 || + (initialImageWidth >= 1600 && (entity.text ?? null)) + ) { + valuesToRemove.push('x0.5'); + if ( + initialImageWidth <= 95 || + initialImageHeight <= 95 || + (initialImageWidth >= 1066 && (entity.text ?? null)) + ) { + valuesToRemove.push('x0.75'); + } + } + } + if ( + (initialImageWidth >= 800 && (entity.text ?? null)) || + entity.image_width > initialImageWidth + ) { + valuesToRemove.push('x1'); + } + if ( + initialImageWidth >= 960 || + initialImageHeight >= 560 || + (initialImageWidth >= 640 && (entity.text ?? null)) + ) { + valuesToRemove.push('x1.25'); + if ( + initialImageWidth >= 800 || + initialImageHeight >= 467 || + (initialImageWidth >= 533 && (entity.text ?? null)) + ) { + valuesToRemove.push('x1.5'); + if ( + initialImageWidth >= 685 || + initialImageHeight >= 400 || + (initialImageWidth >= 457 && (entity.text ?? null)) + ) { + valuesToRemove.push('x1.75'); + if ( + initialImageWidth >= 600 || + initialImageHeight >= 350 || + (initialImageWidth >= 400 && (entity.text ?? null)) + ) { + valuesToRemove.push('x2'); + } + } + } + } + console.log('valuesToRemove: ', valuesToRemove); + return valuesToRemove; +}; + export const getImageSpeedDialSizeSmallerLabelsToRemove = (entity: IImage) => { - const elementsLabelsToRemove = []; + const valuesToRemove = []; const initialImageWidth = Math.ceil(entity.image_width / +entity.image_scale); const initialImageHeight = Math.ceil(entity.image_height / +entity.image_scale); if (initialImageWidth <= 400 || initialImageHeight <= 400) { - elementsLabelsToRemove.push('x0.25'); + valuesToRemove.push('x0.25'); if ( initialImageWidth <= 200 || initialImageHeight <= 200 || (initialImageWidth >= 1600 && entity.text_position) ) { - elementsLabelsToRemove.push('x0.5'); + valuesToRemove.push('x0.5'); if ( initialImageWidth <= 95 || initialImageHeight <= 95 || (initialImageWidth >= 1066 && entity.text_position) ) { - elementsLabelsToRemove.push('x0.75'); + valuesToRemove.push('x0.75'); } } } @@ -82,48 +145,56 @@ export const getImageSpeedDialSizeSmallerLabelsToRemove = (entity: IImage) => { (initialImageWidth >= 800 && entity.text_position) || entity.image_width < initialImageWidth ) { - elementsLabelsToRemove.push('x1'); + valuesToRemove.push('x1'); } - return elementsLabelsToRemove; + return valuesToRemove; }; export const getImageSpeedDialSizeBiggerLabelsToRemove = (entity: IImage) => { - const elementsLabelsToRemove = []; + const valuesToRemove = []; const initialImageWidth = Math.ceil(entity.image_width / +entity.image_scale); const initialImageHeight = Math.ceil(entity.image_height / +entity.image_scale); - if ( - (initialImageWidth >= 800 && entity.text_position) || - entity.image_width > initialImageWidth - ) { - elementsLabelsToRemove.push('x1'); + if ((initialImageWidth >= 800 && entity.text) || entity.image_width > initialImageWidth) { + valuesToRemove.push('x1'); } if ( initialImageWidth >= 960 || initialImageHeight >= 560 || - (initialImageWidth >= 640 && entity.text_position) + (initialImageWidth >= 640 && entity.text) ) { - elementsLabelsToRemove.push('x1.25'); + valuesToRemove.push('x1.25'); if ( initialImageWidth >= 800 || initialImageHeight >= 467 || - (initialImageWidth >= 533 && entity.text_position) + (initialImageWidth >= 533 && entity.text) ) { - elementsLabelsToRemove.push('x1.5'); + valuesToRemove.push('x1.5'); if ( initialImageWidth >= 685 || initialImageHeight >= 400 || - (initialImageWidth >= 457 && entity.text_position) + (initialImageWidth >= 457 && entity.text) ) { - elementsLabelsToRemove.push('x1.75'); + valuesToRemove.push('x1.75'); if ( initialImageWidth >= 600 || initialImageHeight >= 350 || - (initialImageWidth >= 400 && entity.text_position) + (initialImageWidth >= 400 && entity.text) ) { - elementsLabelsToRemove.push('x2'); + valuesToRemove.push('x2'); } } } } - return elementsLabelsToRemove; + return valuesToRemove; +}; + +export const scaleImage = (entityData: IImage, prevScale: string) => { + let scale = entityData.image_scale; + if (scale[0] === 'x') scale = scale.slice(1); + if (prevScale[0] === 'x') prevScale = prevScale.slice(1); + const initialWidth = Math.ceil(+entityData.image_width / +prevScale); + entityData.image_width = Math.ceil(initialWidth * +scale); + const initialHeight = Math.ceil(+entityData.image_height / +prevScale); + entityData.image_height = Math.ceil(initialHeight * +scale); + return entityData; }; diff --git a/src/app/interfaces/ui.ts b/src/app/interfaces/ui.ts index cf6b6fe107fddfeb317f3a24c9a5a165955c4e0f..4e294a91bb158284f2febcd7c0f6d23d8fd283ce 100644 --- a/src/app/interfaces/ui.ts +++ b/src/app/interfaces/ui.ts @@ -1,7 +1,8 @@ import type { TTheme } from '@/app/interfaces/environment'; -export interface IToggleButtonItem { +export interface IToggleButtonOption { label: string; + value?: string | number | boolean; textColor?: TTheme; backgroundColor?: TTheme; isLabelHidden?: boolean; diff --git a/src/app/stores/filesWebsocket.ts b/src/app/stores/filesWebsocket.ts index 79087bcf14560870c570256ab032b0d4eb6fbeb6..43e5e6bcc61b7889a25d4321d7648649d37ad6a9 100644 --- a/src/app/stores/filesWebsocket.ts +++ b/src/app/stores/filesWebsocket.ts @@ -12,7 +12,6 @@ export const useFilesWebsocketStore = defineStore('filesWebsocketStore', () => { socket.value = new WebSocket('ws://localhost:5001'); socket.value.binaryType = 'arraybuffer'; socket.value.onmessage = (response) => { - console.log('response: ', response); if (response?.data?.byteLength) { filesBuffer.value.push(response); } @@ -33,7 +32,6 @@ export const useFilesWebsocketStore = defineStore('filesWebsocketStore', () => { imageUrl.value = ''; } function sendData(data: unknown) { - console.log('data: ', data); socket.value.send(data); } return { diff --git a/src/app/stores/websocket.ts b/src/app/stores/websocket.ts index 450c42a962613f92c7d4f5a0a244ae7c81dff882..fc1bdaeb8371bd5df3fd4222e77cb159285158bb 100644 --- a/src/app/stores/websocket.ts +++ b/src/app/stores/websocket.ts @@ -29,7 +29,7 @@ export const useWebsocketStore = defineStore('websocketStore', () => { socket.value = new WebSocket('ws://localhost:5000'); socket.value.onopen = async () => { const userUuid = cookies.get('user_uuid'); - console.log('userUuid', userUuid); + // console.log('userUuid', userUuid); if (userUuid) { const getUserData = { event: 'getUser', @@ -111,13 +111,11 @@ export const useWebsocketStore = defineStore('websocketStore', () => { authorizationStore.setUserNickName(response.data.nick_name); authorizationStore.setUserData(response.data); dataStore.setPagesData(response.data.pages_uuid); - console.log('getUser response.data: ', response.data); break; } case 'getPage': { dataStore.setCurrentPageUuid(response.data.page_uuid); dataStore.setCurrentPageData(response.data); - console.log('getPage response.data: ', response.data); break; } case 'getPageEntities': { diff --git a/src/components/CreateEntityMenu.vue b/src/components/CreateEntityMenu.vue index b8293ece9bdd69953d50369f46b32a75a2bfeb80..2bb2a00642d671ee09452b624907bb191efe15c4 100644 --- a/src/components/CreateEntityMenu.vue +++ b/src/components/CreateEntityMenu.vue @@ -47,9 +47,12 @@ const addImage = async (files: FileList) => { image_buffer: buffer, entity_position: 'left', entity_title_position: 'center', + font_size: '24', + text_position: 'right', + paragraph_size: 'full', image_width: image.width, image_height: image.height, - image_scale: '1' + image_scale: 'x1' }); }; }; diff --git a/src/components/entities/settings/ImageSettings.vue b/src/components/entities/settings/ImageSettings.vue index e14ccf843bfb7ce6460d58b401880fbdbe7eee7e..da5e4ba6cb97295cd37068420f4f76e4e83eda45 100644 --- a/src/components/entities/settings/ImageSettings.vue +++ b/src/components/entities/settings/ImageSettings.vue @@ -3,7 +3,7 @@ import type { IImage } from '@/app/interfaces/entities'; import { convertThemeToColorWhiteDefault, deleteEntity, editEntity } from '@/app/helpers'; import type { TTheme } from '@/app/interfaces/environment'; import cookies from '@/app/plugins/Cookie'; -import type { IToggleButtonItem } from '@/app/interfaces/ui'; +import { useWindowSize } from '@vueuse/core'; interface Props { entityData: IImage; @@ -14,25 +14,8 @@ const entityData = computed(() => props.entityData); const newEntityData = ref({ ...entityData.value }); watch(entityData, () => (newEntityData.value = entityData.value)); const isModal = ref(false); +const { width: windowWidth } = useWindowSize(); -const addText = () => { - editEntity({ - ...entityData.value, - text: 'Text', - text_position: 'right', - font_size: entityData.value.font_size ?? '24', - paragraph_size: 'full' - }); - newEntityData.value = { ...entityData.value, text: 'Text' }; -}; -const removeText = () => { - const newState = { ...entityData.value }; - ['text', 'text_position', 'font_size', 'paragraph_size'].forEach((item) => { - newState[item] = null; - }); - editEntity({ ...newState }); - newEntityData.value = newState; -}; const changeFontSize = (newSize: '16' | '20' | '24' | '40' | '64') => { entityData.value.font_size = newSize; editEntity({ ...entityData.value, font_size: newSize }); @@ -42,135 +25,22 @@ const themeColorConverted = convertThemeToColorWhiteDefault(themeColor); const isTitle = ref(!!entityData.value.title); const isText = ref(!!entityData.value.text); const isEntityWidthFull = ref(entityData.value.paragraph_size === 'full'); - +const isModalToDeleteImage = ref(false); +const textContainerWidth = computed(() => { + if (!isEntityWidthFull.value) + return (windowWidth.value - 160 - newEntityData.value.image_width) / 2; + return windowWidth.value - 160 - newEntityData.value.image_width; +}); const maxLines = computed(() => { - if (isTitle.value) { - return Math.floor(168 / 24); + if (isText.value) { + return Math.floor(newEntityData.value.image_height / newEntityData.value.font_size); } else { - return Math.floor(240 / 24); + return 0; } }); -const entityIsTitleOptions = ref([ - { - label: 'Off', - value: false, - textStyle: 'bold' - }, - { - label: 'On', - value: true, - textStyle: 'bold' - } -]); -const entityIsTextOptions = ref([ - { - label: 'Off', - value: false, - textStyle: 'bold' - }, - { - label: 'On', - value: true, - textStyle: 'bold' - } -]); -const entityPositionOptions = ref([ - { - label: 'left', - isLabelHidden: true - }, - { - label: 'center', - isLabelHidden: true - }, - { - label: 'right', - isLabelHidden: true - } -]); -const entityTitlePositionOptions = ref([ - { - label: 'left', - isLabelHidden: true - }, - { - label: 'center', - isLabelHidden: true - }, - { - label: 'right', - isLabelHidden: true - } -]); -const entityTextPositionOptions = ref([ - { - label: 'Left', - value: 'left', - textStyle: 'bold' - }, - { - label: 'Right', - value: 'right', - textStyle: 'bold' - } -]); -const entityParagraphSizeOptions = ref([ - { - label: 'Half', - value: 'half', - textStyle: 'bold' - }, - { - label: 'Full', - value: 'full', - textStyle: 'bold' - } -]); -const imageScaleOptions = ref([ - { - label: 'x0.25', - value: 0, - color: 'var(--purple-700)' - }, - { - label: 'x0.5', - value: 1, - color: 'var(--indigo-500)' - }, - { - label: 'x0.75', - value: 2, - color: 'var(--sky-500)' - }, - { - label: 'x1', - value: 3, - color: 'var(--green-500)' - }, - { - label: 'x1.25', - value: 4, - color: 'var(--yellow-500)' - }, - { - label: 'x1.5', - value: 5, - color: 'var(--orange-500)' - }, - { - label: 'x1.75', - value: 6, - color: 'var(--red-500)' - }, - { - label: 'x2', - value: 7, - color: 'var(--red-800)' - } -]); const saveChanges = () => { const entityPosition = isEntityWidthFull.value ? 'full' : 'half'; - if (entityPosition !== entityData.value.entity_position) { + if (entityPosition !== entityData.value.paragraph_size) { newEntityData.value.paragraph_size = entityPosition; } if (isTitle.value !== !!entityData.value.title) { @@ -180,18 +50,26 @@ const saveChanges = () => { newEntityData.value.title = null; } } - if (isText.value !== !!entityData.value.title) { + if (isText.value !== !!entityData.value.text) { if (isText.value) { - newEntityData.value.title = 'Text'; + newEntityData.value.text = 'Text'; } else { - newEntityData.value.title = null; + newEntityData.value.text = null; } } - if (JSON.stringify(entityData) !== JSON.stringify(newEntityData.value)) { + if (JSON.stringify(entityData.value) !== JSON.stringify(newEntityData.value)) { emit('saveChanges', newEntityData.value); } isModal.value = false; }; +const toggleConfirmToDeleteImage = () => { + isModalToDeleteImage.value = !isModalToDeleteImage.value; +}; +const deleteImage = () => { + deleteEntity(entityData.value.entity_uuid); + isModalToDeleteImage.value = false; + isModal.value = false; +}; diff --git a/src/components/entities/settings/lists/ImageSettingsList.vue b/src/components/entities/settings/lists/ImageSettingsList.vue index 535f2a6a5730e6fbf0ed61d5aa5f66e23b5e1af4..576207c8246aefcb649d36f013ed837560636d90 100644 --- a/src/components/entities/settings/lists/ImageSettingsList.vue +++ b/src/components/entities/settings/lists/ImageSettingsList.vue @@ -3,21 +3,22 @@ import type { TTheme } from '@/app/interfaces/environment'; import { useVModels } from '@vueuse/core'; import type { IImage } from '@/app/interfaces/entities'; import ToggleButton from '@/shared/ui/ToggleButton.vue'; -import type { ISliderOption, IToggleButtonItem } from '@/app/interfaces/ui'; - +import { + imageScaleOptions, + entityIsTitleOptions, + entityIsTextOptions, + entityPositionOptions, + entityTitlePositionOptions, + entityTextPositionOptions, + isEntityWidthFullOptions +} from './options'; +import { getImageScalesToRemove, scaleImage } from '@/app/helpers/images'; interface Props { newEntityData: IImage; isTitle: boolean; isText: boolean; isEntityWidthFull: boolean; themeColor: TTheme; - entityIsTitleOptions: IToggleButtonItem[]; - entityIsTextOptions: IToggleButtonItem[]; - entityPositionOptions: IToggleButtonItem[]; - entityTitlePositionOptions: IToggleButtonItem[]; - entityParagraphSizeOptions: IToggleButtonItem[]; - entityTextPositionOptions: IToggleButtonItem[]; - imageScaleOptions: ISliderOption[]; } const props = defineProps(); const emit = defineEmits([ @@ -27,6 +28,22 @@ const emit = defineEmits([ 'update:isEntityWidthFull' ]); const { newEntityData, isTitle, isText, isEntityWidthFull } = useVModels(props, emit); +const scalesToRemove = getImageScalesToRemove(newEntityData.value); +if (scalesToRemove.length) { + imageScaleOptions.value = imageScaleOptions.value.filter( + (item) => !~scalesToRemove.indexOf(item.label) + ); + for (let i = 0; i < imageScaleOptions.value.length; i++) { + imageScaleOptions.value[i].value = i; + } +} +console.log('imageScaleOptions: ', imageScaleOptions.value); +watch( + () => newEntityData.value.image_scale, + (cur, prev) => { + newEntityData.value = scaleImage(newEntityData.value, prev); + } +);