mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-30 08:50:51 +01:00
Merge branch 'feature/room-settings' into dev
This commit is contained in:
commit
fe22d0b183
26
src/events/friend-list/FriendListContentEvent.ts
Normal file
26
src/events/friend-list/FriendListContentEvent.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { MessengerFriend } from '../../views/friend-list/common/MessengerFriend';
|
||||
import { FriendListEvent } from './FriendListEvent';
|
||||
|
||||
export class FriendListContentEvent extends FriendListEvent
|
||||
{
|
||||
public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT';
|
||||
|
||||
private _friends: Map<number, string>;
|
||||
|
||||
constructor(friends: MessengerFriend[])
|
||||
{
|
||||
super(FriendListContentEvent.FRIEND_LIST_CONTENT);
|
||||
|
||||
this._friends = new Map();
|
||||
|
||||
friends.forEach(entry =>
|
||||
{
|
||||
this._friends.set(entry.id, entry.name);
|
||||
});
|
||||
}
|
||||
|
||||
public get friends(): Map<number, string>
|
||||
{
|
||||
return this._friends;
|
||||
}
|
||||
}
|
@ -4,4 +4,5 @@ export class FriendListEvent extends NitroEvent
|
||||
{
|
||||
public static SHOW_FRIEND_LIST: string = 'IE_SHOW_FRIEND_LIST';
|
||||
public static TOGGLE_FRIEND_LIST: string = 'IE_TOGGLE_FRIEND_LIST';
|
||||
public static REQUEST_FRIEND_LIST: string = 'FLSFRE_REQUEST_FRIEND_LIST';
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
|
||||
import React, { FC, useCallback, useEffect, useReducer, useState } from 'react';
|
||||
import { FC, useCallback, useEffect, useReducer, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { GetRoomSession, LocalizeText } from '../../api';
|
||||
import { FriendEnteredRoomEvent, FriendListEvent } from '../../events';
|
||||
import { FriendListContentEvent } from '../../events/friend-list/FriendListContentEvent';
|
||||
import { FriendListSendFriendRequestEvent } from '../../events/friend-list/FriendListSendFriendRequestEvent';
|
||||
import { useRoomEngineEvent } from '../../hooks/events';
|
||||
import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event';
|
||||
@ -35,12 +36,17 @@ export const FriendListView: FC<FriendListViewProps> = props =>
|
||||
case FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST:
|
||||
const requestEvent = (event as FriendListSendFriendRequestEvent);
|
||||
return;
|
||||
case FriendListEvent.REQUEST_FRIEND_LIST:
|
||||
console.log('requested');
|
||||
dispatchUiEvent(new FriendListContentEvent(friendListState.friends));
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
}, [friendListState.friends]);
|
||||
|
||||
useUiEvent(FriendListEvent.SHOW_FRIEND_LIST, onFriendListEvent);
|
||||
useUiEvent(FriendListEvent.TOGGLE_FRIEND_LIST, onFriendListEvent);
|
||||
useUiEvent(FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendListEvent);
|
||||
useUiEvent(FriendListEvent.REQUEST_FRIEND_LIST, onFriendListEvent);
|
||||
|
||||
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) =>
|
||||
{
|
||||
|
@ -20,7 +20,6 @@ export default class RoomSettingsData
|
||||
public allowPetsEat: boolean;
|
||||
|
||||
public usersWithRights: Map<number, string>;
|
||||
public friendsWithoutRights: Map<number, string>;
|
||||
|
||||
public hideWalls: boolean;
|
||||
public wallThickness: number;
|
||||
@ -59,7 +58,6 @@ export default class RoomSettingsData
|
||||
this.allowPetsEat = parser.allowPetsEat;
|
||||
|
||||
this.usersWithRights = new Map<number, string>();
|
||||
this.friendsWithoutRights = new Map<number, string>();
|
||||
|
||||
this.hideWalls = parser.hideWalls;
|
||||
this.wallThickness = parser.thicknessWall;
|
||||
@ -74,26 +72,5 @@ export default class RoomSettingsData
|
||||
this.kickState = parser.moderationSettings.allowKick;
|
||||
this.banState = parser.moderationSettings.allowBan;
|
||||
this.bannedUsers = new Map<number, string>();
|
||||
this.selectedUserToUnban = 0;
|
||||
}
|
||||
|
||||
public selectUserToUnban(userId: number): void
|
||||
{
|
||||
if(this.selectedUserToUnban === userId)
|
||||
{
|
||||
this.selectedUserToUnban = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.selectedUserToUnban = userId;
|
||||
}
|
||||
}
|
||||
|
||||
public get selectedUsernameToUnban(): string
|
||||
{
|
||||
if(this.selectedUserToUnban > 0)
|
||||
return this.bannedUsers.get(this.selectedUserToUnban);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -4,4 +4,50 @@
|
||||
.content-area {
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
.user-rights-container {
|
||||
|
||||
.row {
|
||||
|
||||
.col:nth-child(even) {
|
||||
//background: $light !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-container {
|
||||
max-height: 100px;
|
||||
min-height: 100px;
|
||||
overflow-y: scroll;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
|
||||
&.rights {
|
||||
max-height: 80%;
|
||||
min-height: 80%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
&.friends-rights {
|
||||
max-height: 90%;
|
||||
min-height: 90%;
|
||||
}
|
||||
|
||||
.rights-button
|
||||
{
|
||||
float: right;
|
||||
margin: 2px;
|
||||
font-size: 7px;
|
||||
padding: 3px;
|
||||
min-height: unset;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
&.selected {
|
||||
background-color: cadetblue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,17 @@
|
||||
import { RoomSettingsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { RoomBannedUsersComposer, RoomBannedUsersEvent, RoomSettingsEvent, RoomUsersWithRightsComposer, RoomUsersWithRightsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { FriendListEvent } from '../../../../events';
|
||||
import { FriendListContentEvent } from '../../../../events/friend-list/FriendListContentEvent';
|
||||
import { dispatchUiEvent, useUiEvent } from '../../../../hooks';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages';
|
||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
|
||||
import RoomSettingsData from '../../common/RoomSettingsData';
|
||||
import { NavigatorRoomSettingsAccessTabView } from './views/tab-access/NavigatorRoomSettingsAccessTabView';
|
||||
import { NavigatorRoomSettingsBasicTabView } from './views/tab-basic/NavigatorRoomSettingsBasicTabView';
|
||||
import { NavigatorRoomSettingsModTabView } from './views/tab-mod/NavigatorRoomSettingsModTabView';
|
||||
import { NavigatorRoomSettingsRightsTabView } from './views/tab-rights/NavigatorRoomSettingsRightsTabView';
|
||||
import { NavigatorRoomSettingsVipChatTabView } from './views/tab-vipchat/NavigatorRoomSettingsVipChatTabView';
|
||||
|
||||
const TABS: string[] = [
|
||||
'navigator.roomsettings.tab.1',
|
||||
@ -19,10 +25,10 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
|
||||
{
|
||||
const [ roomSettingsData, setRoomSettingsData ] = useState<RoomSettingsData>(null);
|
||||
const [ currentTab, setCurrentTab ] = useState(TABS[0]);
|
||||
const [ friends, setFriends ] = useState<Map<number, string>>(new Map());
|
||||
|
||||
const updateSettings = useCallback((roomSettings: RoomSettingsData) =>
|
||||
{
|
||||
console.log('update', roomSettings);
|
||||
setRoomSettingsData(roomSettings);
|
||||
}, [ setRoomSettingsData ]);
|
||||
|
||||
@ -33,40 +39,87 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
|
||||
if(!parser) return;
|
||||
|
||||
setRoomSettingsData(new RoomSettingsData(parser));
|
||||
SendMessageHook(new RoomUsersWithRightsComposer(parser.roomId));
|
||||
SendMessageHook(new RoomBannedUsersComposer(parser.roomId));
|
||||
}, []);
|
||||
|
||||
CreateMessageHook(RoomSettingsEvent, onRoomSettingsEvent);
|
||||
const onRoomUsersWithRightsEvent = useCallback((event: RoomUsersWithRightsEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
const save = useCallback(() =>
|
||||
if(!parser || !roomSettingsData) return;
|
||||
|
||||
if(roomSettingsData.roomId !== parser.roomId) return;
|
||||
|
||||
const data = Object.assign({}, roomSettingsData);
|
||||
|
||||
data.usersWithRights = new Map(parser.users);
|
||||
|
||||
setRoomSettingsData(data);
|
||||
}, [roomSettingsData]);
|
||||
|
||||
const onRoomBannedUsersEvent = useCallback((event: RoomBannedUsersEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
if(!parser || !roomSettingsData) return;
|
||||
|
||||
if(roomSettingsData.roomId !== parser.roomId) return;
|
||||
|
||||
const data = Object.assign({}, roomSettingsData);
|
||||
|
||||
data.bannedUsers = new Map(parser.users);
|
||||
|
||||
setRoomSettingsData(data);
|
||||
}, [roomSettingsData]);
|
||||
|
||||
const onFriendsListContentEvent = useCallback((event: FriendListContentEvent) =>
|
||||
{
|
||||
if(!roomSettingsData || !event.friends) return;
|
||||
|
||||
setFriends(event.friends);
|
||||
}, [roomSettingsData]);
|
||||
|
||||
CreateMessageHook(RoomSettingsEvent, onRoomSettingsEvent);
|
||||
CreateMessageHook(RoomUsersWithRightsEvent, onRoomUsersWithRightsEvent);
|
||||
CreateMessageHook(RoomBannedUsersEvent, onRoomBannedUsersEvent);
|
||||
useUiEvent(FriendListContentEvent.FRIEND_LIST_CONTENT, onFriendsListContentEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(roomSettingsData) dispatchUiEvent(new FriendListEvent(FriendListEvent.REQUEST_FRIEND_LIST));
|
||||
}, [roomSettingsData])
|
||||
|
||||
const save = useCallback((data: RoomSettingsData) =>
|
||||
{
|
||||
SendMessageHook(
|
||||
new SaveRoomSettingsComposer(
|
||||
roomSettingsData.roomId,
|
||||
roomSettingsData.roomName,
|
||||
roomSettingsData.roomDescription,
|
||||
roomSettingsData.lockState,
|
||||
roomSettingsData.password,
|
||||
roomSettingsData.userCount,
|
||||
roomSettingsData.categoryId,
|
||||
roomSettingsData.tags.length,
|
||||
roomSettingsData.tags,
|
||||
roomSettingsData.tradeState,
|
||||
roomSettingsData.allowPets,
|
||||
roomSettingsData.allowPetsEat,
|
||||
roomSettingsData.allowWalkthrough,
|
||||
roomSettingsData.hideWalls,
|
||||
roomSettingsData.wallThickness,
|
||||
roomSettingsData.floorThickness,
|
||||
roomSettingsData.muteState,
|
||||
roomSettingsData.kickState,
|
||||
roomSettingsData.banState,
|
||||
roomSettingsData.chatBubbleMode,
|
||||
roomSettingsData.chatBubbleWeight,
|
||||
roomSettingsData.chatBubbleSpeed,
|
||||
roomSettingsData.chatDistance,
|
||||
roomSettingsData.chatFloodProtection
|
||||
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
|
||||
));
|
||||
}, [ roomSettingsData ]);
|
||||
}, []);
|
||||
|
||||
const processAction = useCallback((action: string) =>
|
||||
{
|
||||
@ -93,6 +146,9 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
|
||||
<NitroCardContentView className="text-black px-4">
|
||||
{ currentTab === TABS[0] && <NavigatorRoomSettingsBasicTabView roomSettingsData={ roomSettingsData } setRoomSettingsData={ updateSettings } onSave={ save } /> }
|
||||
{ currentTab === TABS[1] && <NavigatorRoomSettingsAccessTabView roomSettingsData={ roomSettingsData } setRoomSettingsData={ updateSettings } onSave={ save } /> }
|
||||
{ currentTab === TABS[2] && <NavigatorRoomSettingsRightsTabView roomSettingsData= {roomSettingsData } setRoomSettingsData={ updateSettings } onSave={ save } friends={friends} /> }
|
||||
{ currentTab === TABS[3] && <NavigatorRoomSettingsVipChatTabView roomSettingsData={ roomSettingsData } setRoomSettingsData={ updateSettings } onSave={ save } /> }
|
||||
{ currentTab === TABS[4] && <NavigatorRoomSettingsModTabView roomSettingsData={ roomSettingsData } setRoomSettingsData={ updateSettings } onSave={ save } /> }
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
);
|
||||
|
@ -4,5 +4,5 @@ export class NavigatorRoomSettingsTabViewProps
|
||||
{
|
||||
roomSettingsData: RoomSettingsData;
|
||||
setRoomSettingsData: (roomSettings: RoomSettingsData) => void;
|
||||
onSave: () => void;
|
||||
onSave: (data: RoomSettingsData) => void;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { FC, useCallback } from 'react';
|
||||
import { LocalizeText } from '../../../../../../api';
|
||||
import RoomSettingsData from '../../../../common/RoomSettingsData';
|
||||
import { NavigatorRoomSettingsTabViewProps } from '../../NavigatorRoomSettingsView.types';
|
||||
|
||||
export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
|
||||
@ -9,7 +8,7 @@ export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabView
|
||||
|
||||
const handleChange = useCallback((field: string, value: string | number | boolean) =>
|
||||
{
|
||||
const roomSettings = ({ ...roomSettingsData } as RoomSettingsData);
|
||||
const roomSettings = Object.assign({}, roomSettingsData);
|
||||
let save = true;
|
||||
|
||||
switch(field)
|
||||
@ -37,7 +36,7 @@ export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabView
|
||||
|
||||
setRoomSettingsData(roomSettings);
|
||||
|
||||
if(save) onSave();
|
||||
if(save) onSave(roomSettings);
|
||||
}, [ roomSettingsData, setRoomSettingsData, onSave ]);
|
||||
|
||||
const isPasswordValid = useCallback(() =>
|
||||
@ -47,11 +46,13 @@ export const NavigatorRoomSettingsAccessTabView: FC<NavigatorRoomSettingsTabView
|
||||
|
||||
const trySave = useCallback(() =>
|
||||
{
|
||||
if(isPasswordValid()) onSave();
|
||||
}, [ isPasswordValid, onSave ]);
|
||||
if(isPasswordValid()) onSave(roomSettingsData);
|
||||
}, [isPasswordValid, onSave, roomSettingsData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.roomaccess.caption')}</div>
|
||||
<div className="mb-3">{ LocalizeText('navigator.roomsettings.roomaccess.info') }</div>
|
||||
<div className="fw-bold">{ LocalizeText('navigator.roomsettings.doormode') }</div>
|
||||
<div className="form-check">
|
||||
<input className="form-check-input" type="radio" name="lockState" checked={ roomSettingsData.lockState === 0 } onChange={ (e) => handleChange('lock_state', 0) } />
|
||||
|
@ -43,18 +43,18 @@ export const NavigatorRoomSettingsBasicTabView: FC<NavigatorRoomSettingsTabViewP
|
||||
|
||||
setRoomSettingsData(roomSettings);
|
||||
|
||||
if(save) onSave();
|
||||
if(save) onSave(roomSettings);
|
||||
}, [ roomSettingsData, setRoomSettingsData, onSave ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="form-group mb-1">
|
||||
<label>{ LocalizeText('navigator.roomname') }</label>
|
||||
<input className="form-control form-control-sm" value={ roomSettingsData.roomName } onChange={ event => handleChange('name', event.target.value) } onBlur={ onSave } />
|
||||
<input className="form-control form-control-sm" value={ roomSettingsData.roomName } onChange={ event => handleChange('name', event.target.value) } onBlur={ () => onSave(roomSettingsData) } />
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<label>{ LocalizeText('navigator.roomsettings.desc') }</label>
|
||||
<input className="form-control form-control-sm" value={ roomSettingsData.roomDescription } onChange={ event => handleChange('description', event.target.value) } onBlur={ onSave } />
|
||||
<input className="form-control form-control-sm" value={ roomSettingsData.roomDescription } onChange={ event => handleChange('description', event.target.value) } onBlur={ () => onSave(roomSettingsData) } />
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<label>{ LocalizeText('navigator.category') }</label>
|
||||
|
@ -0,0 +1,107 @@
|
||||
import { RoomUnbanUserComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { LocalizeText } from '../../../../../../api';
|
||||
import { SendMessageHook } from '../../../../../../hooks';
|
||||
import { NavigatorRoomSettingsTabViewProps } from '../../NavigatorRoomSettingsView.types';
|
||||
|
||||
export const NavigatorRoomSettingsModTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
|
||||
{
|
||||
const { roomSettingsData = null, setRoomSettingsData = null, onSave = null } = props;
|
||||
const [selectedUserId, setSelectedUserId] = useState<number>(-1);
|
||||
|
||||
const handleChange = useCallback((field: string, value: string | number | boolean) =>
|
||||
{
|
||||
const clone = Object.assign({}, roomSettingsData);
|
||||
let save = true;
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case 'moderation_mute':
|
||||
clone.muteState = Number(value);
|
||||
break;
|
||||
case 'moderation_kick':
|
||||
clone.kickState = Number(value);
|
||||
break;
|
||||
case 'moderation_ban':
|
||||
clone.banState = Number(value);
|
||||
break;
|
||||
}
|
||||
|
||||
setRoomSettingsData(clone);
|
||||
|
||||
if(save) onSave(clone);
|
||||
}, [roomSettingsData, setRoomSettingsData, onSave]);
|
||||
|
||||
const unBanUser = useCallback((userId: number) =>
|
||||
{
|
||||
const clone = Object.assign({}, roomSettingsData);
|
||||
|
||||
clone.bannedUsers.delete(userId);
|
||||
setRoomSettingsData(clone);
|
||||
|
||||
SendMessageHook(new RoomUnbanUserComposer(userId, roomSettingsData.roomId));
|
||||
setSelectedUserId(-1);
|
||||
}, [roomSettingsData, setRoomSettingsData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-3">{LocalizeText('navigator.roomsettings.moderation.header')}</div>
|
||||
<div className="form-group mb-1" >
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.moderation.mute.header')}</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_mute" checked={roomSettingsData.muteState === 0} onChange={(e) => handleChange('moderation_mute', 0)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.none')}</label>
|
||||
</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_mute" checked={roomSettingsData.muteState === 1} onChange={(e) => handleChange('moderation_mute', 1)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.rights')}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group mb-1" >
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.moderation.kick.header')}</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_kick" checked={roomSettingsData.kickState === 0} onChange={(e) => handleChange('moderation_kick', 0)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.all')}</label>
|
||||
</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_kick" checked={roomSettingsData.kickState === 1} onChange={(e) => handleChange('moderation_kick', 1)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.rights')}</label>
|
||||
</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_kick" checked={roomSettingsData.kickState === 2} onChange={(e) => handleChange('moderation_kick', 2)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.none')}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group mb-1" >
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.moderation.ban.header')}</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_ban" checked={roomSettingsData.banState === 0} onChange={(e) => handleChange('moderation_ban', 0)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.none')}</label>
|
||||
</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input className="form-check-input" type="radio" name="moderation_ban" checked={roomSettingsData.banState === 1} onChange={(e) => handleChange('moderation_ban', 1)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.moderation.rights')}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fw-bold mt-3 mb-1">{LocalizeText('navigator.roomsettings.moderation.banned.users')} ({roomSettingsData.bannedUsers.size})</div>
|
||||
<div className="row">
|
||||
<div className="col-6">
|
||||
<div className="list-container">
|
||||
{
|
||||
Array.from(roomSettingsData.bannedUsers.entries()).map(([id, name], index) =>
|
||||
{
|
||||
return <div key={index} className={'list-item' + ((id === selectedUserId) ? ' selected' : '')} onClick={e => setSelectedUserId(id)} >
|
||||
{name}
|
||||
</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6">
|
||||
<button className={'btn btn-primary btn-sm w-100' + ((selectedUserId < 1) ? ' disabled' : '')} onClick={ e => unBanUser(selectedUserId) }>{LocalizeText('navigator.roomsettings.moderation.unban')} {selectedUserId > 0 && roomSettingsData.bannedUsers.get(selectedUserId)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
import { RemoveAllRightsMessageComposer, RoomGiveRightsComposer, RoomTakeRightsComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useMemo } from 'react';
|
||||
import { LocalizeText } from '../../../../../../api';
|
||||
import { SendMessageHook } from '../../../../../../hooks';
|
||||
import { UserProfileIconView } from '../../../../../shared/user-profile-icon/UserProfileIconView';
|
||||
import { NavigatorRoomSettingsRightsTabViewProps } from './NavigatorRoomSettingsRightsTabView.types';
|
||||
|
||||
export const NavigatorRoomSettingsRightsTabView: FC<NavigatorRoomSettingsRightsTabViewProps> = props =>
|
||||
{
|
||||
const { roomSettingsData = null, setRoomSettingsData = null, onSave = null, friends = null } = props;
|
||||
|
||||
const removeUserRights = useCallback( (userId: number) =>
|
||||
{
|
||||
const clone = Object.assign({}, roomSettingsData);
|
||||
|
||||
clone.usersWithRights.delete(userId);
|
||||
|
||||
setRoomSettingsData(clone);
|
||||
SendMessageHook(new RoomTakeRightsComposer(userId));
|
||||
}, [roomSettingsData, setRoomSettingsData]);
|
||||
|
||||
const giveUserRights = useCallback( (userId: number, name: string) =>
|
||||
{
|
||||
const clone = Object.assign({}, roomSettingsData);
|
||||
|
||||
clone.usersWithRights.set(userId, name);
|
||||
|
||||
setRoomSettingsData(clone);
|
||||
SendMessageHook(new RoomGiveRightsComposer(userId));
|
||||
}, [roomSettingsData, setRoomSettingsData]);
|
||||
|
||||
const removeAllRights = useCallback( () =>
|
||||
{
|
||||
const clone = Object.assign({}, roomSettingsData);
|
||||
|
||||
clone.usersWithRights = new Map();
|
||||
|
||||
setRoomSettingsData(clone);
|
||||
SendMessageHook(new RemoveAllRightsMessageComposer(clone.roomId));
|
||||
}, [roomSettingsData, setRoomSettingsData]);
|
||||
|
||||
const friendsWithoutRights = useMemo(() =>
|
||||
{
|
||||
const map = new Map<number, string>();
|
||||
|
||||
friends.forEach((name, id) =>
|
||||
{
|
||||
if(!roomSettingsData.usersWithRights.has(id))
|
||||
map.set(id, name);
|
||||
});
|
||||
|
||||
return map;
|
||||
}, [friends, roomSettingsData]);
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column h-100 overflow-hidden user-rights">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
filter
|
||||
</div>
|
||||
</div>
|
||||
<div className="row h-100">
|
||||
<div className="col-6 d-flex flex-column h-100">
|
||||
<div className="fw-bold mb-1">{ LocalizeText('navigator.flatctrls.userswithrights', [ 'displayed', 'total' ], [ roomSettingsData.usersWithRights.size.toString(), roomSettingsData.usersWithRights.size.toString() ]) }</div>
|
||||
<div className="d-flex flex-column justify-content-between rounded bg-white h-100 overflow-hidden px-2 py-1 user-rights-container">
|
||||
<div className="row row-cols-1 overflow-auto">
|
||||
{ Array.from(roomSettingsData.usersWithRights.entries()).map(([id, name], index) =>
|
||||
{
|
||||
return (
|
||||
<div key={index} className="d-flex align-items-center col w-100" onClick={ () => removeUserRights(id) }>
|
||||
<div className="d-flex align-items-center me-2">
|
||||
<UserProfileIconView userName={ name } />
|
||||
<span>{ name }</span>
|
||||
</div>
|
||||
<i className="fas fa-caret-right fw-bold text-black me-2" />
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<button className="btn btn-danger btn-sm w-100" disabled={ !roomSettingsData.usersWithRights.size } onClick={ removeAllRights } >{ LocalizeText('navigator.flatctrls.clear') }</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 d-flex flex-column h-100">
|
||||
<div className="fw-bold mb-1">{ LocalizeText('navigator.flatctrls.friends', [ 'displayed', 'total' ], [ friendsWithoutRights.size.toString(), friendsWithoutRights.size.toString() ]) }</div>
|
||||
<div className="d-flex flex-column rounded bg-white h-100 overflow-hidden px-2 py-1 user-rights-container">
|
||||
<div className="row row-cols-1 overflow-auto">
|
||||
{ Array.from(friendsWithoutRights.entries()).map(([id, name], index) =>
|
||||
{
|
||||
return (
|
||||
<div key={index} className="d-flex align-items-center col w-100" onClick={ () => giveUserRights(id, name) }>
|
||||
<i className="fas fa-caret-left fw-bold text-black me-2" />
|
||||
<div className="d-flex align-items-center">
|
||||
<UserProfileIconView userName={ name } />
|
||||
<span>{ name }</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
// <div className="row h-100">
|
||||
// <div className="col-6">
|
||||
// <div className="fw-bold mb-2">{LocalizeText('navigator.flatctrls.userswithrights', ['displayed', 'total'], [roomSettingsData.usersWithRights.size.toString(), roomSettingsData.usersWithRights.size.toString()])}</div>
|
||||
// </div>
|
||||
// <div className="col-6">
|
||||
// <div className="fw-bold mb-2">{LocalizeText('navigator.flatctrls.friends', ['displayed', 'total'], [friendsWithoutRights.size.toString(), friendsWithoutRights.size.toString()])}</div>
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className="row h-100">
|
||||
// <div className="col-6 d-flex flex-column h-100">
|
||||
// <div className="row row-cols-1 g-0 overflow-auto">
|
||||
// {
|
||||
// Array.from(roomSettingsData.usersWithRights.entries()).map(([id, name], index) =>
|
||||
// {
|
||||
// return (
|
||||
// <div key={ index } className="col">
|
||||
// <span className="w-100" >{name}</span>
|
||||
// <button className="btn btn-danger btn-sm rights-button" onClick={ () => removeUserRights(id) }>
|
||||
// <i className="fas fa-times" />
|
||||
// </button>
|
||||
// </div>
|
||||
// );
|
||||
// })
|
||||
// }
|
||||
// </div>
|
||||
// <button className={'btn btn-danger btn-sm w-100' + ((roomSettingsData.usersWithRights.size < 1) ? ' disabled' : '')} onClick={ removeAllRights } >{ LocalizeText('navigator.flatctrls.clear') }</button>
|
||||
// </div>
|
||||
// <div className="col-6 d-flex flex-column h-100">
|
||||
// <div className="row row-cols-1 g-0 overflow-auto bg-white h-100">
|
||||
// {
|
||||
// Array.from(friendsWithoutRights.entries()).map(([id, name], index) =>
|
||||
// {
|
||||
// return (
|
||||
// <div key={index} className="col">
|
||||
// <span className="w-100">{name}</span>
|
||||
// <button className="btn btn-success btn-sm rights-button" onClick={ () => giveUserRights(id, name) }>
|
||||
// <i className="fas fa-chevron-left" />
|
||||
// </button>
|
||||
// </div>
|
||||
// );
|
||||
// })
|
||||
// }
|
||||
// </div>
|
||||
// </div >
|
||||
// </div >
|
||||
);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { NavigatorRoomSettingsTabViewProps } from '../../NavigatorRoomSettingsView.types';
|
||||
|
||||
export interface NavigatorRoomSettingsRightsTabViewProps extends NavigatorRoomSettingsTabViewProps
|
||||
{
|
||||
friends: Map<number, string>;
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
import { FC, useCallback } from 'react';
|
||||
import { LocalizeText } from '../../../../../../api';
|
||||
import { NavigatorRoomSettingsTabViewProps } from '../../NavigatorRoomSettingsView.types';
|
||||
|
||||
export const NavigatorRoomSettingsVipChatTabView: FC<NavigatorRoomSettingsTabViewProps> = props =>
|
||||
{
|
||||
const { roomSettingsData = null, setRoomSettingsData = null, onSave = null } = props;
|
||||
|
||||
const handleChange = useCallback((field: string, value: string | number | boolean) =>
|
||||
{
|
||||
const clone = Object.assign({}, roomSettingsData);
|
||||
let save = true;
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case 'hide_walls':
|
||||
clone.hideWalls = Boolean(value);
|
||||
break;
|
||||
case 'wall_thickness':
|
||||
clone.wallThickness = Number(value);
|
||||
break;
|
||||
case 'floor_thickness':
|
||||
clone.floorThickness = Number(value);
|
||||
break;
|
||||
case 'bubble_mode':
|
||||
clone.chatBubbleMode = Number(value);
|
||||
break;
|
||||
case 'chat_weight':
|
||||
clone.chatBubbleWeight = Number(value);
|
||||
break;
|
||||
case 'bubble_speed':
|
||||
clone.chatBubbleSpeed = Number(value);
|
||||
break;
|
||||
case 'flood_protection':
|
||||
clone.chatFloodProtection = Number(value);
|
||||
break;
|
||||
case 'chat_distance':
|
||||
clone.chatDistance = Number(value);
|
||||
save = false;
|
||||
break;
|
||||
}
|
||||
|
||||
setRoomSettingsData(clone);
|
||||
|
||||
if(save) onSave(clone);
|
||||
}, [roomSettingsData, setRoomSettingsData, onSave]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.vip.caption')}</div>
|
||||
<div className="mb-3">{LocalizeText('navigator.roomsettings.vip.info')}</div>
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.vip_settings')}</div>
|
||||
<div className="form-check">
|
||||
<input className="form-check-input" type="checkbox" checked={roomSettingsData.hideWalls} onChange={(e) => handleChange('hide_walls', e.target.checked)} />
|
||||
<label className="form-check-label">{LocalizeText('navigator.roomsettings.hide_walls')}</label>
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<select className="form-select form-select-sm" value={roomSettingsData.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>
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<select className="form-select form-select-sm" value={roomSettingsData.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>
|
||||
<option value="-2">{LocalizeText('navigator.roomsettings.floor_thickness.thinnest')}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="fw-bold">{LocalizeText('navigator.roomsettings.chat_settings')}</div>
|
||||
<div className="mb-2">{LocalizeText('navigator.roomsettings.chat_settings.info')}</div>
|
||||
<div className="form-group mb-1">
|
||||
<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>
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<select className="form-select form-select-sm" value={roomSettingsData.chatBubbleWeight} onChange={event => handleChange('chat_weight', event.target.value)}>
|
||||
<option value="0">{LocalizeText('navigator.roomsettings.chat.bubbles.width.normal')}</option>
|
||||
<option value="1">{LocalizeText('navigator.roomsettings.chat.bubbles.width.thin')}</option>
|
||||
<option value="2">{LocalizeText('navigator.roomsettings.chat.bubbles.width.wide')}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<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>
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<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>
|
||||
</div>
|
||||
<div className="form-group mb-0">
|
||||
<label>{LocalizeText('navigator.roomsettings.chat_settings.hearing.distance')}</label>
|
||||
<input type="number" min="0" className="form-control form-control-sm" value={roomSettingsData.chatDistance} onChange={event => handleChange('chat_distance', event.target.valueAsNumber)} onBlur={() => onSave(roomSettingsData)} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
16
src/views/shared/user-profile-icon/UserProfileIconView.tsx
Normal file
16
src/views/shared/user-profile-icon/UserProfileIconView.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { FC, useCallback } from 'react';
|
||||
import { UserProfileIconViewProps } from './UserProfileIconView.types';
|
||||
|
||||
export const UserProfileIconView: FC<UserProfileIconViewProps> = props =>
|
||||
{
|
||||
const { userId = -1, userName = null } = props;
|
||||
|
||||
const visitProfile = useCallback(() =>
|
||||
{
|
||||
|
||||
}, [ userId, userName ]);
|
||||
|
||||
return (
|
||||
<i className="icon icon-user-profile me-1 cursor-pointer" onClick={ visitProfile } />
|
||||
);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
export interface UserProfileIconViewProps
|
||||
{
|
||||
userId?: number;
|
||||
userName?: string;
|
||||
}
|
Loading…
Reference in New Issue
Block a user