diff --git a/src/components/main/MainView.tsx b/src/components/main/MainView.tsx index 43435ab..66ae798 100644 --- a/src/components/main/MainView.tsx +++ b/src/components/main/MainView.tsx @@ -20,6 +20,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'; @@ -93,6 +94,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..29c4e85 --- /dev/null +++ b/src/components/nitrobubblehidden/NitrobubbleHiddenView.tsx @@ -0,0 +1,61 @@ +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/RoomWidgets.scss b/src/components/room/widgets/RoomWidgets.scss index 6198731..d6e2bed 100644 --- a/src/components/room/widgets/RoomWidgets.scss +++ b/src/components/room/widgets/RoomWidgets.scss @@ -99,6 +99,26 @@ height: $nitro-doorbell-height; } +.nitro-room-tools-history { + background: #212131; + box-shadow: inset 0 5px rgba(38, 38, 57, 0.6), inset 0 -4px rgba(25, 25, 37, 0.6); + border-radius: 5px; + transition: all 0.2s ease; + margin-left: 3px; + max-height: 104px; + overflow-y: auto; + z-index: 5; + padding-left: 6px; +} + +.nitro-room-history-rooms { + position: fixed; + transition: all 0.2s ease; + max-height: 40px; + margin-left: 2px; + bottom: 75px; +} + @import './avatar-info/AvatarInfoWidgetView'; @import './chat/ChatWidgetView'; @import './chat-input/ChatInputView'; diff --git a/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx b/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx index 76fd022..6c690aa 100644 --- a/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx +++ b/src/components/room/widgets/room-tools/RoomToolsWidgetView.tsx @@ -1,6 +1,6 @@ import { CreateLinkEvent, GetGuestRoomResultEvent, GetRoomEngine, NavigatorSearchComposer, RateFlatMessageComposer } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; -import { LocalizeText, SendMessageComposer } from '../../../../api'; +import { LocalizeText, SendMessageComposer, TryVisitRoom } from '../../../../api'; import { Base, Column, Flex, Text, TransitionAnimation, TransitionAnimationTypes, classNames } from '../../../../common'; import { useMessageEvent, useNavigator, useRoom } from '../../../../hooks'; @@ -11,8 +11,11 @@ export const RoomToolsWidgetView: FC<{}> = props => const [ roomOwner, setRoomOwner ] = useState(null); const [ roomTags, setRoomTags ] = useState(null); const [ isOpen, setIsOpen ] = useState(false); - const { navigatorData = null } = useNavigator(); + const [ isOpenHistory, setIsOpenHistory ] = useState(false); + const { navigatorData = null } = useNavigator(); + const [ roomHistory, setRoomHistory ] = useState<{ roomId: number, roomName: string }[]>([]); const { roomSession = null } = useRoom(); + const [areBubblesMuted, setAreBubblesMuted] = useState(false); const handleToolClick = (action: string, value?: string) => { @@ -37,6 +40,18 @@ export const RoomToolsWidgetView: FC<{}> = props => 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'); + } + setAreBubblesMuted(!areBubblesMuted); + const bubbleIcon = document.getElementById('bubbleIcon'); + if (bubbleIcon) { + bubbleIcon.classList.toggle('icon-chat-disablebubble'); + } + return; case 'like_room': SendMessageComposer(new RateFlatMessageComposer(1)); return; @@ -47,18 +62,52 @@ export const RoomToolsWidgetView: FC<{}> = props => CreateLinkEvent(`navigator/search/${ value }`); SendMessageComposer(new NavigatorSearchComposer('hotel_view', `tag:${ value }`)); return; + case 'room_history': + if (roomHistory.length > 0) { + const roomHistoryTool = document.getElementById("roomhistorytool"); + if (!isOpenHistory) { + roomHistoryTool.style.display = "block"; + setIsOpenHistory(true); + } else { + setIsOpenHistory(false); + roomHistoryTool.style.display = "none"; + } + } + return; + case 'room_history_back': + TryVisitRoom(roomHistory[roomHistory.findIndex(room => room.roomId === navigatorData.currentRoomId) - 1].roomId) + return; + case 'room_history_next': + TryVisitRoom(roomHistory[roomHistory.findIndex(room => room.roomId === navigatorData.currentRoomId) + 1].roomId) + return; } } + + const onChangeRoomHistory = (roomId: number, roomName: string) => { + const newStorage = JSON.parse(window.localStorage.getItem('nitro.room.history')) || []; - useMessageEvent(GetGuestRoomResultEvent, event => - { + if (newStorage.some(room => room.roomId === roomId)) return; + + if (newStorage.length >= 10) newStorage.shift(); + + const newData = [...newStorage, { roomId, roomName }]; + + setRoomHistory(newData); + SetLocalStorage('nitro.room.history', newData); + }; + + useMessageEvent(GetGuestRoomResultEvent, event => { + CreateLinkEvent('nitrobubblehidden/hide'); const parser = event.getParser(); - if(!parser.roomEnter || (parser.data.roomId !== roomSession.roomId)) return; + 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); + const { roomName, ownerName, tags } = parser.data; + + if (roomName !== roomSession.roomName) { setRoomName(roomName); } + if (ownerName !== roomSession.ownerName) { setRoomOwner(ownerName); } + if (JSON.stringify(tags) !== JSON.stringify(roomSession.tags)) { setRoomTags(tags); } + onChangeRoomHistory(parser.data.roomId, parser.data.roomName); }); useEffect(() => @@ -69,12 +118,17 @@ export const RoomToolsWidgetView: FC<{}> = props => return () => clearTimeout(timeout); }, [ roomName, roomOwner, roomTags ]); + + useEffect(() => { + setRoomHistory(JSON.parse(window.localStorage.getItem('nitro.room.history')) || []); + }, []); return ( handleToolClick('settings') } /> handleToolClick('zoom') } className={ classNames('icon', (!isZoomedIn && 'icon-zoom-less'), (isZoomedIn && 'icon-zoom-more')) } /> + handleToolClick('hiddenbubbles') } /> handleToolClick('chat_history') } className="icon icon-chat-history" /> { navigatorData.canRate && handleToolClick('like_room') } className="icon icon-like-room" /> } @@ -95,6 +149,26 @@ export const RoomToolsWidgetView: FC<{}> = props => + + 1 && roomHistory[0]?.roomId !== navigatorData.currentRoomId } title={ LocalizeText('room.history.button.back.tooltip') } className={ `icon ${ (roomHistory?.length === 0 || roomHistory[0]?.roomId === navigatorData.currentRoomId) ? 'icon-room-history-back-disabled' : 'icon-room-history-back-enabled' }` } onClick={ () => (roomHistory?.length === 0 || roomHistory[0]?.roomId === navigatorData.currentRoomId) ? null : handleToolClick('room_history_back') } /> + 0 } title={ LocalizeText('room.history.button.tooltip') } className={ `icon ${ roomHistory?.length === 0 ? 'icon-room-history-disabled' : 'icon-room-history-enabled' } margin-button-history` } onClick={ () => roomHistory?.length === 0 ? null : handleToolClick('room_history') } /> + 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 }; + }) + } + + + + +
); }