mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
feat(mod-tools): reactive ModToolsUserView (online dot + refresh on sanction)
ModToolsUserView used a one-shot ModeratorUserInfoData snapshot taken at panel-open time. Two consequences: - The online/offline icon (rendered next to userName) was frozen on the value at open. If the target user joined/left while the panel stayed open, the icon kept lying. - After the moderator applied a sanction via ModToolsUserModActionView the user info window stayed open with stale cfhCount / banCount / cautionCount / lastSanctionTime; you had to close and reopen to see the bump. Fix shape mirrors the ModToolsView selected-user dot from yesterday: - Read useRoomUserListSnapshot in the component (outside any useBetween scope — useSyncExternalStore constraint). If the target user is in the current room they're online; fall back to userInfo.online otherwise. Tooltip surfaces which path produced the value. - Subscribe to ModeratorActionResultMessageEvent (parser carries userId + success). On a successful action targeting THIS userId, re-send GetModeratorUserInfoMessageComposer so the table re-fetches.
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import { CreateLinkEvent, GetModeratorUserInfoMessageComposer, ModeratorUserInfoData, ModeratorUserInfoEvent } from '@nitrots/nitro-renderer';
|
import { CreateLinkEvent, GetModeratorUserInfoMessageComposer, ModeratorActionResultMessageEvent, ModeratorUserInfoData, ModeratorUserInfoEvent } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { FriendlyTime, LocalizeText, SendMessageComposer } from '../../../../api';
|
import { FriendlyTime, LocalizeText, SendMessageComposer } from '../../../../api';
|
||||||
import { Button, Column, DraggableWindowPosition, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
|
import { Button, Column, DraggableWindowPosition, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
|
||||||
import { useMessageEvent } from '../../../../hooks';
|
import { useMessageEvent, useRoomUserListSnapshot } from '../../../../hooks';
|
||||||
import { ModToolsUserModActionView } from './ModToolsUserModActionView';
|
import { ModToolsUserModActionView } from './ModToolsUserModActionView';
|
||||||
import { ModToolsUserRoomVisitsView } from './ModToolsUserRoomVisitsView';
|
import { ModToolsUserRoomVisitsView } from './ModToolsUserRoomVisitsView';
|
||||||
import { ModToolsUserSendMessageView } from './ModToolsUserSendMessageView';
|
import { ModToolsUserSendMessageView } from './ModToolsUserSendMessageView';
|
||||||
@@ -20,6 +20,15 @@ export const ModToolsUserView: FC<ModToolsUserViewProps> = props =>
|
|||||||
const [ sendMessageVisible, setSendMessageVisible ] = useState(false);
|
const [ sendMessageVisible, setSendMessageVisible ] = useState(false);
|
||||||
const [ modActionVisible, setModActionVisible ] = useState(false);
|
const [ modActionVisible, setModActionVisible ] = useState(false);
|
||||||
const [ roomVisitsVisible, setRoomVisitsVisible ] = useState(false);
|
const [ roomVisitsVisible, setRoomVisitsVisible ] = useState(false);
|
||||||
|
// Reactive presence: if the target user is currently in the room
|
||||||
|
// we're observing, they're online — irrespective of what the
|
||||||
|
// one-shot ModeratorUserInfoData.online said when the panel opened.
|
||||||
|
const roomUserList = useRoomUserListSnapshot();
|
||||||
|
const isPresentInCurrentRoom = useMemo(
|
||||||
|
() => roomUserList.some(user => user && (user.webID === userId)),
|
||||||
|
[ roomUserList, userId ]
|
||||||
|
);
|
||||||
|
const isOnline = isPresentInCurrentRoom || !!(userInfo && userInfo.online);
|
||||||
|
|
||||||
const userProperties = useMemo(() =>
|
const userProperties = useMemo(() =>
|
||||||
{
|
{
|
||||||
@@ -95,6 +104,19 @@ export const ModToolsUserView: FC<ModToolsUserViewProps> = props =>
|
|||||||
setUserInfo(parser.data);
|
setUserInfo(parser.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Refresh counters (cfhCount / banCount / cautionCount /
|
||||||
|
// lastSanctionTime) after the moderator applies a sanction on THIS
|
||||||
|
// user — otherwise the table stays frozen on the values at panel
|
||||||
|
// open. Parser carries userId so we can filter precisely.
|
||||||
|
useMessageEvent<ModeratorActionResultMessageEvent>(ModeratorActionResultMessageEvent, event =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!parser || !parser.success || parser.userId !== userId) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new GetModeratorUserInfoMessageComposer(userId));
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
SendMessageComposer(new GetModeratorUserInfoMessageComposer(userId));
|
SendMessageComposer(new GetModeratorUserInfoMessageComposer(userId));
|
||||||
@@ -120,7 +142,7 @@ export const ModToolsUserView: FC<ModToolsUserViewProps> = props =>
|
|||||||
<td>
|
<td>
|
||||||
{ property.value }
|
{ property.value }
|
||||||
{ property.showOnline &&
|
{ property.showOnline &&
|
||||||
<i className={ `icon icon-pf-${ userInfo.online ? 'online' : 'offline' } ms-2` } /> }
|
<i className={ `icon icon-pf-${ isOnline ? 'online' : 'offline' } ms-2` } title={ isPresentInCurrentRoom ? 'In this room' : (userInfo.online ? 'Online' : 'Offline') } /> }
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user