mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 15:36:18 +00:00
feat(avatar-info): make Give/Remove Rights instantly reactive
Replaced the cached `avatarInfo.targetRoomControllerLevel` derivation with a local `controllerLevel` state that: - starts from the popup-open snapshot - listens to FlatControllerAddedEvent / FlatControllerRemovedEvent filtered by avatarInfo.webID - is optimistically bumped on `give_rights` / `remove_rights` clicks so the moderate submenu flips immediately without waiting for the server roundtrip Same shape as the recent useIsUserIgnored migration: the popup now auto-flips the button without forcing the user to close+reopen it.
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { CreateLinkEvent, GetSessionDataManager, RoomControllerLevel, RoomObjectCategory, RoomObjectVariable, RoomUnitGiveHandItemComposer, SetRelationshipStatusComposer, TradingOpenComposer } from '@nitrots/nitro-renderer';
|
import { CreateLinkEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, GetSessionDataManager, RoomControllerLevel, RoomObjectCategory, RoomObjectVariable, RoomUnitGiveHandItemComposer, SetRelationshipStatusComposer, TradingOpenComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
|
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
|
||||||
import { AvatarInfoUser, DispatchUiEvent, GetOwnRoomObject, GetUserProfile, LocalizeText, MessengerFriend, ReportType, RoomWidgetUpdateChatInputContentEvent, SendMessageComposer } from '../../../../../api';
|
import { AvatarInfoUser, DispatchUiEvent, GetOwnRoomObject, GetUserProfile, LocalizeText, MessengerFriend, ReportType, RoomWidgetUpdateChatInputContentEvent, SendMessageComposer } from '../../../../../api';
|
||||||
import { Flex } from '../../../../../common';
|
import { Flex } from '../../../../../common';
|
||||||
import { useFriends, useHelp, useIsUserIgnored, useRoom, useSessionInfo, useWiredTools } from '../../../../../hooks';
|
import { useFriends, useHelp, useIsUserIgnored, useMessageEvent, useRoom, useSessionInfo, useWiredTools } from '../../../../../hooks';
|
||||||
import { ContextMenuHeaderView } from '../../context-menu/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../../context-menu/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../../context-menu/ContextMenuListItemView';
|
||||||
import { ContextMenuView } from '../../context-menu/ContextMenuView';
|
import { ContextMenuView } from '../../context-menu/ContextMenuView';
|
||||||
@@ -36,16 +36,39 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
// scope here) so useSyncExternalStore installs against the real
|
// scope here) so useSyncExternalStore installs against the real
|
||||||
// React dispatcher.
|
// React dispatcher.
|
||||||
const isIgnored = useIsUserIgnored(avatarInfo.name);
|
const isIgnored = useIsUserIgnored(avatarInfo.name);
|
||||||
|
// Reactive controller level: starts from the cached value at popup
|
||||||
|
// open time, then updates from FlatControllerAdded/Removed events
|
||||||
|
// and from optimistic clicks so the Give/Remove Rights buttons flip
|
||||||
|
// instantly without waiting for a server roundtrip.
|
||||||
|
const [ controllerLevel, setControllerLevel ] = useState(avatarInfo.targetRoomControllerLevel);
|
||||||
|
|
||||||
|
useMessageEvent<FlatControllerAddedEvent>(FlatControllerAddedEvent, event =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!parser || (parser.data.userId !== avatarInfo.webID)) return;
|
||||||
|
|
||||||
|
setControllerLevel(RoomControllerLevel.GUEST);
|
||||||
|
});
|
||||||
|
|
||||||
|
useMessageEvent<FlatControllerRemovedEvent>(FlatControllerRemovedEvent, event =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!parser || (parser.userId !== avatarInfo.webID)) return;
|
||||||
|
|
||||||
|
setControllerLevel(RoomControllerLevel.NONE);
|
||||||
|
});
|
||||||
|
|
||||||
const isShowGiveRights = useMemo(() =>
|
const isShowGiveRights = useMemo(() =>
|
||||||
{
|
{
|
||||||
return (avatarInfo.amIOwner && (avatarInfo.targetRoomControllerLevel < RoomControllerLevel.GUEST) && !avatarInfo.isGuildRoom);
|
return (avatarInfo.amIOwner && (controllerLevel < RoomControllerLevel.GUEST) && !avatarInfo.isGuildRoom);
|
||||||
}, [ avatarInfo ]);
|
}, [ avatarInfo, controllerLevel ]);
|
||||||
|
|
||||||
const isShowRemoveRights = useMemo(() =>
|
const isShowRemoveRights = useMemo(() =>
|
||||||
{
|
{
|
||||||
return (avatarInfo.amIOwner && (avatarInfo.targetRoomControllerLevel === RoomControllerLevel.GUEST) && !avatarInfo.isGuildRoom);
|
return (avatarInfo.amIOwner && (controllerLevel === RoomControllerLevel.GUEST) && !avatarInfo.isGuildRoom);
|
||||||
}, [ avatarInfo ]);
|
}, [ avatarInfo, controllerLevel ]);
|
||||||
|
|
||||||
const moderateMenuHasContent = useMemo(() =>
|
const moderateMenuHasContent = useMemo(() =>
|
||||||
{
|
{
|
||||||
@@ -155,9 +178,15 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
break;
|
break;
|
||||||
case 'give_rights':
|
case 'give_rights':
|
||||||
roomSession.sendGiveRightsMessage(avatarInfo.webID);
|
roomSession.sendGiveRightsMessage(avatarInfo.webID);
|
||||||
|
setControllerLevel(RoomControllerLevel.GUEST);
|
||||||
|
hideMenu = false;
|
||||||
|
setMode(MODE_MODERATE);
|
||||||
break;
|
break;
|
||||||
case 'remove_rights':
|
case 'remove_rights':
|
||||||
roomSession.sendTakeRightsMessage(avatarInfo.webID);
|
roomSession.sendTakeRightsMessage(avatarInfo.webID);
|
||||||
|
setControllerLevel(RoomControllerLevel.NONE);
|
||||||
|
hideMenu = false;
|
||||||
|
setMode(MODE_MODERATE);
|
||||||
break;
|
break;
|
||||||
case 'trade':
|
case 'trade':
|
||||||
SendMessageComposer(new TradingOpenComposer(avatarInfo.roomIndex));
|
SendMessageComposer(new TradingOpenComposer(avatarInfo.roomIndex));
|
||||||
@@ -210,6 +239,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
setMode(MODE_NORMAL);
|
setMode(MODE_NORMAL);
|
||||||
|
setControllerLevel(avatarInfo.targetRoomControllerLevel);
|
||||||
}, [ avatarInfo ]);
|
}, [ avatarInfo ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user