From 6f30fe5f29577415f19466f956fec0ac5b303880 Mon Sep 17 00:00:00 2001 From: duckietm Date: Thu, 20 Mar 2025 11:56:52 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A3=20Updated=20the=20Left=20toolbar?= =?UTF-8?q?=20also=20added=20hide=20all=20chat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/images/icons/disablebubble.png | Bin 0 -> 737 bytes src/assets/images/icons/enablebubble.png | Bin 0 -> 734 bytes .../icons/room-history-back-disabled.png | Bin 0 -> 267 bytes .../icons/room-history-back-enabled.png | Bin 0 -> 280 bytes .../images/icons/room-history-disabled.png | Bin 0 -> 393 bytes .../images/icons/room-history-enabled.png | Bin 0 -> 402 bytes .../icons/room-history-next-disabled.png | Bin 0 -> 260 bytes .../icons/room-history-next-enabled.png | Bin 0 -> 267 bytes src/components/MainView.tsx | 2 + .../NitrobubbleHiddenView.tsx | 59 ++++++ .../widgets/chat/ChatWidgetMessageView.tsx | 2 +- .../room-tools/RoomToolsWidgetView.tsx | 171 ++++++++++++------ src/css/icons/icons.css | 12 ++ 13 files changed, 191 insertions(+), 55 deletions(-) create mode 100644 src/assets/images/icons/disablebubble.png create mode 100644 src/assets/images/icons/enablebubble.png create mode 100644 src/assets/images/icons/room-history-back-disabled.png create mode 100644 src/assets/images/icons/room-history-back-enabled.png create mode 100644 src/assets/images/icons/room-history-disabled.png create mode 100644 src/assets/images/icons/room-history-enabled.png create mode 100644 src/assets/images/icons/room-history-next-disabled.png create mode 100644 src/assets/images/icons/room-history-next-enabled.png create mode 100644 src/components/nitrobubblehidden/NitrobubbleHiddenView.tsx diff --git a/src/assets/images/icons/disablebubble.png b/src/assets/images/icons/disablebubble.png new file mode 100644 index 0000000000000000000000000000000000000000..bbf1390d2092c3a4ba80181c7ceb3e32a536e6f9 GIT binary patch literal 737 zcmV<70v`Q|P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0(MD6K~y+Tt&?9! zQ*ji>zjK?r=^W`~3gtgqR$H0a?ZKGi;Y0R?P^4B z*NftB5%H*AkAXvO9u{$Zx`2_j#3utR&J*_r z5WGIXqasXXG2|@>EXTgHrL5H;m6}5=G*wusLrNct>^(eD+?da~KDTPY%i0^ugD4*WSLtuU$Fc^rVu9F^cR?KR&xwfIoaz}n* zb$dwPR@N$m3Z#=f;4B{(P}QM>pi!|{R>|-spr)04$|XK1!VLLkj1H$1kQr$!G%(au zl7sjF?fr5QNosGyh|mMmW~{;NV*ow%O;|76VyHW1(s26WYs Tkxlvk00000NkvXXu0mjf>t#(` literal 0 HcmV?d00001 diff --git a/src/assets/images/icons/enablebubble.png b/src/assets/images/icons/enablebubble.png new file mode 100644 index 0000000000000000000000000000000000000000..217109c5f3f84c03826d2f614ea170f9b75d51e2 GIT binary patch literal 734 zcmV<40wMj0P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0&_`3K~y+Tt&&S< z6G0fq|J%(bTiROF^bwkfv4Ip*rHPPg6>Y2s@h*7LgHQ!~@qrJ_$@ZWGgo2_4^`N47 z(A1Nlf>pE<5NuE^6dx5l*hIyxjgoEBWSyCv-6T!L9{LMkzQ@e`=i6@=%YndsDH``n zMOY}J^*9_D?z+s=B8Oh}R389c@hg9MW%WD>R>b>Z0?}5X%60ylgOn@LT5rOB;5Wyj=)*o34w|+L0b(`B!i@O^vM|{rr*&r63GNUDddYSW;6>vmai@r?(2>yuKiHX~mM_WD%k-RN> zLv4eKlrqZ&1c=1igj%?3>ezltMJMs&K&A;2)(CxP|ji+Wl%w_@KE>MD)_Goq4eNV_WzSbJ6J}5zgXGDU_G(v QjQ{`u07*qoM6N<$f|LeNn*aa+ literal 0 HcmV?d00001 diff --git a/src/assets/images/icons/room-history-back-disabled.png b/src/assets/images/icons/room-history-back-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..78a447502ed4d6a2ef67b5fbb41459609d601abb GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^NNn{1`g#vs+Tt!6%C1k~A)D@(ZWX!G2fx^{3v4?>aTS<^#@P80s*t~zqexL|v zfk$L90|Vb75M~tB@M-`G7I?ZihFJKYz2eB#V8G*YamB}f;bxNVjvnf);=jzzKCEzE zvCVy%_l6ZsED@oeJ7h%jPuXruR0xV`3BGy!$WIs5kJBo=olI0()dbd;&$Q&`316X< zxWhqp=8s+H>pZ4-HdPNn{1`MFV_7Tv=IJWSz~ex{7sDLoQr6ui#}1lsVJb;t8bKOM?7@|APU8lsB^* zP>8d@BeIx*f$tCqGm2_>H2?)GJzX3_Ec}mNG30A7;Bmg_#Qojgs55)QgqZZ^{U#IV zH7wm?oVAZ-wzfyZ-Ki~)S5*YtE!Jn=_(<(eiv8q+!k$K6MqWaT6f|ubKRj7+(qzuW zA9qY-CMslFD7qdhaG3O^S^d(JtJjarRN3Kv$CbbEto2#f=|}!cM(t*>ZR9d9I{GmR P=m-W+S3j3^P6Nn{1`wE}!XT*bvjWYrYpwN<4QWTa#z#Uw-x^)!?eq_or()s^K`l_ZVz6ikh^ zfXbKgeP;(!d?i7C!T*r~gX@7iCx9}X1s;*bKm~_EnDKc2iWH#WIZqeI5DWjMmjn4) z6nI!JC@DpK{CEBCwk_IO2Yt)x6wYxAC>3}(xT|k%{Gg<;hl7dHO7P$UX$3=;O%*dr z-nE-Gok;n#Xwjq>PqbUEOpY(+QZukmatb$`792XdK;0|zn#NPj7ssx6 z)bBSGOWRWJYI>`jMf&aTMJIhLHo6_Fs}tH3Z7$ro;{0*{Ddy%}`*VJsXSeL*f4)O- VE$6>)JwTr^c)I$ztaD0e0ss_0j>rH2 literal 0 HcmV?d00001 diff --git a/src/assets/images/icons/room-history-enabled.png b/src/assets/images/icons/room-history-enabled.png new file mode 100644 index 0000000000000000000000000000000000000000..287227bf40c3b6725cde5bacb0e9600efe9e7f43 GIT binary patch literal 402 zcmeAS@N?(olHy`uVBq!ia0vp^ia@N)!3-pIKTQq;QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{173GfMVWo2d2Ne!{;DwcINm(*30G0<4s*AQr;(ik6@>tmPfEVHZM_vpGF z5oKARjyLNX`+yXGNswRge-yxQ<<5+SKq<}wkH}&M2EM}}%y>M1MG8>xvZsqs z%h7x-3OuYAl$yF8{F`o_n_0`lsy_2~bA|r_fyQQLBdL|VJH#2^xhfP~;N)hy%h09x z;OJeI^JN9fA6(S5m9##(`5jzR_tSW~0#mWD=q9cfsX3>EEm-B3?_uvST(y&Ba^$bn z$SZeP1m9jS4K5b~}l(od%)$~$1i{wk`L|19K-#Nn{1`g#vs+Tt!6%Wz-dNn{1`MFV_7Tv=IJth$PIQbR6WIIrMkE9-0ylv!21;4_e7FA4Gs{tpHWQr^sN zKq1ZokH}&M2EM}}%y>M1MG8-9F!NW`|t-Zp6 z=K@yxnJikoYB6tM$`hYz$1^z{v*IUbpHp`cWA-$e!7^DO-{_H#+q<0^oP|n?aS1{! zDuD`{I9#snQ~Lcm?4aAJWAdVg<%dEaFF)<#A~k6}yW^CCTuGq444$rjF6*2UngCgX BSzZ7D literal 0 HcmV?d00001 diff --git a/src/components/MainView.tsx b/src/components/MainView.tsx index bfbf443..e8b838d 100644 --- a/src/components/MainView.tsx +++ b/src/components/MainView.tsx @@ -19,6 +19,7 @@ import { HotelView } from './hotel-view/HotelView'; import { InventoryView } from './inventory/InventoryView'; import { ModToolsView } from './mod-tools/ModToolsView'; import { NavigatorView } from './navigator/NavigatorView'; +import { NitrobubbleHiddenView } from './nitrobubblehidden/NitrobubbleHiddenView'; import { NitropediaView } from './nitropedia/NitropediaView'; import { RightSideView } from './right-side/RightSideView'; import { RoomView } from './room/RoomView'; @@ -97,6 +98,7 @@ export const MainView: FC<{}> = props => + diff --git a/src/components/nitrobubblehidden/NitrobubbleHiddenView.tsx b/src/components/nitrobubblehidden/NitrobubbleHiddenView.tsx new file mode 100644 index 0000000..6f93c75 --- /dev/null +++ b/src/components/nitrobubblehidden/NitrobubbleHiddenView.tsx @@ -0,0 +1,59 @@ +import { AddLinkEventTracker, ILinkEventTracker, RemoveLinkEventTracker } from '@nitrots/nitro-renderer'; +import { FC, useEffect, useMemo, useRef, useState } from 'react'; +import { useChatHistory } from '../../hooks'; + +export const NitrobubbleHiddenView: FC<{}> = props => +{ + const [ isVisible, setIsVisible ] = useState(false); + const [ searchText, setSearchText ] = useState(''); + const { chatHistory = [] } = useChatHistory(); + const elementRef = useRef(null); + + const filteredChatHistory = useMemo(() => + { + if (searchText.length === 0) return chatHistory; + + let text = searchText.toLowerCase(); + + return chatHistory.filter(entry => ((entry.message && entry.message.toLowerCase().includes(text))) || (entry.name && entry.name.toLowerCase().includes(text))); + }, [ chatHistory, searchText ]); + + useEffect(() => + { + if(elementRef && elementRef.current && isVisible) elementRef.current.scrollTop = elementRef.current.scrollHeight; + }, [ isVisible ]); + + useEffect(() => + { + const linkTracker: ILinkEventTracker = { + linkReceived: (url: string) => + { + const parts = url.split('/'); + + if(parts.length < 2) return; + + switch(parts[1]) + { + case 'show': + setIsVisible(true); + return; + case 'hide': + setIsVisible(false); + return; + case 'toggle': + setIsVisible(prevValue => !prevValue); + return; + } + }, + eventUrlPrefix: 'nitrobubblehidden/' + }; + + AddLinkEventTracker(linkTracker); + + return () => RemoveLinkEventTracker(linkTracker); + }, []); + + if(!isVisible) return null; + var stylecssnew = ""; + return (
); +} diff --git a/src/components/room/widgets/chat/ChatWidgetMessageView.tsx b/src/components/room/widgets/chat/ChatWidgetMessageView.tsx index 7a4b919..48c0564 100644 --- a/src/components/room/widgets/chat/ChatWidgetMessageView.tsx +++ b/src/components/room/widgets/chat/ChatWidgetMessageView.tsx @@ -76,7 +76,7 @@ export const ChatWidgetMessageView: FC = ({ }, [ chat, isReady, isVisible, makeRoom ]); return ( -
GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }> { chat.styleId === 0 && (
diff --git a/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx b/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx index 962a3ce..4efac15 100644 --- a/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx +++ b/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx @@ -2,40 +2,35 @@ import { CreateLinkEvent, GetGuestRoomResultEvent, GetRoomEngine, NavigatorSearc import { AnimatePresence, motion } from 'framer-motion'; import { classNames } from '../../../../layout'; import { FC, useEffect, useState } from 'react'; -import { GetConfigurationValue, LocalizeText, SendMessageComposer } from '../../../../api'; +import { GetConfigurationValue, LocalizeText, SendMessageComposer, SetLocalStorage, TryVisitRoom } from '../../../../api'; import { Text } from '../../../../common'; import { useMessageEvent, useNavigator, useRoom } from '../../../../hooks'; - -export const RoomToolsWidgetView: FC<{}> = props => -{ - const [ isZoomedIn, setIsZoomedIn ] = useState(false); - const [ roomName, setRoomName ] = useState(null); - const [ roomOwner, setRoomOwner ] = useState(null); - const [ roomTags, setRoomTags ] = useState(null); - const [ isOpen, setIsOpen ] = useState(false); +export const RoomToolsWidgetView: FC<{}> = props => { + const [areBubblesMuted, setAreBubblesMuted] = useState(false); + const [isZoomedIn, setIsZoomedIn] = useState(false); + const [roomName, setRoomName] = useState(null); + const [roomOwner, setRoomOwner] = useState(null); + const [roomTags, setRoomTags] = useState(null); + const [isOpen, setIsOpen] = useState(false); + const [isOpenHistory, setIsOpenHistory] = useState(false); + const [roomHistory, setRoomHistory] = useState<{ roomId: number, roomName: string }[]>([]); const { navigatorData = null } = useNavigator(); const { roomSession = null } = useRoom(); - const handleToolClick = (action: string, value?: string) => - { - switch(action) - { + const handleToolClick = (action: string, value?: string) => { + switch (action) { case 'settings': CreateLinkEvent('navigator/toggle-room-info'); return; case 'zoom': - setIsZoomedIn(prevValue => - { - if(GetConfigurationValue('room.zoom.enabled', true)) - { + setIsZoomedIn(prevValue => { + if (GetConfigurationValue('room.zoom.enabled', true)) { const scale = GetRoomEngine().getRoomInstanceRenderingCanvasScale(roomSession.roomId, 1); GetRoomEngine().setRoomInstanceRenderingCanvasScale(roomSession.roomId, 1, scale === 1 ? 0.5 : 1); - } - else - { + } else { const geometry = GetRoomEngine().getRoomInstanceGeometry(roomSession.roomId, 1); - if(geometry) geometry.performZoom(); + if (geometry) geometry.performZoom(); } return !prevValue; }); @@ -43,6 +38,10 @@ export const RoomToolsWidgetView: FC<{}> = props => case 'chat_history': CreateLinkEvent('chat-history/toggle'); return; + case 'hiddenbubbles': + CreateLinkEvent('nitrobubblehidden/toggle'); + setAreBubblesMuted(prev => !prev); + return; case 'like_room': SendMessageComposer(new RateFlatMessageComposer(1)); return; @@ -50,41 +49,80 @@ export const RoomToolsWidgetView: FC<{}> = props => CreateLinkEvent('navigator/toggle-room-link'); return; case 'navigator_search_tag': - CreateLinkEvent(`navigator/search/${ value }`); - SendMessageComposer(new NavigatorSearchComposer('hotel_view', `tag:${ value }`)); + CreateLinkEvent(`navigator/search/${value}`); + SendMessageComposer(new NavigatorSearchComposer('hotel_view', `tag:${value}`)); + return; + case 'room_history': + if (roomHistory.length > 0) setIsOpenHistory(prev => !prev); + return; + case 'room_history_back': + const prevIndex = roomHistory.findIndex(room => room.roomId === navigatorData.currentRoomId) - 1; + if (prevIndex >= 0) TryVisitRoom(roomHistory[prevIndex].roomId); + return; + case 'room_history_next': + const nextIndex = roomHistory.findIndex(room => room.roomId === navigatorData.currentRoomId) + 1; + if (nextIndex < roomHistory.length) TryVisitRoom(roomHistory[nextIndex].roomId); return; } }; - useMessageEvent(GetGuestRoomResultEvent, event => - { - const parser = event.getParser(); - if(!parser.roomEnter || (parser.data.roomId !== roomSession.roomId)) return; + const onChangeRoomHistory = (roomId: number, roomName: string) => { + let newStorage = JSON.parse(window.localStorage.getItem('nitro.room.history') || '[]'); + if (newStorage.some((room: { roomId: number }) => room.roomId === 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); + if (newStorage.length >= 10) newStorage.shift(); + newStorage = [...newStorage, { roomId, roomName }]; + + setRoomHistory(newStorage); + SetLocalStorage('nitro.room.history', newStorage); + }; + + 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); }); - useEffect(() => - { + useEffect(() => { setIsOpen(true); const timeout = setTimeout(() => setIsOpen(false), 5000); return () => clearTimeout(timeout); - }, [ roomName, roomOwner, roomTags ]); + }, [roomName, roomOwner, roomTags]); + + useEffect(() => { + setRoomHistory(JSON.parse(window.localStorage.getItem('nitro.room.history') || '[]')); + }, []); + + useEffect(() => { + const handleTabClose = () => { + window.localStorage.removeItem('nitro.room.history'); + }; + window.addEventListener('beforeunload', handleTabClose); + return () => window.removeEventListener('beforeunload', handleTabClose); + }, []); return (
-
handleToolClick('settings') } /> -
handleToolClick('zoom') } /> -
handleToolClick('chat_history') } /> - { navigatorData.canRate && -
handleToolClick('like_room') } /> } +
handleToolClick('hiddenbubbles')} /> +
handleToolClick('settings')} /> +
handleToolClick('zoom')} /> +
handleToolClick('chat_history')} /> +
handleToolClick('hiddenbubbles')} /> + + {navigatorData.canRate && ( +
handleToolClick('like_room')} /> + )} +
handleToolClick('toggle_room_link')} /> +
handleToolClick('room_history')} />
- { isOpen && + {isOpen && ( = props =>
- { roomName } - { roomOwner } + {roomName} + {roomOwner}
- { roomTags && roomTags.length > 0 && + {roomTags && roomTags.length > 0 && (
- { roomTags.map((tag, index) => ( - handleToolClick('navigator_search_tag', tag) } + {roomTags.map((tag, index) => ( + handleToolClick('navigator_search_tag', tag)} > - #{ tag } + #{tag} - )) } -
} + ))} +
+ )}
- } + + )} + {isOpenHistory && ( + +
+ {roomHistory.map(history => ( + TryVisitRoom(history.roomId)} + > + {history.roomName} + + ))} +
+
+ )}
diff --git a/src/css/icons/icons.css b/src/css/icons/icons.css index dc89bc6..e5c0fe2 100644 --- a/src/css/icons/icons.css +++ b/src/css/icons/icons.css @@ -379,6 +379,18 @@ height: 22px; } +.icon-chat-enablebubble { + background: url('@/assets/images/icons/enablebubble.png'); + width: 17px; + height: 21px; +} + + .icon-chat-disablebubble { + background: url('@/assets/images/icons/disablebubble.png'); + width: 17px; + height: 21px; +} + .nitro-icon.icon-arrows { background: url("@/assets/images/icons/arrows.png"); width: 17px;