From 512ead3543c47e87c5cd89a972c75d0cb0925374 Mon Sep 17 00:00:00 2001 From: DuckieTM Date: Tue, 18 Mar 2025 19:35:43 +0100 Subject: [PATCH] :up: Fix the Zoom / Effect and layout --- .../views/CameraWidgetShowPhotoView.tsx | 81 ++++----- .../views/editor/CameraWidgetEditorView.tsx | 171 ++++++++---------- .../furniture/FurnitureExternalImageView.tsx | 29 ++- src/css/widgets/FurnitureWidgets.css | 11 +- 4 files changed, 143 insertions(+), 149 deletions(-) diff --git a/src/components/camera/views/CameraWidgetShowPhotoView.tsx b/src/components/camera/views/CameraWidgetShowPhotoView.tsx index 08d3a29..212bee3 100644 --- a/src/components/camera/views/CameraWidgetShowPhotoView.tsx +++ b/src/components/camera/views/CameraWidgetShowPhotoView.tsx @@ -1,71 +1,68 @@ +import { GetRoomEngine, RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; import { FaArrowLeft, FaArrowRight } from 'react-icons/fa'; import { GetUserProfile, IPhotoData, LocalizeText } from '../../../api'; import { Flex, Grid, Text } from '../../../common'; -export interface CameraWidgetShowPhotoViewProps -{ +export interface CameraWidgetShowPhotoViewProps { currentIndex: number; currentPhotos: IPhotoData[]; + onClick?: () => void; } -export const CameraWidgetShowPhotoView: FC = props => -{ - const { currentIndex = -1, currentPhotos = null } = props; - const [ imageIndex, setImageIndex ] = useState(0); +export const CameraWidgetShowPhotoView: FC = props => { + const { currentIndex = -1, currentPhotos = null, onClick = null } = props; + const [imageIndex, setImageIndex] = useState(0); - const currentImage = (currentPhotos && currentPhotos.length) ? currentPhotos[imageIndex] : null; - - const next = () => - { - setImageIndex(prevValue => - { - let newIndex = (prevValue + 1); - - if(newIndex >= currentPhotos.length) newIndex = 0; + const currentImage = currentPhotos && currentPhotos.length ? currentPhotos[imageIndex] : null; + const next = () => { + setImageIndex(prevValue => { + let newIndex = prevValue + 1; + if (newIndex >= currentPhotos.length) newIndex = 0; return newIndex; }); }; - const previous = () => - { - setImageIndex(prevValue => - { - let newIndex = (prevValue - 1); - - if(newIndex < 0) newIndex = (currentPhotos.length - 1); - + const previous = () => { + setImageIndex(prevValue => { + let newIndex = prevValue - 1; + if (newIndex < 0) newIndex = currentPhotos.length - 1; return newIndex; }); }; - useEffect(() => - { + useEffect(() => { setImageIndex(currentIndex); - }, [ currentIndex ]); + }, [currentIndex]); - if(!currentImage) return null; + if (!currentImage) return null; + + const getUserData = (roomId: number, objectId: number, type: string): number | string => + { + const roomObject = GetRoomEngine().getRoomObject(roomId, objectId, RoomObjectCategory.WALL); + if (!roomObject) return; + return type == 'username' ? roomObject.model.getValue(RoomObjectVariable.FURNITURE_OWNER_NAME) : roomObject.model.getValue(RoomObjectVariable.FURNITURE_OWNER_ID); + } return ( - - - { !currentImage.w && - { LocalizeText('camera.loading') } } + + + {!currentImage.w && {LocalizeText('camera.loading')}} - { currentImage.m && currentImage.m.length && - { currentImage.m } } -
- { (currentImage.n || '') } - { new Date(currentImage.t * 1000).toLocaleDateString() } + {currentImage.m && currentImage.m.length && {currentImage.m}} +
+ {currentImage.n || ''} + GetUserProfile(Number(getUserData(currentImage.s, Number(currentImage.u), 'id')))}> { getUserData(currentImage.s, Number(currentImage.u), 'username') } + GetUserProfile(currentImage.oi)}>{currentImage.o} + {new Date(currentImage.t * 1000).toLocaleDateString()}
- { (currentPhotos.length > 1) && + {currentPhotos.length > 1 && ( - - GetUserProfile(currentImage.oi) }>{ currentImage.o } - + + - } + )} ); -}; +}; \ No newline at end of file diff --git a/src/components/camera/views/editor/CameraWidgetEditorView.tsx b/src/components/camera/views/editor/CameraWidgetEditorView.tsx index 68a4399..75ae074 100644 --- a/src/components/camera/views/editor/CameraWidgetEditorView.tsx +++ b/src/components/camera/views/editor/CameraWidgetEditorView.tsx @@ -3,11 +3,10 @@ import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { FaSave, FaSearchMinus, FaSearchPlus, FaTrash } from 'react-icons/fa'; import ReactSlider from 'react-slider'; import { CameraEditorTabs, CameraPicture, CameraPictureThumbnail, LocalizeText } from '../../../../api'; -import { Button, ButtonGroup, Column, Flex, Grid, LayoutImage, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView, Text } from '../../../../common'; +import { Button, Column, Flex, Grid, LayoutImage, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView, Text } from '../../../../common'; import { CameraWidgetEffectListView } from './effect-list'; -export interface CameraWidgetEditorViewProps -{ +export interface CameraWidgetEditorViewProps { picture: CameraPicture; availableEffects: IRoomCameraWidgetEffect[]; myLevel: number; @@ -18,8 +17,7 @@ export interface CameraWidgetEditorViewProps const TABS: string[] = [ CameraEditorTabs.COLORMATRIX, CameraEditorTabs.COMPOSITE ]; -export const CameraWidgetEditorView: FC = props => -{ +export const CameraWidgetEditorView: FC = props => { const { picture = null, availableEffects = null, myLevel = 1, onClose = null, onCancel = null, onCheckout = null } = props; const [ currentTab, setCurrentTab ] = useState(TABS[0]); const [ selectedEffectName, setSelectedEffectName ] = useState(null); @@ -29,66 +27,46 @@ export const CameraWidgetEditorView: FC = props => const [ currentPictureUrl, setCurrentPictureUrl ] = useState(''); const isBusy = useRef(false); - const getColorMatrixEffects = useMemo(() => - { + const getColorMatrixEffects = useMemo(() => { return availableEffects.filter(effect => effect.colorMatrix); }, [ availableEffects ]); - const getCompositeEffects = useMemo(() => - { + const getCompositeEffects = useMemo(() => { return availableEffects.filter(effect => effect.texture); }, [ availableEffects ]); - const getEffectList = useCallback(() => - { - if(currentTab === CameraEditorTabs.COLORMATRIX) - { - return getColorMatrixEffects; - } - - return getCompositeEffects; + const getEffectList = useCallback(() => { + return currentTab === CameraEditorTabs.COLORMATRIX ? getColorMatrixEffects : getCompositeEffects; }, [ currentTab, getColorMatrixEffects, getCompositeEffects ]); - const getSelectedEffectIndex = useCallback((name: string) => - { - if(!name || !name.length || !selectedEffects || !selectedEffects.length) return -1; - - return selectedEffects.findIndex(effect => (effect.effect.name === name)); + const getSelectedEffectIndex = useCallback((name: string) => { + if (!name || !name.length || !selectedEffects || !selectedEffects.length) return -1; + return selectedEffects.findIndex(effect => effect.effect.name === name); }, [ selectedEffects ]); - const getCurrentEffectIndex = useMemo(() => - { + const getCurrentEffectIndex = useMemo(() => { return getSelectedEffectIndex(selectedEffectName); }, [ selectedEffectName, getSelectedEffectIndex ]); - const getCurrentEffect = useMemo(() => - { - if(!selectedEffectName) return null; - - return (selectedEffects[getCurrentEffectIndex] || null); + const getCurrentEffect = useMemo(() => { + if (!selectedEffectName) return null; + return selectedEffects[getCurrentEffectIndex] || null; }, [ selectedEffectName, getCurrentEffectIndex, selectedEffects ]); - const setSelectedEffectAlpha = useCallback((alpha: number) => - { + const setSelectedEffectAlpha = useCallback((alpha: number) => { const index = getCurrentEffectIndex; + if (index === -1) return; - if(index === -1) return; - - setSelectedEffects(prevValue => - { + setSelectedEffects(prevValue => { const clone = [ ...prevValue ]; const currentEffect = clone[index]; - - clone[getCurrentEffectIndex] = new RoomCameraWidgetSelectedEffect(currentEffect.effect, alpha); - + clone[index] = new RoomCameraWidgetSelectedEffect(currentEffect.effect, alpha); return clone; }); - }, [ getCurrentEffectIndex, setSelectedEffects ]); + }, [ getCurrentEffectIndex ]); - const processAction = useCallback((type: string, effectName: string = null) => - { - switch(type) - { + const processAction = useCallback((type: string, effectName: string = null) => { + switch (type) { case 'close': onClose(); return; @@ -102,37 +80,27 @@ export const CameraWidgetEditorView: FC = props => setCurrentTab(String(effectName)); return; case 'select_effect': { - let existingIndex = getSelectedEffectIndex(effectName); + const existingIndex = getSelectedEffectIndex(effectName); + if (existingIndex >= 0) return; - if(existingIndex >= 0) return; - - const effect = availableEffects.find(effect => (effect.name === effectName)); - - if(!effect) return; - - setSelectedEffects(prevValue => - { - return [ ...prevValue, new RoomCameraWidgetSelectedEffect(effect, 1) ]; - }); + const effect = availableEffects.find(effect => effect.name === effectName); + if (!effect) return; + setSelectedEffects(prevValue => [ ...prevValue, new RoomCameraWidgetSelectedEffect(effect, 1) ]); setSelectedEffectName(effect.name); return; } case 'remove_effect': { - let existingIndex = getSelectedEffectIndex(effectName); + const existingIndex = getSelectedEffectIndex(effectName); + if (existingIndex === -1) return; - if(existingIndex === -1) return; - - setSelectedEffects(prevValue => - { + setSelectedEffects(prevValue => { const clone = [ ...prevValue ]; - clone.splice(existingIndex, 1); - return clone; }); - if(selectedEffectName === effectName) setSelectedEffectName(null); + if (selectedEffectName === effectName) setSelectedEffectName(null); return; } case 'clear_effects': @@ -140,78 +108,90 @@ export const CameraWidgetEditorView: FC = props => setSelectedEffects([]); return; case 'download': { - (async () => - { + (async () => { const image = new Image(); - image.src = currentPictureUrl; - const newWindow = window.open(''); newWindow.document.write(image.outerHTML); })(); return; } case 'zoom': - setIsZoomed(!isZoomed); + setIsZoomed(prev => !prev); return; } - }, [ isZoomed, availableEffects, selectedEffectName, currentPictureUrl, getSelectedEffectIndex, onCancel, onCheckout, onClose, setIsZoomed, setSelectedEffects ]); - - useEffect(() => - { - const processThumbnails = async () => - { - const renderedEffects = await Promise.all(availableEffects.map(effect => GetRoomCameraWidgetManager().applyEffects(picture.texture, [ new RoomCameraWidgetSelectedEffect(effect, 1) ], false))); + }, [ availableEffects, selectedEffectName, currentPictureUrl, getSelectedEffectIndex, onCancel, onCheckout, onClose ]); + useEffect(() => { + const processThumbnails = async () => { + const renderedEffects = await Promise.all( + availableEffects.map(effect => + GetRoomCameraWidgetManager().applyEffects(picture.texture, [ new RoomCameraWidgetSelectedEffect(effect, 1) ], false) + ) + ); setEffectsThumbnails(renderedEffects.map((image, index) => new CameraPictureThumbnail(availableEffects[index].name, image.src))); }; - processThumbnails(); }, [ picture, availableEffects ]); - useEffect(() => - { + useEffect(() => { GetRoomCameraWidgetManager() - .applyEffects(picture.texture, selectedEffects, isZoomed) - .then(imageElement => - { + .applyEffects(picture.texture, selectedEffects, false) // Remove isZoomed from here + .then(imageElement => { setCurrentPictureUrl(imageElement.src); }) - .catch(error => - { + .catch(error => { NitroLogger.error('Failed to apply effects to picture', error); }); - }, [ picture, selectedEffects, isZoomed ]); + }, [ picture, selectedEffects ]); // Remove isZoomed from dependency array return ( processAction('close') } /> - { TABS.map(tab => - { - return processAction('change_tab', tab) }>; - }) } + { TABS.map(tab => ( + processAction('change_tab', tab) }> + + + )) } - + - - { selectedEffectName && + + { selectedEffectName && ( { LocalizeText('camera.effect.name.' + selectedEffectName) } setSelectedEffectAlpha(event) } - renderThumb={ ({ key, ...props }, state) =>
{ state.valueNow }
} /> -
} + renderThumb={ ({ key, ...props }, state) =>
{ state.valueNow }
} + /> +
+ ) }
@@ -222,8 +202,7 @@ export const CameraWidgetEditorView: FC = props =>
@@ -240,4 +219,4 @@ export const CameraWidgetEditorView: FC = props => ); -}; +}; \ No newline at end of file diff --git a/src/components/room/widgets/furniture/FurnitureExternalImageView.tsx b/src/components/room/widgets/furniture/FurnitureExternalImageView.tsx index 5e8d4eb..7fe070c 100644 --- a/src/components/room/widgets/furniture/FurnitureExternalImageView.tsx +++ b/src/components/room/widgets/furniture/FurnitureExternalImageView.tsx @@ -1,23 +1,34 @@ -import { GetSessionDataManager } from '@nitrots/nitro-renderer'; import { FC } from 'react'; -import { ReportType } from '../../../../api'; +import { GetConfigurationValue, LocalizeText, ReportType } from '../../../../api'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common'; import { useFurnitureExternalImageWidget, useHelp } from '../../../../hooks'; import { CameraWidgetShowPhotoView } from '../../../camera/views/CameraWidgetShowPhotoView'; -export const FurnitureExternalImageView: FC<{}> = props => -{ +export const FurnitureExternalImageView: FC<{}> = props => { const { objectId = -1, currentPhotoIndex = -1, currentPhotos = null, onClose = null } = useFurnitureExternalImageWidget(); const { report = null } = useHelp(); - if((objectId === -1) || (currentPhotoIndex === -1)) return null; + if (objectId === -1 || currentPhotoIndex === -1) return null; + + const handleOpenFullPhoto = () => { + const photoUrl = currentPhotos[currentPhotoIndex].w.replace('_small.png', '.png'); + if (photoUrl) { + console.log("Opened photo URL:", photoUrl); + window.open(photoUrl, '_blank'); + } + }; return ( - - report(ReportType.PHOTO, { extraData: currentPhotos[currentPhotoIndex].w, roomId: currentPhotos[currentPhotoIndex].s, reportedUserId: GetSessionDataManager().userId, roomObjectId: Number(currentPhotos[currentPhotoIndex].u) }) } /> + + report(ReportType.PHOTO, { extraData: currentPhotos[currentPhotoIndex].w, roomId: currentPhotos[currentPhotoIndex].s, reportedUserId: GetSessionDataManager().userId, roomObjectId: Number(currentPhotos[currentPhotoIndex].u) })} + /> - + ); -}; +}; \ No newline at end of file diff --git a/src/css/widgets/FurnitureWidgets.css b/src/css/widgets/FurnitureWidgets.css index 54ba0e5..1f6b799 100644 --- a/src/css/widgets/FurnitureWidgets.css +++ b/src/css/widgets/FurnitureWidgets.css @@ -2,6 +2,14 @@ pointer-events: none; } +.no-resize { + resize: none !important; + min-width: 340px !important; + max-width: 340px !important; + min-height: 430px !important; + max-height: 430px !important; +} + .nitro-widget-custom-stack-height { width: 275px; height: 220px; @@ -53,7 +61,7 @@ width: 320px; height: 320px; } - + .picture-preview-buttons { display: flex; align-items: center; @@ -64,7 +72,6 @@ .picture-preview-buttons-previous, .picture-preview-buttons-next { color: #222; - background-color: white; padding: 10px; border-radius: 50%; }