diff --git a/src/assets/images/icons/disablebubble.png b/src/assets/images/icons/disablebubble.png new file mode 100644 index 0000000..bbf1390 Binary files /dev/null and b/src/assets/images/icons/disablebubble.png differ diff --git a/src/assets/images/icons/enablebubble.png b/src/assets/images/icons/enablebubble.png new file mode 100644 index 0000000..217109c Binary files /dev/null and b/src/assets/images/icons/enablebubble.png differ 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 0000000..78a4475 Binary files /dev/null and b/src/assets/images/icons/room-history-back-disabled.png differ diff --git a/src/assets/images/icons/room-history-back-enabled.png b/src/assets/images/icons/room-history-back-enabled.png new file mode 100644 index 0000000..bed6a42 Binary files /dev/null and b/src/assets/images/icons/room-history-back-enabled.png differ diff --git a/src/assets/images/icons/room-history-disabled.png b/src/assets/images/icons/room-history-disabled.png new file mode 100644 index 0000000..fcd8119 Binary files /dev/null and b/src/assets/images/icons/room-history-disabled.png differ 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 0000000..287227b Binary files /dev/null and b/src/assets/images/icons/room-history-enabled.png differ diff --git a/src/assets/images/icons/room-history-next-disabled.png b/src/assets/images/icons/room-history-next-disabled.png new file mode 100644 index 0000000..3f82d0e Binary files /dev/null and b/src/assets/images/icons/room-history-next-disabled.png differ diff --git a/src/assets/images/icons/room-history-next-enabled.png b/src/assets/images/icons/room-history-next-enabled.png new file mode 100644 index 0000000..3de01c0 Binary files /dev/null and b/src/assets/images/icons/room-history-next-enabled.png differ 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;