diff --git a/src/components/mod-tools/ModToolsView.tsx b/src/components/mod-tools/ModToolsView.tsx index d42381d..181eb0c 100644 --- a/src/components/mod-tools/ModToolsView.tsx +++ b/src/components/mod-tools/ModToolsView.tsx @@ -1,8 +1,9 @@ import { AddLinkEventTracker, CreateLinkEvent, ILinkEventTracker, RemoveLinkEventTracker, RoomEngineEvent, RoomId, RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer'; -import { FC, useEffect, useRef, useState } from 'react'; -import { GetRoomSession, ISelectedUser } from '../../api'; +import { FC, useEffect, useMemo, useRef, useState } from 'react'; +import { FaTimes } from 'react-icons/fa'; +import { GetRoomSession, ISelectedUser, LocalizeText } from '../../api'; import { Button, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common'; -import { useModTools, useNitroEvent, useObjectSelectedEvent } from '../../hooks'; +import { useModTools, useNitroEvent, useObjectSelectedEvent, useRoomUserListSnapshot } from '../../hooks'; import { ModToolsChatlogView } from './views/room/ModToolsChatlogView'; import { ModToolsRoomView } from './views/room/ModToolsRoomView'; import { ModToolsTicketsView } from './views/tickets/ModToolsTicketsView'; @@ -15,8 +16,24 @@ export const ModToolsView: FC<{}> = props => const [ currentRoomId, setCurrentRoomId ] = useState(-1); const [ selectedUser, setSelectedUser ] = useState(null); const [ isTicketsVisible, setIsTicketsVisible ] = useState(false); - const { openRooms = [], openRoomChatlogs = [], openUserChatlogs = [], openUserInfos = [], openRoomInfo = null, closeRoomInfo = null, toggleRoomInfo = null, openRoomChatlog = null, closeRoomChatlog = null, toggleRoomChatlog = null, openUserInfo = null, closeUserInfo = null, toggleUserInfo = null, openUserChatlog = null, closeUserChatlog = null, toggleUserChatlog = null } = useModTools(); + const { tickets = [], openRooms = [], openRoomChatlogs = [], openUserChatlogs = [], openUserInfos = [], openRoomInfo = null, closeRoomInfo = null, toggleRoomInfo = null, openRoomChatlog = null, closeRoomChatlog = null, toggleRoomChatlog = null, openUserInfo = null, closeUserInfo = null, toggleUserInfo = null, openUserChatlog = null, closeUserChatlog = null, toggleUserChatlog = null } = useModTools(); const elementRef = useRef(null); + // Reactive room roster — used to auto-clear the selected user if + // they leave the room while the panel is open, and to show an + // online dot on the selected-user button without going through + // userDataManager imperatively on every render. + const roomUserList = useRoomUserListSnapshot(); + // Count of OPEN tickets the moderator hasn't picked yet — shown + // as a badge on the Report Tool button so a new ticket is visible + // immediately, without forcing the user to click through. + const openTicketsCount = useMemo( + () => tickets.filter(ticket => ticket && (ticket.state === 1)).length, + [ tickets ] + ); + const isSelectedUserPresent = useMemo( + () => !!(selectedUser && roomUserList.some(user => user && (user.webID === selectedUser.userId))), + [ selectedUser, roomUserList ] + ); useNitroEvent([ RoomEngineEvent.INITIALIZED, @@ -120,28 +137,59 @@ export const ModToolsView: FC<{}> = props => const isRoomInfoOpen = currentRoomId > 0 && openRooms.includes(currentRoomId); const isRoomChatlogOpen = currentRoomId > 0 && openRoomChatlogs.includes(currentRoomId); const isUserInfoOpen = selectedUser && openUserInfos.includes(selectedUser.userId); + const noRoomHint = LocalizeText('mod.tools.no.room') || 'Enter a room first'; return ( <> { isVisible && - + setIsVisible(false) } /> - - - } diff --git a/src/hooks/mod-tools/useModTools.ts b/src/hooks/mod-tools/useModTools.ts index be1013a..7001076 100644 --- a/src/hooks/mod-tools/useModTools.ts +++ b/src/hooks/mod-tools/useModTools.ts @@ -30,7 +30,7 @@ const useModToolsState = () => const newValue = [ ...prevValue ]; const existingIndex = newValue.indexOf(roomId); - if(existingIndex >= 0) newValue.splice(existingIndex); + if(existingIndex >= 0) newValue.splice(existingIndex, 1); return newValue; }); @@ -56,7 +56,7 @@ const useModToolsState = () => const newValue = [ ...prevValue ]; const existingIndex = newValue.indexOf(roomId); - if(existingIndex >= 0) newValue.splice(existingIndex); + if(existingIndex >= 0) newValue.splice(existingIndex, 1); return newValue; }); @@ -82,7 +82,7 @@ const useModToolsState = () => const newValue = [ ...prevValue ]; const existingIndex = newValue.indexOf(userId); - if(existingIndex >= 0) newValue.splice(existingIndex); + if(existingIndex >= 0) newValue.splice(existingIndex, 1); return newValue; }); @@ -108,7 +108,7 @@ const useModToolsState = () => const newValue = [ ...prevValue ]; const existingIndex = newValue.indexOf(userId); - if(existingIndex >= 0) newValue.splice(existingIndex); + if(existingIndex >= 0) newValue.splice(existingIndex, 1); return newValue; }); @@ -116,7 +116,7 @@ const useModToolsState = () => const toggleUserChatlog = (userId: number) => { - if(openRoomChatlogs.indexOf(userId) >= 0) closeUserChatlog(userId); + if(openUserChatlogs.indexOf(userId) >= 0) closeUserChatlog(userId); else openUserChatlog(userId); };