diff --git a/package.json b/package.json index c17108a..83a4609 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dompurify": "^3.0.11", "emoji-mart": "^5.5.2", "emoji-toolkit": "8.0.0", + "framer-motion": "^11.2.12", "react": "^18.2.0", "react-bootstrap": "^2.7.2", "react-dom": "^18.2.0", diff --git a/src/App.tsx b/src/App.tsx index 072b05d..e242393 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,8 @@ import { ConfigurationEvent, GetAssetManager, HabboWebTools, LegacyExternalInterface, Nitro, NitroCommunicationDemoEvent, NitroConfiguration, NitroEvent, NitroLocalizationEvent, NitroVersion, RoomEngineEvent } from '@nitrots/nitro-renderer'; +import { AnimatePresence, motion } from 'framer-motion'; +import { Base } from './common'; import { FC, useCallback, useEffect, useState } from 'react'; import { GetCommunication, GetConfiguration, GetNitroInstance, GetUIVersion } from './api'; -import { Base, TransitionAnimation, TransitionAnimationTypes } from './common'; import { LoadingView } from './components/loading/LoadingView'; import { MainView } from './components/main/MainView'; import { useConfigurationEvent, useLocalizationEvent, useMainEvent, useRoomEngineEvent } from './hooks'; @@ -132,9 +133,12 @@ export const App: FC<{}> = props => { (!isReady || isError) && } - - - + + { isReady && ( + + + )} + ); diff --git a/src/common/index.ts b/src/common/index.ts index bc70d55..7488300 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -18,6 +18,5 @@ export * from './layout'; export * from './layout/limited-edition'; export * from "./Slider"; export * from './Text'; -export * from './transitions'; export * from './types'; export * from './utils'; diff --git a/src/common/layout/LayoutNotificationBubbleView.tsx b/src/common/layout/LayoutNotificationBubbleView.tsx index a482166..b85595a 100644 --- a/src/common/layout/LayoutNotificationBubbleView.tsx +++ b/src/common/layout/LayoutNotificationBubbleView.tsx @@ -1,6 +1,6 @@ +import { AnimatePresence, motion } from 'framer-motion'; import { FC, useEffect, useMemo, useState } from 'react'; import { Flex, FlexProps } from '..'; -import { TransitionAnimation, TransitionAnimationTypes } from '../transitions'; export interface LayoutNotificationBubbleViewProps extends FlexProps { @@ -45,8 +45,14 @@ export const LayoutNotificationBubbleView: FC }, [ fadesOut, timeoutMs, onClose ]); return ( - - - + + { isVisible && + + + } + ); } diff --git a/src/common/transitions/TransitionAnimation.tsx b/src/common/transitions/TransitionAnimation.tsx deleted file mode 100644 index 6eefd2d..0000000 --- a/src/common/transitions/TransitionAnimation.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { FC, ReactNode, useEffect, useState } from 'react'; -import { Transition } from 'react-transition-group'; -import { getTransitionAnimationStyle } from './TransitionAnimationStyles'; - -interface TransitionAnimationProps -{ - type: string; - inProp: boolean; - timeout?: number; - className?: string; - children?: ReactNode; -} - -export const TransitionAnimation: FC = props => -{ - const { type = null, inProp = false, timeout = 300, className = null, children = null } = props; - - const [ isChildrenVisible, setChildrenVisible ] = useState(false); - - useEffect(() => - { - let timeoutData: ReturnType = null; - - if(inProp) - { - setChildrenVisible(true); - } - else - { - timeoutData = setTimeout(() => - { - setChildrenVisible(false); - clearTimeout(timeout); - }, timeout); - } - - return () => - { - if(timeoutData) clearTimeout(timeoutData); - } - }, [ inProp, timeout ]); - - return ( - - { state => ( - - { isChildrenVisible && children } - - ) } - - ); -} diff --git a/src/common/transitions/TransitionAnimationStyles.ts b/src/common/transitions/TransitionAnimationStyles.ts deleted file mode 100644 index 0d512d0..0000000 --- a/src/common/transitions/TransitionAnimationStyles.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { CSSProperties } from 'react'; -import { TransitionStatus } from 'react-transition-group'; -import { ENTERING, EXITING } from 'react-transition-group/Transition'; -import { TransitionAnimationTypes } from './TransitionAnimationTypes'; - -export function getTransitionAnimationStyle(type: string, transition: TransitionStatus, timeout: number = 300): Partial -{ - switch(type) - { - case TransitionAnimationTypes.BOUNCE: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'bounceIn', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'bounceOut', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.SLIDE_LEFT: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'slideInLeft', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'slideOutLeft', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.SLIDE_RIGHT: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'slideInRight', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'slideOutRight', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.FLIP_X: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'flipInX', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'flipOutX', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.FADE_UP: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'fadeInUp', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'fadeOutDown', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.FADE_IN: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'fadeIn', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'fadeOut', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.FADE_DOWN: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'fadeInDown', - animationDuration: `${ timeout }ms` - } - case EXITING: - return { - animationName: 'fadeOutUp', - animationDuration: `${ timeout }ms` - } - } - case TransitionAnimationTypes.HEAD_SHAKE: - switch(transition) - { - default: - return {} - case ENTERING: - return { - animationName: 'headShake', - animationDuration: `${ timeout }ms` - } - } - } - - return null; -} diff --git a/src/common/transitions/TransitionAnimationTypes.ts b/src/common/transitions/TransitionAnimationTypes.ts deleted file mode 100644 index 4ecc23b..0000000 --- a/src/common/transitions/TransitionAnimationTypes.ts +++ /dev/null @@ -1,11 +0,0 @@ -export class TransitionAnimationTypes -{ - public static BOUNCE: string = 'bounce'; - public static SLIDE_LEFT: string = 'slideLeft'; - public static SLIDE_RIGHT: string = 'slideRight'; - public static FLIP_X: string = 'flipX'; - public static FADE_IN: string = 'fadeIn'; - public static FADE_DOWN: string = 'fadeDown'; - public static FADE_UP: string = 'fadeUp'; - public static HEAD_SHAKE: string = 'headShake'; -} diff --git a/src/common/transitions/index.ts b/src/common/transitions/index.ts deleted file mode 100644 index 283a005..0000000 --- a/src/common/transitions/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './TransitionAnimation'; -export * from './TransitionAnimationStyles'; -export * from './TransitionAnimationTypes'; diff --git a/src/components/main/MainView.tsx b/src/components/main/MainView.tsx index 97ae2cc..c33f40b 100644 --- a/src/components/main/MainView.tsx +++ b/src/components/main/MainView.tsx @@ -1,7 +1,8 @@ import { HabboWebTools, ILinkEventTracker, RoomSessionEvent } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; import { AddEventLinkTracker, GetCommunication, RemoveLinkEventTracker } from '../../api'; -import { Base, TransitionAnimation, TransitionAnimationTypes } from '../../common'; +import { AnimatePresence, motion } from 'framer-motion'; +import { Base } from '../../common'; import { useRoomSessionManagerEvent } from '../../hooks'; import { AchievementsView } from '../achievements/AchievementsView'; import { AvatarEditorView } from '../avatar-editor/AvatarEditorView'; @@ -83,9 +84,15 @@ export const MainView: FC<{}> = props => return ( - - - + + { landingViewVisible && + + + } + diff --git a/src/components/room/RoomView.tsx b/src/components/room/RoomView.tsx index b1714d3..707990d 100644 --- a/src/components/room/RoomView.tsx +++ b/src/components/room/RoomView.tsx @@ -1,3 +1,5 @@ +import { RoomSession } from '@nitrots/nitro-renderer'; +import { AnimatePresence, motion } from 'framer-motion'; import { FC, useEffect, useRef } from 'react'; import { DispatchMouseEvent, DispatchTouchEvent, GetNitroInstance } from '../../api'; import { Base } from '../../common'; @@ -12,6 +14,8 @@ export const RoomView: FC<{}> = props => useEffect(() => { + if(!roomSession) return; + const canvas = GetNitroInstance().application.renderer.view; if(!canvas) return; @@ -31,15 +35,24 @@ export const RoomView: FC<{}> = props => if(!element) return; element.appendChild(canvas); - }, []); + }, [ roomSession ]); return ( - - { roomSession && - <> - - { roomSession.isSpectator && } - > } - + + { + + + { roomSession instanceof RoomSession && + <> + + { roomSession.isSpectator && } + > } + + + } + ); -} +}; diff --git a/src/components/room/widgets/RoomWidgets.scss b/src/components/room/widgets/RoomWidgets.scss index abd70d6..6dc55ad 100644 --- a/src/components/room/widgets/RoomWidgets.scss +++ b/src/components/room/widgets/RoomWidgets.scss @@ -1,7 +1,9 @@ .nitro-room-tools-container { position: absolute; bottom: $toolbar-height + 25px; - left: 0; + left: 0px; + display: flex; // Lay out children side by side + align-items: flex-start; // Align items to the top .nitro-room-tools { background: #212131; @@ -9,13 +11,13 @@ border-top-right-radius: $border-radius; border-bottom-right-radius: $border-radius; transition: all .2s ease; - z-index: 71; + z-index: 2; margin-left: -20px; .list-group-item { background: transparent; padding: 3px 0px; - color: $white; + color: #FFF; border-color: rgba($black, 0.3); cursor: pointer; @@ -46,13 +48,20 @@ } } + .nitro-room-tools-side-container { + display: flex; + flex-direction: column; // Stack children vertically + margin-left: 10px; // Space between nitro-room-tools and side container + gap: 10px; // Space between history and info + } + .nitro-room-history { background: #212131; box-shadow: inset 0px 5px lighten(rgba($dark, .6), 2.5), inset 0 -4px darken(rgba($dark, .6), 4); transition: all .2s ease; width: 150px; overflow: hidden; - z-index: 3; + z-index: 1; } .nitro-room-tools-info { diff --git a/src/components/room/widgets/furniture/FurnitureCraftingView.tsx b/src/components/room/widgets/furniture/FurnitureCraftingView.tsx index 88cf5a2..3e7ca16 100644 --- a/src/components/room/widgets/furniture/FurnitureCraftingView.tsx +++ b/src/components/room/widgets/furniture/FurnitureCraftingView.tsx @@ -12,9 +12,11 @@ export const FurnitureCraftingView: FC<{}> = props => const isOwner = useMemo(() => { + if(!roomSession) return false; + const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, objectId, RoomObjectCategory.FLOOR); return IsOwnerOfFurniture(roomObject); - }, [ objectId, roomSession.roomId ]); + }, [ objectId, roomSession ]); const canCraft = useMemo(() => { diff --git a/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx b/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx index 690875f..7abe6a8 100644 --- a/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx +++ b/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx @@ -1,12 +1,13 @@ import { GetGuestRoomResultEvent, NavigatorSearchComposer, RateFlatMessageComposer, RoomDataParser } from '@nitrots/nitro-renderer'; +import { AnimatePresence, motion } from 'framer-motion'; import { FC, useEffect, useState } from 'react'; import { CreateLinkEvent, GetRoomEngine, LocalizeText, SendMessageComposer, SetLocalStorage, TryVisitRoom } from '../../../../api'; -import { Base, Column, Flex, Text, TransitionAnimation, TransitionAnimationTypes, classNames } from '../../../../common'; +import { Base, Column, Flex, Text, classNames } from '../../../../common'; import { useMessageEvent, useNavigator, useRoom } from '../../../../hooks'; export const RoomToolsWidgetView: FC<{}> = props => { - const [ areBubblesMuted, setAreBubblesMuted ] = useState(false); + const [ areBubblesMuted, setAreBubblesMuted ] = useState(false); const [ isZoomedIn, setIsZoomedIn ] = useState(false); const [ roomName, setRoomName ] = useState(null); const [ roomOwner, setRoomOwner ] = useState(null); @@ -17,8 +18,8 @@ export const RoomToolsWidgetView: FC<{}> = props => const [ roomHistory, setRoomHistory ] = useState<{ roomId: number, roomName: string }[]>([]); const { navigatorData = null } = useNavigator(); const { roomSession = null } = useRoom(); - - useEffect(() => { if (!roomName) { setRoomName(LocalizeText('landing.view.generic.welcome.first_login')); } }, [roomName]); + + useEffect(() => { if (!roomName) { setRoomName(LocalizeText('landing.view.generic.welcome.first_login')); } }, [roomName]); const handleToolClick = (action: string, value?: string) => { @@ -31,35 +32,32 @@ export const RoomToolsWidgetView: FC<{}> = props => setIsZoomedIn(prevValue => { let scale = GetRoomEngine().getRoomInstanceRenderingCanvasScale(roomSession.roomId, 1); - if(!prevValue) scale /= 2; else scale *= 2; - GetRoomEngine().setRoomInstanceRenderingCanvasScale(roomSession.roomId, 1, scale); - return !prevValue; }); return; case 'chat_history': CreateLinkEvent('chat-history/toggle'); return; - case 'hiddenbubbles': - CreateLinkEvent('nitrobubblehidden/toggle'); - const bubbleElement = document.getElementById('bubble'); - if (bubbleElement) { - bubbleElement.classList.toggle('icon-chat-disablebubble'); - } - const hiddenbubblesTextElement = document.getElementById('hiddenbubblesText'); - if (hiddenbubblesTextElement) { - const newText = areBubblesMuted ? LocalizeText('room.unmute.button.text') : LocalizeText('room.mute.button.text'); - hiddenbubblesTextElement.innerText = newText; - } - setAreBubblesMuted(!areBubblesMuted); - const bubbleIcon = document.getElementById('bubbleIcon'); - if (bubbleIcon) { - bubbleIcon.classList.toggle('icon-chat-disablebubble'); - } - return; + case 'hiddenbubbles': + CreateLinkEvent('nitrobubblehidden/toggle'); + const bubbleElement = document.getElementById('bubble'); + if (bubbleElement) { + bubbleElement.classList.toggle('icon-chat-disablebubble'); + } + const hiddenbubblesTextElement = document.getElementById('hiddenbubblesText'); + if (hiddenbubblesTextElement) { + const newText = areBubblesMuted ? LocalizeText('room.unmute.button.text') : LocalizeText('room.mute.button.text'); + hiddenbubblesTextElement.innerText = newText; + } + setAreBubblesMuted(!areBubblesMuted); + const bubbleIcon = document.getElementById('bubbleIcon'); + if (bubbleIcon) { + bubbleIcon.classList.toggle('icon-chat-disablebubble'); + } + return; case 'like_room': SendMessageComposer(new RateFlatMessageComposer(1)); return; @@ -85,13 +83,9 @@ export const RoomToolsWidgetView: FC<{}> = props => const onChangeRoomHistory = (roomId: number, roomName: string) => { let newStorage = JSON.parse(window.localStorage.getItem('nitro.room.history')); - if (newStorage && newStorage.filter( (room: RoomDataParser) => room.roomId === roomId ).length > 0) return; - if (newStorage && newStorage.length >= 10) newStorage.shift(); - const newData = !newStorage ? [ { roomId: roomId, roomName: roomName } ] : [ ...newStorage, { roomId: roomId, roomName: roomName } ]; - setRoomHistory(newData); return SetLocalStorage('nitro.room.history', newData ); } @@ -99,13 +93,11 @@ export const RoomToolsWidgetView: FC<{}> = props => useMessageEvent(GetGuestRoomResultEvent, event => { const parser = event.getParser(); - if(!parser.roomEnter || (parser.data.roomId !== roomSession.roomId)) return; if(roomName !== parser.data.roomName) setRoomName(parser.data.roomName); if(roomOwner !== parser.data.ownerName) setRoomOwner(parser.data.ownerName); if(roomTags !== parser.data.tags) setRoomTags(parser.data.tags); - onChangeRoomHistory(parser.data.roomId, parser.data.roomName); }); @@ -115,21 +107,14 @@ export const RoomToolsWidgetView: FC<{}> = props => { if (JSON.parse(window.localStorage.getItem('nitro.room.history'))) window.localStorage.removeItem('nitro.room.history'); }; - window.addEventListener('beforeunload', handleTabClose); - - return () => - { - window.removeEventListener('beforeunload', handleTabClose); - }; + return () => window.removeEventListener('beforeunload', handleTabClose); }, []); useEffect(() => { setIsOpen(true); - const timeout = setTimeout(() => setIsOpen(false), 5000); - return () => clearTimeout(timeout); }, [ roomName, roomOwner, roomTags, show ]); @@ -154,7 +139,7 @@ export const RoomToolsWidgetView: FC<{}> = props => { navigatorData.canRate && handleToolClick('like_room') } className="icon icon-like-room" /> } handleToolClick('toggle_room_link') } className="icon icon-room-link" /> - handleToolClick('hiddenbubbles') } className={`icon ${areBubblesMuted ? 'icon-chat-disablebubble' : 'icon-chat-enablebubble'}`} /> + handleToolClick('hiddenbubbles') } className={`icon ${areBubblesMuted ? 'icon-chat-disablebubble' : 'icon-chat-enablebubble'}`} /> @@ -164,7 +149,8 @@ export const RoomToolsWidgetView: FC<{}> = props => handleToolClick('zoom') }>{ LocalizeText('room.zoom.button.text') } - handleToolClick('chat_history') }>{ LocalizeText('room.chathistory.button.text') } + handleToolClick('chat_history') }>{ LocalizeText('room.chathistory.button.text') } + { navigatorData.canRate && handleToolClick('like_room') }>{ LocalizeText('room.like.button.text') } @@ -172,7 +158,7 @@ export const RoomToolsWidgetView: FC<{}> = props => handleToolClick('toggle_room_link') }>{ LocalizeText('navigator.embed.caption') } - + handleToolClick('hiddenbubbles')}> {areBubblesMuted ? LocalizeText('room.unmute.button.text') : LocalizeText('room.mute.button.text')} @@ -183,34 +169,50 @@ export const RoomToolsWidgetView: FC<{}> = props => 1 && roomHistory[roomHistory.length - 1]?.roomId !== navigatorData.currentRoomId } title={ LocalizeText('room.history.button.forward.tooltip') } className={ `icon ${ (roomHistory?.length === 0 || roomHistory[roomHistory.length - 1]?.roomId === navigatorData.currentRoomId) ? 'icon-room-history-next-disabled' : 'icon-room-history-next-enabled' }` } onClick={ () => (roomHistory?.length === 0 || roomHistory[roomHistory.length - 1]?.roomId === navigatorData.currentRoomId) ? null : handleToolClick('room_history_next') } /> - - - - - - { (roomHistory.length > 0) && roomHistory.map(history => - { - return TryVisitRoom(history.roomId) }>{ history.roomName }; - }) } + + + + { isOpenHistory && ( + + + + { (roomHistory.length > 0) && roomHistory.map(history => + TryVisitRoom(history.roomId) }>{ history.roomName } + ) } + + - - - + + )} + + + + { isOpen && ( + + + + {roomName} + {roomOwner} + + {roomTags && roomTags.length > 0 ? ( + + {roomTags.map((tag, index) => ( + handleToolClick('navigator_search_tag', tag)}> + #{tag} + + ))} + + ) : ( + { LocalizeText('navigator.notagsfound') } + )} + + + + )} + - - - - - {roomName} {roomOwner} - {roomTags && roomTags.length > 0 ? ( - {roomTags.map((tag, index) => ( handleToolClick('navigator_search_tag', tag)} > #{tag} ))} - ) : ( { LocalizeText('navigator.notagsfound') } )} - - - - > - ) } + )} ); } \ No newline at end of file diff --git a/src/components/toolbar/ToolbarMeView.tsx b/src/components/toolbar/ToolbarMeView.tsx index be2075d..7dcafda 100644 --- a/src/components/toolbar/ToolbarMeView.tsx +++ b/src/components/toolbar/ToolbarMeView.tsx @@ -1,17 +1,14 @@ import { MouseEventType, RoomObjectCategory } from '@nitrots/nitro-renderer'; import { Dispatch, FC, PropsWithChildren, SetStateAction, useEffect, useRef } from 'react'; -import { CreateLinkEvent, DispatchUiEvent, GetConfiguration, GetRoomEngine, GetRoomSession, GetSessionDataManager, GetUserProfile } from '../../api'; +import { CreateLinkEvent, DispatchUiEvent, GetConfiguration, GetRoomEngine, GetRoomSession, GetUserProfile } from '../../api'; import { Base, Flex, LayoutItemCountView } from '../../common'; import { GuideToolEvent } from '../../events'; -interface ToolbarMeViewProps -{ +export const ToolbarMeView: FC>; -} - -export const ToolbarMeView: FC> = props => +}>> = props => { const { useGuideTool = false, unseenAchievementCount = 0, setMeExpanded = null, children = null, ...rest } = props; const elementRef = useRef(); @@ -19,7 +16,6 @@ export const ToolbarMeView: FC> = props => useEffect(() => { const roomSession = GetRoomSession(); - if(!roomSession) return; GetRoomEngine().selectRoomObject(roomSession.roomId, roomSession.ownRoomIndex, RoomObjectCategory.UNIT); @@ -27,15 +23,25 @@ export const ToolbarMeView: FC> = props => useEffect(() => { - const onClick = (event: MouseEvent) => setMeExpanded(false); + const handleClickOutside = (event: MouseEvent) => + { + if (elementRef.current && !elementRef.current.contains(event.target as Node)) + { + setMeExpanded(false); + } + }; - document.addEventListener('click', onClick); - - return () => document.removeEventListener(MouseEventType.MOUSE_CLICK, onClick); + document.addEventListener('click', handleClickOutside); + return () => document.removeEventListener('click', handleClickOutside); }, [ setMeExpanded ]); + const handleMenuClick = (event: React.MouseEvent) => + { + event.stopPropagation(); + }; + return ( - + { (GetConfiguration('guides.enabled') && useGuideTool) && DispatchUiEvent(new GuideToolEvent(GuideToolEvent.TOGGLE_GUIDE_TOOL)) } /> } CreateLinkEvent('achievements/toggle') }> @@ -49,4 +55,4 @@ export const ToolbarMeView: FC> = props => { children } ); -} +} \ No newline at end of file diff --git a/src/components/toolbar/ToolbarView.scss b/src/components/toolbar/ToolbarView.scss index 2a356dc..222f2af 100644 --- a/src/components/toolbar/ToolbarView.scss +++ b/src/components/toolbar/ToolbarView.scss @@ -70,7 +70,7 @@ .nitro-toolbar-me { position: absolute; - bottom: 68px; + bottom: 35px; left: 15px; z-index: $toolbar-memenu-zindex; //background: rgba(20, 20, 20, .95); @@ -87,7 +87,7 @@ row-gap: 0rem!important; height: 200px; left: 62px; - z-index: 9999999; + z-index: 1; } .navigation-item { diff --git a/src/components/toolbar/ToolbarView.tsx b/src/components/toolbar/ToolbarView.tsx index 0a2d425..9f21664 100644 --- a/src/components/toolbar/ToolbarView.tsx +++ b/src/components/toolbar/ToolbarView.tsx @@ -1,7 +1,8 @@ import { Dispose, DropBounce, EaseOut, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait } from '@nitrots/nitro-renderer'; -import { FC, useState } from 'react'; +import { AnimatePresence, motion } from 'framer-motion'; +import { FC, useState, useEffect } from 'react'; import { CreateLinkEvent, GetConfiguration, GetSessionDataManager, MessengerIconState, OpenMessengerChat, VisitDesktop } from '../../api'; -import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common'; +import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView } from '../../common'; import { useAchievements, useFriends, useInventoryUnseenTracker, useMessageEvent, useMessenger, useRoomEngineEvent, useSessionInfo } from '../../hooks'; import { ToolbarMeView } from './ToolbarMeView'; @@ -20,7 +21,6 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => useMessageEvent(PerkAllowancesMessageEvent, event => { const parser = event.getParser(); - setUseGuideTool(parser.isAllowed(PerkEnum.USE_GUIDE_TOOL)); }); @@ -29,25 +29,21 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => const animationIconToToolbar = (iconName: string, image: HTMLImageElement, x: number, y: number) => { const target = (document.body.getElementsByClassName(iconName)[0] as HTMLElement); - if(!target) return; image.className = 'toolbar-icon-animation'; image.style.visibility = 'visible'; image.style.left = (x + 'px'); image.style.top = (y + 'px'); - document.body.append(image); const targetBounds = target.getBoundingClientRect(); const imageBounds = image.getBoundingClientRect(); - const left = (imageBounds.x - targetBounds.x); const top = (imageBounds.y - targetBounds.y); const squared = Math.sqrt(((left * left) + (top * top))); const wait = (500 - Math.abs(((((1 / squared) * 100) * 500) * 0.5))); const height = 20; - const motionName = (`ToolbarBouncing[${ iconName }]`); if(!Motions.getMotionByTag(motionName)) @@ -56,22 +52,45 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => } const motion = new Queue(new EaseOut(new JumpBy(image, wait, ((targetBounds.x - imageBounds.x) + height), (targetBounds.y - imageBounds.y), 100, 1), 1), new Dispose(image)); - Motions.runMotion(motion); } animationIconToToolbar('icon-inventory', event.image, event.x, event.y); }); + const handleAvatarClick = (event: React.MouseEvent) => { + event.stopPropagation(); + setMeExpanded(prev => !prev); + }; + return ( <> - - - + + { isMeExpanded && ( + + + + )} + - setMeExpanded(!isMeExpanded) }> + { (getTotalUnseen > 0) && } @@ -108,4 +127,4 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => > ); -} +} \ No newline at end of file diff --git a/src/hooks/rooms/widgets/useAvatarInfoWidget.ts b/src/hooks/rooms/widgets/useAvatarInfoWidget.ts index b69caff..a74e8ed 100644 --- a/src/hooks/rooms/widgets/useAvatarInfoWidget.ts +++ b/src/hooks/rooms/widgets/useAvatarInfoWidget.ts @@ -346,6 +346,8 @@ const useAvatarInfoWidgetState = () => useEffect(() => { + if(!roomSession) return; + roomSession.isDecorating = isDecorating; }, [ roomSession, isDecorating ]);