Navigator settings update

This commit is contained in:
Bill 2022-03-27 18:44:29 -04:00
parent d250f24df5
commit afc6bc44f8
12 changed files with 455 additions and 367 deletions

View File

@ -0,0 +1,8 @@
export interface IRoomChatSettings
{
mode: number;
weight: number;
speed: number;
distance: number;
protection: number;
}

View File

@ -0,0 +1,23 @@
import { IRoomChatSettings } from './IRoomChatSettings';
import { IRoomModerationSettings } from './IRoomModerationSettings';
export interface IRoomData
{
roomId: number;
roomName: string;
roomDescription: string;
categoryId: number;
userCount: number;
tags: string[];
tradeState: number;
allowWalkthrough: boolean;
lockState: number;
password: string;
allowPets: boolean;
allowPetsEat: boolean;
hideWalls: boolean;
wallThickness: number;
floorThickness: number;
chatSettings: IRoomChatSettings;
moderationSettings: IRoomModerationSettings;
}

View File

@ -0,0 +1,6 @@
export interface IRoomModerationSettings
{
allowMute: number;
allowKick: number;
allowBan: number;
}

View File

@ -1,6 +1,9 @@
export * from './DoorStateType';
export * from './INavigatorData';
export * from './INavigatorSearchFilter';
export * from './IRoomChatSettings';
export * from './IRoomData';
export * from './IRoomModerationSettings';
export * from './NavigatorSearchResultViewDisplayMode';
export * from './RoomInfoData';
export * from './RoomModels';

View File

