mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
c9df2d8765
Introduce a reusable NavigatorRoomSettingsSectionView card (rounded bg-gray-100 panel with a bold-small title) and apply it across the Access, VIP/Chat, Moderation and Rights tabs so every room-settings screen matches the Base and Misc tab styling. Pure visual restyle — handleChange wiring, events, composers and validations are unchanged.
179 lines
6.9 KiB
TypeScript
179 lines
6.9 KiB
TypeScript
import { FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, RemoveAllRightsMessageComposer, RoomGiveRightsComposer, RoomTakeRightsComposer, RoomUsersWithRightsComposer } from '@nitrots/nitro-renderer';
|
|
import { FC, useEffect, useRef, useState } from 'react';
|
|
import { IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
|
|
import { Button, Column, Flex, Grid, Text, UserProfileIconView } from '../../../../common';
|
|
import { useFriends, useMessageEvent } from '../../../../hooks';
|
|
import { NavigatorRoomSettingsSectionView } from './NavigatorRoomSettingsSectionView';
|
|
|
|
interface NavigatorRoomSettingsTabViewProps
|
|
{
|
|
roomData: IRoomData;
|
|
handleChange: (field: string, value: string | number | boolean) => void;
|
|
}
|
|
|
|
const STAFF_CHAT_ID = -1;
|
|
const STAFF_CHAT_NAME = 'Staff Chat';
|
|
|
|
export const NavigatorRoomSettingsRightsTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
|
|
{
|
|
const { roomData = null } = props;
|
|
const [ usersWithRights, setUsersWithRights ] = useState<Map<number, string>>(new Map());
|
|
const { onlineFriends = [], offlineFriends = [] } = useFriends();
|
|
const pendingActionsRef = useRef<Set<string>>(new Set());
|
|
|
|
const guardedSend = (key: string, composer: any) =>
|
|
{
|
|
if(pendingActionsRef.current.has(key)) return;
|
|
|
|
pendingActionsRef.current.add(key);
|
|
SendMessageComposer(composer);
|
|
|
|
setTimeout(() => pendingActionsRef.current.delete(key), 2000);
|
|
};
|
|
|
|
const allFriendsRaw = [ ...onlineFriends, ...offlineFriends ];
|
|
|
|
const allFriends = allFriendsRaw.filter(friend =>
|
|
{
|
|
if(friend.id === STAFF_CHAT_ID) return false;
|
|
if(friend.name === STAFF_CHAT_NAME) return false;
|
|
if(friend.id <= 0) return false;
|
|
|
|
return true;
|
|
});
|
|
|
|
const filteredUsersWithRights = new Map(
|
|
Array.from(usersWithRights.entries()).filter(([ id, name ]) =>
|
|
{
|
|
if(id === STAFF_CHAT_ID) return false;
|
|
if(name === STAFF_CHAT_NAME) return false;
|
|
if(id <= 0) return false;
|
|
|
|
return true;
|
|
})
|
|
);
|
|
|
|
const friendsWithoutRights = allFriends.filter(friend => !filteredUsersWithRights.has(friend.id));
|
|
|
|
useMessageEvent<FlatControllersEvent>(FlatControllersEvent, event =>
|
|
{
|
|
const parser = event.getParser();
|
|
|
|
if(!roomData || (roomData.roomId !== parser.roomId)) return;
|
|
|
|
setUsersWithRights(parser.users);
|
|
});
|
|
|
|
useMessageEvent<FlatControllerAddedEvent>(FlatControllerAddedEvent, event =>
|
|
{
|
|
const parser = event.getParser();
|
|
|
|
if(!roomData || (roomData.roomId !== parser.roomId)) return;
|
|
|
|
setUsersWithRights(prevValue =>
|
|
{
|
|
const newValue = new Map(prevValue);
|
|
|
|
newValue.set(parser.data.userId, parser.data.userName);
|
|
|
|
return newValue;
|
|
});
|
|
});
|
|
|
|
useMessageEvent<FlatControllerRemovedEvent>(FlatControllerRemovedEvent, event =>
|
|
{
|
|
const parser = event.getParser();
|
|
|
|
if(!roomData || (roomData.roomId !== parser.roomId)) return;
|
|
|
|
setUsersWithRights(prevValue =>
|
|
{
|
|
const newValue = new Map(prevValue);
|
|
|
|
newValue.delete(parser.userId);
|
|
|
|
return newValue;
|
|
});
|
|
});
|
|
|
|
useEffect(() =>
|
|
{
|
|
if(!roomData) return;
|
|
|
|
SendMessageComposer(new RoomUsersWithRightsComposer(roomData.roomId));
|
|
}, [ roomData ]);
|
|
|
|
return (
|
|
<Grid>
|
|
<Column size={ 6 }>
|
|
<NavigatorRoomSettingsSectionView gap={ 1 } className="h-full"
|
|
title={ LocalizeText(
|
|
'navigator.flatctrls.userswithrights',
|
|
[ 'displayed', 'total' ],
|
|
[
|
|
filteredUsersWithRights.size.toString(),
|
|
filteredUsersWithRights.size.toString()
|
|
]
|
|
) }>
|
|
<Flex overflow="hidden" className="nitro-card-panel p-2 list-container">
|
|
<Column fullWidth overflow="auto" gap={ 1 }>
|
|
{ Array.from(filteredUsersWithRights.entries()).map(([ id, name ], index) =>
|
|
{
|
|
return (
|
|
<Flex key={ `${id}-${index}` } shrink alignItems="center" gap={ 1 } overflow="hidden">
|
|
<UserProfileIconView userId={ id } />
|
|
<Text
|
|
pointer
|
|
grow
|
|
onClick={ () => guardedSend(`take_${id}`, new RoomTakeRightsComposer(id)) }>
|
|
{ name }
|
|
</Text>
|
|
</Flex>
|
|
);
|
|
}) }
|
|
</Column>
|
|
</Flex>
|
|
|
|
<Button
|
|
variant="danger"
|
|
disabled={ !filteredUsersWithRights.size }
|
|
onClick={ () => roomData && guardedSend('removeAll', new RemoveAllRightsMessageComposer(roomData.roomId)) }>
|
|
{ LocalizeText('navigator.flatctrls.clear') }
|
|
</Button>
|
|
</NavigatorRoomSettingsSectionView>
|
|
</Column>
|
|
|
|
<Column size={ 6 }>
|
|
<NavigatorRoomSettingsSectionView gap={ 1 } className="h-full"
|
|
title={ LocalizeText(
|
|
'navigator.flatctrls.friends',
|
|
[ 'displayed', 'total' ],
|
|
[
|
|
friendsWithoutRights.length.toString(),
|
|
allFriends.length.toString()
|
|
]
|
|
) }>
|
|
<Flex overflow="hidden" className="nitro-card-panel p-2 list-container">
|
|
<Column fullWidth overflow="auto" gap={ 1 }>
|
|
{ friendsWithoutRights.map((friend, index) =>
|
|
{
|
|
return (
|
|
<Flex key={ `${friend.id}-${index}` } shrink alignItems="center" gap={ 1 } overflow="hidden">
|
|
<UserProfileIconView userId={ friend.id } />
|
|
<Text
|
|
pointer
|
|
grow
|
|
onClick={ () => guardedSend(`give_${friend.id}`, new RoomGiveRightsComposer(friend.id)) }>
|
|
{ friend.name }
|
|
</Text>
|
|
</Flex>
|
|
);
|
|
}) }
|
|
</Column>
|
|
</Flex>
|
|
</NavigatorRoomSettingsSectionView>
|
|
</Column>
|
|
</Grid>
|
|
);
|
|
};
|