@ -16,11 +16,9 @@ export class NavigatorRoomInfoViewProps
export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
{
const { onCloseClick = null } = props;
const [ roomThumbnail, setRoomThumbnail ] = useState(null);
const [ isRoomPicked, setIsRoomPicked ] = useState(false);
const [ isRoomMuted, setIsRoomMuted ] = useState(false);
const { navigatorData = null } = useNavigatorContext();
const isMod = GetSessionDataManager().isModerator;
const hasPermission = (permission: string) =>
@ -28,7 +26,7 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
switch(permission)
{
case 'settings':
return (GetSessionDataManager().userId === navigatorData.enteredGuestRoom.ownerId || isMod );
return (GetSessionDataManager().userId === navigatorData.enteredGuestRoom.ownerId || GetSessionDataManager().isModerator);
case 'staff_pick':
return GetSessionDataManager().securityLevel >= SecurityLevel.COMMUNITY;
default: return false;
@ -49,7 +47,7 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
newRoomId = navigatorData.enteredGuestRoom.roomId;
}
SendMessageComposer(new UserHomeRoomComposer(newRoomId));
if(newRoomId > 0) SendMessageComposer(new UserHomeRoomComposer(newRoomId));
return;
case 'navigator_search_tag':
return;

View File

@ -1,27 +1,38 @@
import { RoomDataParser } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
import { LocalizeText, RoomSettingsData } from '../../../../api';
import { FC, useEffect, useState } from 'react';
import { IRoomData, LocalizeText } from '../../../../api';
import { Column, Flex, Text } from '../../../../common';
import { BatchUpdates } from '../../../../hooks';
interface NavigatorRoomSettingsTabViewProps
{
roomSettingsData: RoomSettingsData;
roomData: IRoomData;
handleChange: (field: string, value: string | number | boolean) => void;
}
export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
{
const { roomSettingsData = null, handleChange = null } = props;
const { roomData = null, handleChange = null } = props;
const [ password, setPassword ] = useState<string>('');
const [ confirmPassword, setConfirmPassword ] = useState('');
const [ isTryingPassword, setIsTryingPassword ] = useState(false);
const isPasswordValid = useCallback(() =>
const saveRoomPassword = () =>
{
return (roomSettingsData.password && (roomSettingsData.password.length > 0) && (roomSettingsData.password === roomSettingsData.confirmPassword));
}, [ roomSettingsData ]);
if(!isTryingPassword || ((password.length <= 0) || (confirmPassword.length <= 0) || (password !== confirmPassword))) return;
const trySave = useCallback(() =>
handleChange('password', password);
}
useEffect(() =>
{
if(isPasswordValid()) handleChange('save', null);
}, [ isPasswordValid, handleChange ]);
BatchUpdates(() =>
{
setPassword('');
setConfirmPassword('');
setIsTryingPassword(false);
});
}, [ roomData ]);
return (
<>
@ -33,27 +44,31 @@ export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabView
<Column gap={ 1 }>
<Text bold>{ LocalizeText('navigator.roomsettings.doormode') }</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="radio" name="lockState" checked={ (roomSettingsData.lockState === RoomDataParser.OPEN_STATE) } onChange={ event => handleChange('lock_state', RoomDataParser.OPEN_STATE) } />
<input className="form-check-input" type="radio" name="lockState" checked={ (roomData.lockState === RoomDataParser.OPEN_STATE) && !isTryingPassword } onChange={ event => handleChange('lock_state', RoomDataParser.OPEN_STATE) } />
<Text>{ LocalizeText('navigator.roomsettings.doormode.open') }</Text>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="radio" name="lockState" checked={ (roomSettingsData.lockState === RoomDataParser.DOORBELL_STATE) } onChange={ event => handleChange('lock_state', RoomDataParser.DOORBELL_STATE) } />
<input className="form-check-input" type="radio" name="lockState" checked={ (roomData.lockState === RoomDataParser.DOORBELL_STATE) && !isTryingPassword } onChange={ event => handleChange('lock_state', RoomDataParser.DOORBELL_STATE) } />
<Text>{ LocalizeText('navigator.roomsettings.doormode.doorbell') }</Text>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="radio" name="lockState" checked={ (roomSettingsData.lockState === RoomDataParser.INVISIBLE_STATE) } onChange={ event => handleChange('lock_state', RoomDataParser.INVISIBLE_STATE) } />
<input className="form-check-input" type="radio" name="lockState" checked={ (roomData.lockState === RoomDataParser.INVISIBLE_STATE) && !isTryingPassword } onChange={ event => handleChange('lock_state', RoomDataParser.INVISIBLE_STATE) } />
<Text>{ LocalizeText('navigator.roomsettings.doormode.invisible') }</Text>
</Flex>
<Flex fullWidth gap={ 1 }>
<input className="form-check-input" type="radio" name="lockState" checked={ (roomSettingsData.lockState === RoomDataParser.PASSWORD_STATE) } onChange={ event => handleChange('lock_state', RoomDataParser.PASSWORD_STATE) } />
{ (roomSettingsData.lockState !== RoomDataParser.PASSWORD_STATE) &&
<input className="form-check-input" type="radio" name="lockState" checked={ (roomData.lockState === RoomDataParser.PASSWORD_STATE) || isTryingPassword } onChange={ event => setIsTryingPassword(event.target.checked) } />
{ !isTryingPassword && (roomData.lockState !== RoomDataParser.PASSWORD_STATE) &&
<Text>{ LocalizeText('navigator.roomsettings.doormode.password') }</Text> }
{ (roomSettingsData.lockState === RoomDataParser.PASSWORD_STATE) &&
{ (isTryingPassword || (roomData.lockState === RoomDataParser.PASSWORD_STATE)) &&
<Column gap={ 1 }>
<Text>{ LocalizeText('navigator.roomsettings.doormode.password') }</Text>
<input type="password" className="form-control form-control-sm col-4" value={ roomSettingsData.password ?? '' } onChange={ (e) => handleChange('password', e.target.value) } onBlur={ trySave } placeholder={ LocalizeText('navigator.roomsettings.password') } />
<input type="password" className="form-control form-control-sm col-4" value={ roomSettingsData.confirmPassword ?? '' } onChange={ (e) => handleChange('confirm_password', e.target.value) } onBlur={ trySave } placeholder={ LocalizeText('navigator.roomsettings.passwordconfirm') } />
{ !isPasswordValid() &&
<input type="password" className="form-control form-control-sm col-4" value={ password } onChange={ event => setPassword(event.target.value) } placeholder={ LocalizeText('navigator.roomsettings.password') } onFocus={ event => setIsTryingPassword(true) } />
{ isTryingPassword && (password.length <= 0) &&
<Text bold small variant="danger">
{ LocalizeText('navigator.roomsettings.passwordismandatory') }
</Text> }
<input type="password" className="form-control form-control-sm col-4" value={ confirmPassword } onChange={ event => setConfirmPassword(event.target.value) } onBlur={ saveRoomPassword } placeholder={ LocalizeText('navigator.roomsettings.passwordconfirm') } />
{ isTryingPassword && ((password.length > 0) && (password !== confirmPassword)) &&
<Text bold small variant="danger">
{ LocalizeText('navigator.roomsettings.invalidconfirm') }
</Text> }
@ -63,11 +78,11 @@ export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabView
<Column gap={ 1 }>
<Text bold>{ LocalizeText('navigator.roomsettings.pets') }</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ roomSettingsData.allowPets } onChange={ event => handleChange('allow_pets', event.target.checked) } />
<input className="form-check-input" type="checkbox" checked={ roomData.allowPets } onChange={ event => handleChange('allow_pets', event.target.checked) } />
<Text>{ LocalizeText('navigator.roomsettings.allowpets') }</Text>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ roomSettingsData.allowPetsEat } onChange={ event => handleChange('allow_pets_eat', event.target.checked) } />
<input className="form-check-input" type="checkbox" checked={ roomData.allowPetsEat } onChange={ event => handleChange('allow_pets_eat', event.target.checked) } />
<Text>{ LocalizeText('navigator.roomsettings.allowfoodconsume') }</Text>
</Flex>
</Column>

View File

@ -1,15 +1,18 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { RoomDeleteComposer } from '@nitrots/nitro-renderer';
import { FC } from 'react';
import { CreateLinkEvent, GetMaxVisitorsList, LocalizeText, NotificationUtilities, RoomSettingsData, SendMessageComposer } from '../../../../api';
import { Base, Flex, Text } from '../../../../common';
import { FC, useEffect, useState } from 'react';
import { CreateLinkEvent, GetMaxVisitorsList, IRoomData, LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../api';
import { Base, Column, Flex, Text } from '../../../../common';
import { BatchUpdates } from '../../../../hooks';
import { useNavigatorContext } from '../../NavigatorContext';
const ROOM_NAME_MIN_LENGTH = 3;
const ROOM_NAME_MAX_LENGTH = 60;
const DESC_MAX_LENGTH = 255;
interface NavigatorRoomSettingsTabViewProps
{
roomSettingsData: RoomSettingsData;
roomData: IRoomData;
handleChange: (field: string, value: string | number | boolean) => void;
close: () => void;
}
@ -17,14 +20,16 @@ interface NavigatorRoomSettingsTabViewProps
export const NavigatorRoomSettingsBasicTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
{
const { roomSettingsData = null, handleChange = null, close = null } = props;
const { roomData = null, handleChange = null, close = null } = props;
const [ roomName, setRoomName ] = useState<string>('');
const [ roomDescription, setRoomDescription ] = useState<string>('');
const { categories = null } = useNavigatorContext();
const deleteRoom = () =>
{
NotificationUtilities.confirm(LocalizeText('navigator.roomsettings.deleteroom.confirm.message', [ 'room_name' ], [ roomSettingsData.roomName ] ), () =>
NotificationUtilities.confirm(LocalizeText('navigator.roomsettings.deleteroom.confirm.message', [ 'room_name' ], [ roomData.roomName ] ), () =>
{
SendMessageComposer(new RoomDeleteComposer(roomSettingsData.roomId));
SendMessageComposer(new RoomDeleteComposer(roomData.roomId));
if(close) close();
@ -33,31 +38,60 @@ export const NavigatorRoomSettingsBasicTabView: FC<NavigatorRoomSettingsTabViewP
null, null, null, LocalizeText('navigator.roomsettings.deleteroom.confirm.title'));
}
const saveRoomName = () =>
{
if((roomName === roomData.roomName) || (roomName.length < ROOM_NAME_MIN_LENGTH) || (roomName.length > ROOM_NAME_MAX_LENGTH)) return;
handleChange('name', roomName);
}
const saveRoomDescription = () =>
{
if((roomDescription === roomData.roomDescription) || (roomDescription.length > DESC_MAX_LENGTH)) return;
handleChange('description', roomDescription);
}
useEffect(() =>
{
BatchUpdates(() =>
{
setRoomName(roomData.roomName);
setRoomDescription(roomData.roomDescription);
});
}, [ roomData ]);
return (
<>
<Flex alignItems="center" gap={ 1 }>
<Text className="col-3">{ LocalizeText('navigator.roomname') }</Text>
<input className="form-control form-control-sm" value={ roomSettingsData.roomName } onChange={ event => handleChange('name', event.target.value) } onBlur={ event => handleChange('save', null) } />
<Column fullWidth gap={ 0 }>
<input className="form-control form-control-sm" value={ roomName } maxLength={ ROOM_NAME_MAX_LENGTH } onChange={ event => setRoomName(event.target.value) } onBlur={ saveRoomName } />
{ (roomName.length < ROOM_NAME_MIN_LENGTH) &&
<Text bold small variant="danger">
{ LocalizeText('navigator.roomsettings.roomnameismandatory') }
</Text> }
</Column>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<Text className="col-3">{ LocalizeText('navigator.roomsettings.desc') }</Text>
<textarea className="form-control form-control-sm" value={ roomSettingsData.roomDescription } onChange={ event => handleChange('description', event.target.value) } onBlur={ event => handleChange('save', null) } maxLength={ DESC_MAX_LENGTH } />
<textarea className="form-control form-control-sm" value={ roomDescription } maxLength={ DESC_MAX_LENGTH } onChange={ event => setRoomDescription(event.target.value) } onBlur={ saveRoomDescription } />
</Flex>
<Flex alignItems="center" gap={ 1 }>
<Text className="col-3">{ LocalizeText('navigator.category') }</Text>
<select className="form-select form-select-sm" value={ roomSettingsData.categoryId } onChange={ event => handleChange('category', event.target.value) }>
<select className="form-select form-select-sm" value={ roomData.categoryId } onChange={ event => handleChange('category', event.target.value) }>
{ categories && categories.map(category => <option key={ category.id } value={ category.id }>{ LocalizeText(category.name) }</option>) }
</select>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<Text className="col-3">{ LocalizeText('navigator.maxvisitors') }</Text>
<select className="form-select form-select-sm" value={ roomSettingsData.userCount } onChange={ event => handleChange('max_visitors', event.target.value) }>
<select className="form-select form-select-sm" value={ roomData.userCount } onChange={ event => handleChange('max_visitors', event.target.value) }>
{ GetMaxVisitorsList && GetMaxVisitorsList.map(value => <option key={ value } value={ value }>{ value }</option>) }
</select>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<Text className="col-3">{ LocalizeText('navigator.tradesettings') }</Text>
<select className="form-select form-select-sm" value={ roomSettingsData.tradeState } onChange={ event => handleChange('trade_state', event.target.value) }>
<select className="form-select form-select-sm" value={ roomData.tradeState } onChange={ event => handleChange('trade_state', event.target.value) }>
<option value="0">{ LocalizeText('navigator.roomsettings.trade_not_allowed') }</option>
<option value="1">{ LocalizeText('navigator.roomsettings.trade_not_with_Controller') }</option>
<option value="2">{ LocalizeText('navigator.roomsettings.trade_allowed') }</option>
@ -65,7 +99,7 @@ export const NavigatorRoomSettingsBasicTabView: FC<NavigatorRoomSettingsTabViewP
</Flex>
<Flex alignItems="center" gap={ 1 }>
<Base className="col-3" />
<input className="form-check-input" type="checkbox" checked={ roomSettingsData.allowWalkthrough } onChange={ event => handleChange('allow_walkthrough', event.target.checked) } />
<input className="form-check-input" type="checkbox" checked={ roomData.allowWalkthrough } onChange={ event => handleChange('allow_walkthrough', event.target.checked) } />
<Text>{ LocalizeText('navigator.roomsettings.allow_walk_through') }</Text>
</Flex>
<Text variant="danger" underline bold pointer className="d-flex justify-content-center align-items-center gap-1" onClick={ deleteRoom }>

View File

@ -1,45 +1,103 @@
import { RoomUnbanUserComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { LocalizeText, RoomSettingsData, SendMessageComposer } from '../../../../api';
import { Base, Button, Column, Grid, Text } from '../../../../common';
import { BannedUserData, BannedUsersFromRoomEvent, RoomBannedUsersComposer, RoomUnbanUserComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
import { Button, Column, Flex, Grid, Text, UserProfileIconView } from '../../../../common';
import { UseMessageEventHook } from '../../../../hooks';
interface NavigatorRoomSettingsTabViewProps
{
roomSettingsData: RoomSettingsData;
roomData: IRoomData;
handleChange: (field: string, value: string | number | boolean) => void;
}
export const NavigatorRoomSettingsModTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
{
const { roomSettingsData = null, handleChange = null } = props;
const { roomData = null, handleChange = null } = props;
const [ selectedUserId, setSelectedUserId ] = useState<number>(-1);
const [ bannedUsers, setBannedUsers ] = useState<BannedUserData[]>([]);
const onBannedUsersFromRoomEvent = useCallback((event: BannedUsersFromRoomEvent) =>
{
const parser = event.getParser();
if(!roomData || (roomData.roomId !== parser.roomId)) return;
setBannedUsers(parser.bannedUsers);
}, [ roomData ]);
UseMessageEventHook(BannedUsersFromRoomEvent, onBannedUsersFromRoomEvent);
const unBanUser = useCallback((userId: number) =>
{
handleChange('unban_user', userId)
setBannedUsers(prevValue =>
{
const newValue = [ ...prevValue ];
const index = newValue.findIndex(value => (value.userId === userId));
if(index >= 0) newValue.splice(index, 1);
return newValue;
})
SendMessageComposer(new RoomUnbanUserComposer(userId, roomData.roomId));
SendMessageComposer(new RoomUnbanUserComposer(userId, roomSettingsData.roomId));
setSelectedUserId(-1);
}, [ roomSettingsData, handleChange ]);
}, [ roomData ]);
useEffect(() =>
{
SendMessageComposer(new RoomBannedUsersComposer(roomData.roomId));
}, [ roomData.roomId ]);
return (
<Grid overflow="auto">
<Column size={ 6 }>
<Text bold>{ LocalizeText('navigator.roomsettings.moderation.banned.users') } ({ roomSettingsData.bannedUsers.length })</Text>
<Column className="bg-white rounded" overflow="hidden">
<Base className="list-container" overflow="auto">
{ roomSettingsData.bannedUsers.map((user, index) =>
<Text bold>{ LocalizeText('navigator.roomsettings.moderation.banned.users') } ({ bannedUsers.length })</Text>
<Flex overflow="hidden" className="bg-white rounded list-container p-2">
<Column fullWidth overflow="auto" gap={ 1 }>
{ bannedUsers && (bannedUsers.length > 0) && bannedUsers.map((user, index) =>
{
return <Text key={ index } className={ ((user.userId === selectedUserId) ? 'selected' : '') } onClick={ event => setSelectedUserId(user.userId)}>{ user.userName }</Text>
return (
<Flex key={ index } shrink alignItems="center" gap={ 1 } overflow="hidden">
<UserProfileIconView userName={ user.userName } />
<Text pointer grow onClick={ event => setSelectedUserId(user.userId) }> { user.userName }</Text>
</Flex>
);
}) }
</Base>
</Column>
</Column>
<Column size={ 6 } justifyContent="end">
<Button disabled={ (selectedUserId < 1) } onClick={ event => unBanUser(selectedUserId) }>
{/* { LocalizeText('navigator.roomsettings.moderation.unban')} {selectedUserId > 0 && roomSettingsData.bannedUsers.get(selectedUserId) } */}
</Flex>
<Button disabled={ (selectedUserId <= 0) } onClick={ event => unBanUser(selectedUserId) }>
{ LocalizeText('navigator.roomsettings.moderation.unban') } {selectedUserId > 0 && bannedUsers.find(user => (user.userId === selectedUserId))?.userName }
</Button>
</Column>
<Column size={ 6 }>
<Column gap={ 1 }>
<Text bold>{ LocalizeText('navigator.roomsettings.moderation.mute.header') }</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ (roomData.moderationSettings.allowMute === 1) } onChange={ event => handleChange('moderation_mute', (event.target.checked ? 1 : 0)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.rights') }</Text>
</Flex>
</Column>
<Column gap={ 1 }>
<Text bold>{LocalizeText('navigator.roomsettings.moderation.kick.header')}</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ (roomData.moderationSettings.allowKick === 0) } onChange={ event => handleChange('moderation_kick', (event.target.checked ? 0 : 2)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.all') }</Text>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ ((roomData.moderationSettings.allowKick === 1) || (roomData.moderationSettings.allowKick === 0)) } disabled={ (roomData.moderationSettings.allowKick === 0) } onChange={ event => handleChange('moderation_kick', (event.target.checked ? 1 : 2)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.rights') }</Text>
</Flex>
</Column>
<Column gap={ 1 }>
<Text bold>{LocalizeText('navigator.roomsettings.moderation.ban.header')}</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ (roomData.moderationSettings.allowBan === 1) } onChange={ event => handleChange('moderation_ban', (event.target.checked ? 1 : 0)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.rights') }</Text>
</Flex>
</Column>
</Column>
</Grid>
);
}

View File

@ -1,82 +1,97 @@
import { RemoveAllRightsMessageComposer, RoomTakeRightsComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
import { LocalizeText, RoomSettingsData, SendMessageComposer } from '../../../../api';
import { FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent, RemoveAllRightsMessageComposer, RoomTakeRightsComposer, RoomUsersWithRightsComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
import { Button, Column, Flex, Grid, Text, UserProfileIconView } from '../../../../common';
import { UseMessageEventHook } from '../../../../hooks';
interface NavigatorRoomSettingsTabViewProps
{
roomSettingsData: RoomSettingsData;
roomData: IRoomData;
handleChange: (field: string, value: string | number | boolean) => void;
}
export const NavigatorRoomSettingsRightsTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
{
const { roomSettingsData = null, handleChange = null } = props;
const { roomData = null } = props;
const [ usersWithRights, setUsersWithRights ] = useState<Map<number, string>>(new Map());
const removeUserRights = useCallback( (userId: number) =>
const onFlatControllersEvent = useCallback((event: FlatControllersEvent) =>
{
handleChange('remove_rights_user', userId);
const parser = event.getParser();
SendMessageComposer(new RoomTakeRightsComposer(userId));
}, [ handleChange ]);
if(!roomData || (roomData.roomId !== parser.roomId)) return;
const removeAllRights = useCallback( () =>
setUsersWithRights(parser.users);
}, [ roomData ]);
UseMessageEventHook(FlatControllersEvent, onFlatControllersEvent);
const onFlatControllerAddedEvent = useCallback((event: FlatControllerAddedEvent) =>
{
handleChange('remove_all_rights', null);
const parser = event.getParser();
SendMessageComposer(new RemoveAllRightsMessageComposer(roomSettingsData.roomId));
}, [ roomSettingsData, handleChange ]);
if(!roomData || (roomData.roomId !== parser.roomId)) return;
setUsersWithRights(prevValue =>
{
const newValue = new Map(prevValue);
newValue.set(parser.data.userId, parser.data.userName);
return newValue;
});
}, [ roomData ]);
UseMessageEventHook(FlatControllerAddedEvent, onFlatControllerAddedEvent);
const onFlatControllerRemovedEvent = useCallback((event: FlatControllerRemovedEvent) =>
{
const parser = event.getParser();
if(!roomData || (roomData.roomId !== parser.roomId)) return;
setUsersWithRights(prevValue =>
{
const newValue = new Map(prevValue);
newValue.delete(parser.userId);
return newValue;
});
}, [ roomData ]);
UseMessageEventHook(FlatControllerRemovedEvent, onFlatControllerRemovedEvent);
useEffect(() =>
{
SendMessageComposer(new RoomUsersWithRightsComposer(roomData.roomId));
}, [ roomData.roomId ]);
return (
<Grid>
<Column size={ 6 }>
<Text bold>
{ LocalizeText('navigator.flatctrls.userswithrights', [ 'displayed', 'total' ], [ roomSettingsData.usersWithRights.size.toString(), roomSettingsData.usersWithRights.size.toString() ]) }
{ LocalizeText('navigator.flatctrls.userswithrights', [ 'displayed', 'total' ], [ usersWithRights.size.toString(), usersWithRights.size.toString() ]) }
</Text>
<Flex overflow="hidden" className="bg-white rounded list-container p-2">
<Column fullWidth overflow="auto" gap={ 1 }>
{ Array.from(roomSettingsData.usersWithRights.entries()).map(([id, name], index) =>
{ Array.from(usersWithRights.entries()).map(([ id, name ], index) =>
{
return (
<Flex key={ index } shrink alignItems="center" gap={ 1 } overflow="hidden">
<UserProfileIconView userName={ name } />
<Text pointer grow key={index} onClick={ event => removeUserRights(id) }> { name }</Text>
<Text pointer grow onClick={ event => SendMessageComposer(new RoomTakeRightsComposer(id)) }> { name }</Text>
</Flex>
);
}) }
</Column>
</Flex>
<Button variant="danger" disabled={ !roomSettingsData.usersWithRights.size } onClick={ removeAllRights } >
</Column>
<Column size={ 6 } justifyContent="end">
<Button variant="danger" disabled={ !usersWithRights.size } onClick={ event => SendMessageComposer(new RemoveAllRightsMessageComposer(roomData.roomId)) } >
{ LocalizeText('navigator.flatctrls.clear') }
</Button>
</Column>
<Column size={ 6 }>
<Column gap={ 1 }>
<Text bold>{ LocalizeText('navigator.roomsettings.moderation.mute.header') }</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ (roomSettingsData.muteState === 1) } onChange={ event => handleChange('moderation_mute', (event.target.checked ? 1 : 0)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.rights') }</Text>
</Flex>
</Column>
<Column gap={ 1 }>
<Text bold>{LocalizeText('navigator.roomsettings.moderation.kick.header')}</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ (roomSettingsData.kickState === 0) } onChange={ event => handleChange('moderation_kick', (event.target.checked ? 0 : 2)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.all') }</Text>
</Flex>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ ((roomSettingsData.kickState === 1) || (roomSettingsData.kickState === 0)) } disabled={ (roomSettingsData.kickState === 0) } onChange={ event => handleChange('moderation_kick', (event.target.checked ? 1 : 2)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.rights') }</Text>
</Flex>
</Column>
<Column gap={ 1 }>
<Text bold>{LocalizeText('navigator.roomsettings.moderation.ban.header')}</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={ (roomSettingsData.banState === 1) } onChange={ event => handleChange('moderation_ban', (event.target.checked ? 1 : 0)) } />
<Text>{ LocalizeText('navigator.roomsettings.moderation.rights') }</Text>
</Flex>
</Column>
</Column>
</Grid>
);
}

View File

@ -1,9 +1,8 @@
import { RoomBannedUsersComposer, RoomSettingsEvent, RoomUsersWithRightsComposer, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
import { BannedUsersFromRoomEvent, FlatControllerAddedEvent, FlatControllerRemovedEvent, FlatControllersEvent } from '@nitrots/nitro-renderer/src/nitro/communication/messages/incoming/roomsettings';
import { RoomBannedUsersComposer, RoomDataParser, RoomSettingsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { LocalizeText, RoomSettingsData, SendMessageComposer } from '../../../../api';
import { IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../common';
import { UseMessageEventHook } from '../../../../hooks';
import { BatchUpdates, UseMessageEventHook } from '../../../../hooks';
import { NavigatorRoomSettingsAccessTabView } from './NavigatorRoomSettingsAccessTabView';
import { NavigatorRoomSettingsBasicTabView } from './NavigatorRoomSettingsBasicTabView';
import { NavigatorRoomSettingsModTabView } from './NavigatorRoomSettingsModTabView';
@ -20,248 +19,170 @@ const TABS: string[] = [
export const NavigatorRoomSettingsView: FC<{}> = props =>
{
const [ roomSettingsData, setRoomSettingsData ] = useState<RoomSettingsData>(null);
const [ roomData, setRoomData ] = useState<IRoomData>(null);
const [ currentTab, setCurrentTab ] = useState(TABS[0]);
const onFlatControllersEvent = useCallback((event: FlatControllersEvent) =>
{
const parser = event.getParser();
if(!parser || !roomSettingsData) return;
if(roomSettingsData.roomId !== parser.roomId) return;
const data = Object.assign({}, roomSettingsData);
data.usersWithRights = new Map(parser.users);
setRoomSettingsData(data);
}, [ roomSettingsData] );
UseMessageEventHook(FlatControllersEvent, onFlatControllersEvent);
const onFlatControllerAddedEvent = useCallback((event: FlatControllerAddedEvent) =>
{
const parser = event.getParser();
if(!parser || !roomSettingsData) return;
if(roomSettingsData.roomId !== parser.roomId) return;
const data = Object.assign({}, roomSettingsData);
// add new controller
setRoomSettingsData(data);
}, [ roomSettingsData] );
UseMessageEventHook(FlatControllerAddedEvent, onFlatControllerAddedEvent);
const onFlatControllerRemovedEvent = useCallback((event: FlatControllerRemovedEvent) =>
{
const parser = event.getParser();
if(!parser || !roomSettingsData) return;
if(roomSettingsData.roomId !== parser.roomId) return;
const data = Object.assign({}, roomSettingsData);
// remove controller
setRoomSettingsData(data);
}, [ roomSettingsData] );
UseMessageEventHook(FlatControllerRemovedEvent, onFlatControllerRemovedEvent);
const updateSettings = useCallback((roomSettings: RoomSettingsData) =>
{
setRoomSettingsData(roomSettings);
}, [ setRoomSettingsData ]);
const onRoomSettingsEvent = useCallback((event: RoomSettingsEvent) =>
{
const parser = event.getParser();
if(!parser) return;
setRoomSettingsData(new RoomSettingsData(parser));
SendMessageComposer(new RoomUsersWithRightsComposer(parser.roomId));
setRoomData({
roomId: parser.roomId,
roomName: parser.name,
roomDescription: parser.description,
categoryId: parser.categoryId,
userCount: parser.userCount,
tags: parser.tags,
tradeState: parser.tradeMode,
allowWalkthrough: parser.allowWalkthrough,
lockState: parser.state,
password: null,
allowPets: parser.allowPets,
allowPetsEat: parser.allowPetsEat,
hideWalls: parser.hideWalls,
wallThickness: parser.thicknessWall,
floorThickness: parser.thicknessFloor,
chatSettings: {
mode: parser.chatSettings.mode,
weight: parser.chatSettings.weight,
speed: parser.chatSettings.speed,
distance: parser.chatSettings.distance,
protection: parser.chatSettings.protection
},
moderationSettings: {
allowMute: parser.moderationSettings.allowMute,
allowKick: parser.moderationSettings.allowKick,
allowBan: parser.moderationSettings.allowBan
}
});
SendMessageComposer(new RoomBannedUsersComposer(parser.roomId));
}, []);
UseMessageEventHook(RoomSettingsEvent, onRoomSettingsEvent);
const onBannedUsersFromRoomEvent = useCallback((event: BannedUsersFromRoomEvent) =>
const close = () =>
{
const parser = event.getParser();
if(!parser || !roomSettingsData) return;
if(roomSettingsData.roomId !== parser.roomId) return;
const data = Object.assign({}, roomSettingsData);
data.bannedUsers = parser.bannedUsers;
setRoomSettingsData(data);
}, [roomSettingsData]);
UseMessageEventHook(BannedUsersFromRoomEvent, onBannedUsersFromRoomEvent);
const saveSettings = useCallback((data: RoomSettingsData) =>
BatchUpdates(() =>
{
SendMessageComposer(
new SaveRoomSettingsComposer(
data.roomId,
data.roomName,
data.roomDescription,
data.lockState,
data.password,
data.userCount,
data.categoryId,
data.tags.length,
data.tags,
data.tradeState,
data.allowPets,
data.allowPetsEat,
data.allowWalkthrough,
data.hideWalls,
data.wallThickness,
data.floorThickness,
data.muteState,
data.kickState,
data.banState,
data.chatBubbleMode,
data.chatBubbleWeight,
data.chatBubbleSpeed,
data.chatDistance,
data.chatFloodProtection
));
}, []);
const processAction = useCallback((action: string) =>
{
switch(action)
{
case 'close':
setRoomSettingsData(null);
setRoomData(null);
setCurrentTab(TABS[0]);
return;
});
}
}, [ setRoomSettingsData ]);
const handleChange = useCallback((field: string, value: string | number | boolean) =>
const handleChange = (field: string, value: string | number | boolean) =>
{
const roomSettings = Object.assign({}, roomSettingsData);
let save = true;
setRoomData(prevValue =>
{
const newValue = { ...prevValue };
switch(field)
{
case 'name':
roomSettings.roomName = String(value);
save = false;
newValue.roomName = String(value);
break;
case 'description':
roomSettings.roomDescription = String(value);
save = false;
newValue.roomDescription = String(value);
break;
case 'category':
roomSettings.categoryId = Number(value);
newValue.categoryId = Number(value);
break;
case 'max_visitors':
roomSettings.userCount = Number(value);
newValue.userCount = Number(value);
break;
case 'trade_state':
roomSettings.tradeState = Number(value);
newValue.tradeState = Number(value);
break;
case 'allow_walkthrough':
roomSettings.allowWalkthrough = Boolean(value);
newValue.allowWalkthrough = Boolean(value);
break;
case 'allow_pets':
roomSettings.allowPets = Boolean(value);
newValue.allowPets = Boolean(value);
break;
case 'allow_pets_eat':
roomSettings.allowPetsEat = Boolean(value);
newValue.allowPetsEat = Boolean(value);
break;
case 'hide_walls':
roomSettings.hideWalls = Boolean(value);
newValue.hideWalls = Boolean(value);
break;
case 'wall_thickness':
roomSettings.wallThickness = Number(value);
newValue.wallThickness = Number(value);
break;
case 'floor_thickness':
roomSettings.floorThickness = Number(value);
newValue.floorThickness = Number(value);
break;
case 'lock_state':
roomSettings.lockState = Number(value);
if(Number(value) === 3) save = false;
newValue.lockState = Number(value);
break;
case 'password':
roomSettings.password = String(value);
save = false;
break;
case 'confirm_password':
roomSettings.confirmPassword = String(value);
save = false;
newValue.lockState = RoomDataParser.PASSWORD_STATE;
newValue.password = String(value);
break;
case 'moderation_mute':
roomSettings.muteState = Number(value);
newValue.moderationSettings.allowMute = Number(value);
break;
case 'moderation_kick':
roomSettings.kickState = Number(value);
newValue.moderationSettings.allowKick = Number(value);
break;
case 'moderation_ban':
roomSettings.banState = Number(value);
newValue.moderationSettings.allowBan = Number(value);
break;
case 'bubble_mode':
roomSettings.chatBubbleMode = Number(value);
newValue.chatSettings.mode = Number(value);
break;
case 'chat_weight':
roomSettings.chatBubbleWeight = Number(value);
newValue.chatSettings.weight = Number(value);
break;
case 'bubble_speed':
roomSettings.chatBubbleSpeed = Number(value);
newValue.chatSettings.speed = Number(value);
break;
case 'flood_protection':
roomSettings.chatFloodProtection = Number(value);
newValue.chatSettings.protection = Number(value);
break;
case 'chat_distance':
roomSettings.chatDistance = Number(value);
save = false;
break;
case 'unban_user': {
const index = roomSettings.bannedUsers.findIndex(user => (user.userId === Number(value)))
if(index > -1) roomSettings.bannedUsers.splice(index, 1);
save = false;
break;
}
case 'remove_rights_user':
roomSettings.usersWithRights.delete(Number(value));
save = false;
break;
case 'remove_all_rights':
roomSettings.usersWithRights.clear();
save = false;
break;
case 'save':
save = true;
newValue.chatSettings.distance = Number(value);
break;
}
setRoomSettingsData(roomSettings);
SendMessageComposer(
new SaveRoomSettingsComposer(
newValue.roomId,
newValue.roomName,
newValue.roomDescription,
newValue.lockState,
newValue.password,
newValue.userCount,
newValue.categoryId,
newValue.tags.length,
newValue.tags,
newValue.tradeState,
newValue.allowPets,
newValue.allowPetsEat,
newValue.allowWalkthrough,
newValue.hideWalls,
newValue.wallThickness,
newValue.floorThickness,
newValue.moderationSettings.allowMute,
newValue.moderationSettings.allowKick,
newValue.moderationSettings.allowBan,
newValue.chatSettings.mode,
newValue.chatSettings.weight,
newValue.chatSettings.speed,
newValue.chatSettings.distance,
newValue.chatSettings.protection
));
if(save) saveSettings(roomSettings);
}, [ roomSettingsData, saveSettings ]);
return newValue;
});
}
if(!roomSettingsData) return null;
if(!roomData) return null;
return (
<NitroCardView uniqueKey="nitro-room-settings" className="nitro-room-settings">
<NitroCardHeaderView headerText={ LocalizeText('navigator.roomsettings') } onCloseClick={ () => processAction('close') } />
<NitroCardHeaderView headerText={ LocalizeText('navigator.roomsettings') } onCloseClick={ close } />
<NitroCardTabsView>
{ TABS.map(tab =>
{
@ -269,16 +190,16 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
}) }
</NitroCardTabsView>
<NitroCardContentView>
{ currentTab === TABS[0] &&
<NavigatorRoomSettingsBasicTabView roomSettingsData={ roomSettingsData } handleChange={ handleChange } close={ () => processAction('close') } /> }
{ currentTab === TABS[1] &&
<NavigatorRoomSettingsAccessTabView roomSettingsData={ roomSettingsData } handleChange={ handleChange } /> }
{ currentTab === TABS[2] &&
<NavigatorRoomSettingsRightsTabView roomSettingsData= {roomSettingsData } handleChange={ handleChange } /> }
{ currentTab === TABS[3] &&
<NavigatorRoomSettingsVipChatTabView roomSettingsData={ roomSettingsData } handleChange={ handleChange } /> }
{ currentTab === TABS[4] &&
<NavigatorRoomSettingsModTabView roomSettingsData={ roomSettingsData } handleChange={ handleChange } /> }
{ (currentTab === TABS[0]) &&
<NavigatorRoomSettingsBasicTabView roomData={ roomData } handleChange={ handleChange } close={ close } /> }
{ (currentTab === TABS[1]) &&
<NavigatorRoomSettingsAccessTabView roomData={ roomData } handleChange={ handleChange } /> }
{ (currentTab === TABS[2]) &&
<NavigatorRoomSettingsRightsTabView roomData= {roomData } handleChange={ handleChange } /> }
{ (currentTab === TABS[3]) &&
<NavigatorRoomSettingsVipChatTabView roomData={ roomData } handleChange={ handleChange } /> }
{ (currentTab === TABS[4]) &&
<NavigatorRoomSettingsModTabView roomData={ roomData } handleChange={ handleChange } /> }
</NitroCardContentView>
</NitroCardView>
);

View File

@ -1,16 +1,23 @@
import { FC } from 'react';
import { LocalizeText, RoomSettingsData } from '../../../../api';
import { RoomChatSettings } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { IRoomData, LocalizeText } from '../../../../api';
import { Column, Flex, Grid, Text } from '../../../../common';
interface NavigatorRoomSettingsTabViewProps
{
roomSettingsData: RoomSettingsData;
roomData: IRoomData;
handleChange: (field: string, value: string | number | boolean) => void;
}
export const NavigatorRoomSettingsVipChatTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
{
const { roomSettingsData = null, handleChange = null } = props;
const { roomData = null, handleChange = null } = props;
const [ chatDistance, setChatDistance ] = useState<number>(0);
useEffect(() =>
{
setChatDistance(roomData.chatSettings.distance);
}, [ roomData.chatSettings ]);
return (
<>
@ -22,41 +29,41 @@ export const NavigatorRoomSettingsVipChatTabView: FC<NavigatorRoomSettingsTabVie
<Column size={ 6 } gap={ 1 }>
<Text bold>{LocalizeText('navigator.roomsettings.chat_settings')}</Text>
<Text>{LocalizeText('navigator.roomsettings.chat_settings.info')}</Text>
<select className="form-select form-select-sm" value={roomSettingsData.chatBubbleMode} onChange={event => handleChange('bubble_mode', event.target.value)}>
<option value="0">{LocalizeText('navigator.roomsettings.chat.mode.free.flow')}</option>
<option value="1">{LocalizeText('navigator.roomsettings.chat.mode.line.by.line')}</option>
<select className="form-select form-select-sm" value={ roomData.chatSettings.mode } onChange={ event => handleChange('bubble_mode', event.target.value) }>
<option value={ RoomChatSettings.CHAT_MODE_FREE_FLOW }>{ LocalizeText('navigator.roomsettings.chat.mode.free.flow') }</option>
<option value={ RoomChatSettings.CHAT_MODE_LINE_BY_LINE }>{ LocalizeText('navigator.roomsettings.chat.mode.line.by.line') }</option>
</select>
<select className="form-select form-select-sm" value={roomSettingsData.chatBubbleWeight} onChange={event => handleChange('chat_weight', event.target.value)}>
<option value="1">{LocalizeText('navigator.roomsettings.chat.bubbles.width.normal')}</option>
<option value="2">{LocalizeText('navigator.roomsettings.chat.bubbles.width.thin')}</option>
<option value="0">{LocalizeText('navigator.roomsettings.chat.bubbles.width.wide')}</option>
<select className="form-select form-select-sm" value={ roomData.chatSettings.weight } onChange={ event => handleChange('chat_weight', event.target.value) }>
<option value={ RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL }>{ LocalizeText('navigator.roomsettings.chat.bubbles.width.normal') }</option>
<option value={ RoomChatSettings.CHAT_BUBBLE_WIDTH_THIN }>{ LocalizeText('navigator.roomsettings.chat.bubbles.width.thin') }</option>
<option value={ RoomChatSettings.CHAT_BUBBLE_WIDTH_WIDE }>{ LocalizeText('navigator.roomsettings.chat.bubbles.width.wide') }</option>
</select>
<select className="form-select form-select-sm" value={roomSettingsData.chatBubbleSpeed} onChange={event => handleChange('bubble_speed', event.target.value)}>
<option value="0">{LocalizeText('navigator.roomsettings.chat.speed.fast')}</option>
<option value="1">{LocalizeText('navigator.roomsettings.chat.speed.normal')}</option>
<option value="2">{LocalizeText('navigator.roomsettings.chat.speed.slow')}</option>
<select className="form-select form-select-sm" value={ roomData.chatSettings.speed } onChange={ event => handleChange('bubble_speed', event.target.value) }>
<option value={ RoomChatSettings.CHAT_SCROLL_SPEED_FAST }>{ LocalizeText('navigator.roomsettings.chat.speed.fast') }</option>
<option value={ RoomChatSettings.CHAT_SCROLL_SPEED_NORMAL }>{ LocalizeText('navigator.roomsettings.chat.speed.normal') }</option>
<option value={ RoomChatSettings.CHAT_SCROLL_SPEED_SLOW }>{ LocalizeText('navigator.roomsettings.chat.speed.slow') }</option>
</select>
<select className="form-select form-select-sm" value={roomSettingsData.chatFloodProtection} onChange={event => handleChange('flood_protection', event.target.value)}>
<option value="0">{LocalizeText('navigator.roomsettings.chat.flood.loose')}</option>
<option value="1">{LocalizeText('navigator.roomsettings.chat.flood.normal')}</option>
<option value="2">{LocalizeText('navigator.roomsettings.chat.flood.strict')}</option>
<select className="form-select form-select-sm" value={ roomData.chatSettings.protection } onChange={ event => handleChange('flood_protection', event.target.value) }>
<option value={ RoomChatSettings.FLOOD_FILTER_LOOSE }>{ LocalizeText('navigator.roomsettings.chat.flood.loose') }</option>
<option value={ RoomChatSettings.FLOOD_FILTER_NORMAL }>{ LocalizeText('navigator.roomsettings.chat.flood.normal') }</option>
<option value={ RoomChatSettings.FLOOD_FILTER_STRICT }>{ LocalizeText('navigator.roomsettings.chat.flood.strict') }</option>
</select>
<Text>{ LocalizeText('navigator.roomsettings.chat_settings.hearing.distance') }</Text>
<input type="number" min="0" className="form-control form-control-sm" value={roomSettingsData.chatDistance} onChange={event => handleChange('chat_distance', event.target.valueAsNumber)} onBlur={ event => handleChange('save', null) } />
<input type="number" min="0" className="form-control form-control-sm" value={ chatDistance } onChange={ event => setChatDistance(event.target.valueAsNumber) } onBlur={ event => handleChange('chat_distance', chatDistance) } />
</Column>
<Column size={ 6 } gap={ 1 }>
<Text bold>{LocalizeText('navigator.roomsettings.vip_settings')}</Text>
<Flex alignItems="center" gap={ 1 }>
<input className="form-check-input" type="checkbox" checked={roomSettingsData.hideWalls} onChange={(e) => handleChange('hide_walls', e.target.checked)} />
<input className="form-check-input" type="checkbox" checked={ roomData.hideWalls } onChange={ event => handleChange('hide_walls', event.target.checked) } />
<Text>{LocalizeText('navigator.roomsettings.hide_walls')}</Text>
</Flex>
<select className="form-select form-select-sm" value={roomSettingsData.wallThickness} onChange={event => handleChange('wall_thickness', event.target.value)}>
<select className="form-select form-select-sm" value={ roomData.wallThickness } onChange={ event => handleChange('wall_thickness', event.target.value) }>
<option value="0">{ LocalizeText('navigator.roomsettings.wall_thickness.normal') }</option>
<option value="1">{ LocalizeText('navigator.roomsettings.wall_thickness.thick') }</option>
<option value="-1">{ LocalizeText('navigator.roomsettings.wall_thickness.thin') }</option>
<option value="-2">{ LocalizeText('navigator.roomsettings.wall_thickness.thinnest') }</option>
</select>
<select className="form-select form-select-sm" value={roomSettingsData.floorThickness} onChange={event => handleChange('floor_thickness', event.target.value)}>
<select className="form-select form-select-sm" value={roomData.floorThickness} onChange={ event => handleChange('floor_thickness', event.target.value) }>
<option value="0">{ LocalizeText('navigator.roomsettings.floor_thickness.normal') }</option>
<option value="1">{ LocalizeText('navigator.roomsettings.floor_thickness.thick') }</option>
<option value="-1">{ LocalizeText('navigator.roomsettings.floor_thickness.thin') }</option>

View File

@ -17,7 +17,7 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
const { roomData = null, children = null, thumbnail = false, ...rest } = props;
const { setDoorData = null } = useNavigatorContext();
function getUserCounterColor(): string
const getUserCounterColor = () =>
{
const num: number = (100 * (roomData.userCount / roomData.maxUserCount));