mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-01-19 05:46:27 +01:00
created user and furni choosers
This commit is contained in:
parent
5b6c8d9ce9
commit
4706149342
@ -15,6 +15,7 @@
|
|||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"react-slider": "^1.3.1",
|
"react-slider": "^1.3.1",
|
||||||
"react-transition-group": "^4.4.2",
|
"react-transition-group": "^4.4.2",
|
||||||
|
"react-virtualized": "^9.22.3",
|
||||||
"typescript": "^4.3.5",
|
"typescript": "^4.3.5",
|
||||||
"web-vitals": "^1.1.2"
|
"web-vitals": "^1.1.2"
|
||||||
},
|
},
|
||||||
|
28
src/events/room-widgets/choosers/RoomObjectItem.ts
Normal file
28
src/events/room-widgets/choosers/RoomObjectItem.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
export class RoomObjectItem
|
||||||
|
{
|
||||||
|
private readonly _id: number;
|
||||||
|
private readonly _category: number;
|
||||||
|
private readonly _name: string;
|
||||||
|
|
||||||
|
constructor(id: number, category: number, name: string)
|
||||||
|
{
|
||||||
|
this._id = id;
|
||||||
|
this._category = category;
|
||||||
|
this._name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id(): number
|
||||||
|
{
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get category(): number
|
||||||
|
{
|
||||||
|
return this._category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name(): string
|
||||||
|
{
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
import { RoomWidgetUpdateEvent } from '../../../views/room/events';
|
||||||
|
import { RoomObjectItem } from './RoomObjectItem';
|
||||||
|
|
||||||
|
export class RoomWidgetChooserContentEvent extends RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
public static USER_CHOOSER_CONTENT: string = 'RWCCE_USER_CHOOSER_CONTENT';
|
||||||
|
public static FURNI_CHOOSER_CONTENT: string = 'RWCCE_FURNI_CHOOSER_CONTENT';
|
||||||
|
|
||||||
|
private _items: RoomObjectItem[];
|
||||||
|
private _isAnyRoomController: boolean;
|
||||||
|
|
||||||
|
constructor(type: string, items: RoomObjectItem[], isAnyRoomController: boolean = false)
|
||||||
|
{
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
this._items = items.slice();
|
||||||
|
this._isAnyRoomController = isAnyRoomController;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get items(): RoomObjectItem[]
|
||||||
|
{
|
||||||
|
return this._items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isAnyRoomController(): boolean
|
||||||
|
{
|
||||||
|
return this._isAnyRoomController;
|
||||||
|
}
|
||||||
|
}
|
@ -8,9 +8,11 @@ import { GetRoomEngine } from '../../api/nitro/room/GetRoomEngine';
|
|||||||
import { RoomContextProvider } from './context/RoomContext';
|
import { RoomContextProvider } from './context/RoomContext';
|
||||||
import { RoomWidgetUpdateRoomViewEvent } from './events/RoomWidgetUpdateRoomViewEvent';
|
import { RoomWidgetUpdateRoomViewEvent } from './events/RoomWidgetUpdateRoomViewEvent';
|
||||||
import { IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers';
|
import { IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers';
|
||||||
|
import { FurniChooserWidgetHandler } from './handlers/FurniChooserWidgetHandler';
|
||||||
import { FurnitureContextMenuWidgetHandler } from './handlers/FurnitureContextMenuWidgetHandler';
|
import { FurnitureContextMenuWidgetHandler } from './handlers/FurnitureContextMenuWidgetHandler';
|
||||||
import { FurnitureCustomStackHeightWidgetHandler } from './handlers/FurnitureCustomStackHeightWidgetHandler';
|
import { FurnitureCustomStackHeightWidgetHandler } from './handlers/FurnitureCustomStackHeightWidgetHandler';
|
||||||
import { RoomWidgetRoomToolsHandler } from './handlers/RoomWidgetRoomToolsHandler';
|
import { RoomWidgetRoomToolsHandler } from './handlers/RoomWidgetRoomToolsHandler';
|
||||||
|
import { UserChooserWidgetHandler } from './handlers/UserChooserWidgetHandler';
|
||||||
import { RoomColorView } from './RoomColorView';
|
import { RoomColorView } from './RoomColorView';
|
||||||
import { RoomViewProps } from './RoomView.types';
|
import { RoomViewProps } from './RoomView.types';
|
||||||
import { RoomWidgetsView } from './widgets/RoomWidgetsView';
|
import { RoomWidgetsView } from './widgets/RoomWidgetsView';
|
||||||
@ -44,6 +46,8 @@ export const RoomView: FC<RoomViewProps> = props =>
|
|||||||
widgetHandlerManager.registerHandler(new RoomWidgetChatHandler());
|
widgetHandlerManager.registerHandler(new RoomWidgetChatHandler());
|
||||||
widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
|
widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
|
||||||
widgetHandlerManager.registerHandler(new FurnitureCustomStackHeightWidgetHandler());
|
widgetHandlerManager.registerHandler(new FurnitureCustomStackHeightWidgetHandler());
|
||||||
|
widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler());
|
||||||
|
widgetHandlerManager.registerHandler(new UserChooserWidgetHandler());
|
||||||
|
|
||||||
setWidgetHandler(widgetHandlerManager);
|
setWidgetHandler(widgetHandlerManager);
|
||||||
|
|
||||||
|
108
src/views/room/handlers/FurniChooserWidgetHandler.ts
Normal file
108
src/views/room/handlers/FurniChooserWidgetHandler.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { NitroEvent, RoomObjectCategory, RoomObjectVariable, RoomWidgetEnum } from '@nitrots/nitro-renderer';
|
||||||
|
import { GetNitroInstance, GetRoomEngine, GetSessionDataManager } from '../../../api';
|
||||||
|
import { RoomObjectItem } from '../../../events/room-widgets/choosers/RoomObjectItem';
|
||||||
|
import { RoomWidgetChooserContentEvent } from '../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent';
|
||||||
|
import { dispatchUiEvent } from '../../../hooks';
|
||||||
|
import { RoomWidgetUpdateEvent } from '../events';
|
||||||
|
import { RoomWidgetMessage, RoomWidgetRequestWidgetMessage, RoomWidgetRoomObjectMessage } from '../messages';
|
||||||
|
import { dynamicSort } from '../widgets/choosers/utils/sorting';
|
||||||
|
import { RoomWidgetHandler } from './RoomWidgetHandler';
|
||||||
|
|
||||||
|
export class FurniChooserWidgetHandler extends RoomWidgetHandler
|
||||||
|
{
|
||||||
|
public processEvent(event: NitroEvent): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
if(!message) return null;
|
||||||
|
|
||||||
|
switch(message.type)
|
||||||
|
{
|
||||||
|
case RoomWidgetRequestWidgetMessage.FURNI_CHOOSER:
|
||||||
|
this.processFurniChooser();
|
||||||
|
break;
|
||||||
|
case RoomWidgetRoomObjectMessage.SELECT_OBJECT:
|
||||||
|
this.selectFurni(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private selectFurni(message: RoomWidgetMessage): void
|
||||||
|
{
|
||||||
|
const event = message as RoomWidgetRoomObjectMessage;
|
||||||
|
|
||||||
|
if(event == null) return;
|
||||||
|
|
||||||
|
if(event.category === RoomObjectCategory.WALL || event.category === RoomObjectCategory.FLOOR)
|
||||||
|
{
|
||||||
|
GetRoomEngine().selectRoomObject(this.container.roomSession.roomId, event.id, event.category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private processFurniChooser(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
if(this.container == null || this.container.roomSession == null || GetRoomEngine() == null || this.container.roomSession.userDataManager == null) return;
|
||||||
|
|
||||||
|
const roomId = this.container.roomSession.roomId;
|
||||||
|
const furniInRoom : RoomObjectItem[] = [];
|
||||||
|
|
||||||
|
furniInRoom.push(...GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.WALL).map<RoomObjectItem>(roomObject => {
|
||||||
|
const type = roomObject.type;
|
||||||
|
let name = null;
|
||||||
|
if(type.startsWith('poster'))
|
||||||
|
{
|
||||||
|
const posterNumber = Number.parseInt(type.replace('poster', ''));
|
||||||
|
name = GetNitroInstance().localization.getValue('poster_' + posterNumber + '_name');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const furniTypeId = Number.parseInt(roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID));
|
||||||
|
const wallItemData = GetSessionDataManager().getWallItemData(furniTypeId);
|
||||||
|
if(wallItemData != null && wallItemData.name.length > 0)
|
||||||
|
{
|
||||||
|
name = wallItemData.name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new RoomObjectItem(roomObject.id, RoomObjectCategory.WALL, name)
|
||||||
|
}));
|
||||||
|
|
||||||
|
furniInRoom.push(...GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.FLOOR).map<RoomObjectItem>(roomObject => {
|
||||||
|
const furniTypeId = Number.parseInt(roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID));
|
||||||
|
const floorItemData = GetSessionDataManager().getFloorItemData(furniTypeId);
|
||||||
|
const name = floorItemData != null ? floorItemData.name : roomObject.type;
|
||||||
|
|
||||||
|
return new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name);
|
||||||
|
}));
|
||||||
|
|
||||||
|
furniInRoom.sort(dynamicSort('name'));
|
||||||
|
|
||||||
|
dispatchUiEvent(new RoomWidgetChooserContentEvent(RoomWidgetChooserContentEvent.FURNI_CHOOSER_CONTENT, furniInRoom, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): string
|
||||||
|
{
|
||||||
|
return RoomWidgetEnum.FURNI_CHOOSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get eventTypes(): string[]
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get messageTypes(): string[]
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
RoomWidgetRequestWidgetMessage.FURNI_CHOOSER,
|
||||||
|
RoomWidgetRoomObjectMessage.SELECT_OBJECT
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
84
src/views/room/handlers/UserChooserWidgetHandler.ts
Normal file
84
src/views/room/handlers/UserChooserWidgetHandler.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { NitroEvent, RoomObjectCategory, RoomWidgetEnum } from '@nitrots/nitro-renderer';
|
||||||
|
import { RoomWidgetHandler } from '.';
|
||||||
|
import { GetRoomEngine } from '../../../api';
|
||||||
|
import { RoomObjectItem } from '../../../events/room-widgets/choosers/RoomObjectItem';
|
||||||
|
import { RoomWidgetChooserContentEvent } from '../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent';
|
||||||
|
import { dispatchUiEvent } from '../../../hooks';
|
||||||
|
import { RoomWidgetUpdateEvent } from '../events';
|
||||||
|
import { RoomWidgetMessage, RoomWidgetRequestWidgetMessage, RoomWidgetRoomObjectMessage } from '../messages';
|
||||||
|
import { dynamicSort } from '../widgets/choosers/utils/sorting';
|
||||||
|
|
||||||
|
export class UserChooserWidgetHandler extends RoomWidgetHandler
|
||||||
|
{
|
||||||
|
public processEvent(event: NitroEvent): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
if(!message) return null;
|
||||||
|
|
||||||
|
switch(message.type)
|
||||||
|
{
|
||||||
|
case RoomWidgetRequestWidgetMessage.USER_CHOOSER:
|
||||||
|
this.processUserChooser();
|
||||||
|
break;
|
||||||
|
case RoomWidgetRoomObjectMessage.SELECT_OBJECT:
|
||||||
|
this.selectUnit(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private processUserChooser(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
if(this.container == null || this.container.roomSession == null || GetRoomEngine() == null || this.container.roomSession.userDataManager == null) return;
|
||||||
|
|
||||||
|
const roomId = this.container.roomSession.roomId;
|
||||||
|
const categoryId = RoomObjectCategory.UNIT;
|
||||||
|
const units = [];
|
||||||
|
|
||||||
|
units.push(...GetRoomEngine().getRoomObjects(roomId, categoryId).map<RoomObjectItem>(roomObject => {
|
||||||
|
const unitData = this.container.roomSession.userDataManager.getUserDataByIndex(roomObject.id);
|
||||||
|
|
||||||
|
if(!unitData) return null;
|
||||||
|
|
||||||
|
return new RoomObjectItem(unitData.roomIndex, categoryId, unitData.name);
|
||||||
|
}));
|
||||||
|
|
||||||
|
units.sort(dynamicSort('name'));
|
||||||
|
dispatchUiEvent(new RoomWidgetChooserContentEvent(RoomWidgetChooserContentEvent.USER_CHOOSER_CONTENT, units));
|
||||||
|
}
|
||||||
|
|
||||||
|
private selectUnit(k: RoomWidgetMessage): void
|
||||||
|
{
|
||||||
|
const event = k as RoomWidgetRoomObjectMessage;
|
||||||
|
|
||||||
|
if(event == null) return;
|
||||||
|
|
||||||
|
if(event.category === RoomObjectCategory.UNIT)
|
||||||
|
{
|
||||||
|
GetRoomEngine().selectRoomObject(this.container.roomSession.roomId, event.id, event.category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): string
|
||||||
|
{
|
||||||
|
return RoomWidgetEnum.USER_CHOOSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get eventTypes(): string[]
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get messageTypes(): string[]
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
RoomWidgetRequestWidgetMessage.USER_CHOOSER,
|
||||||
|
RoomWidgetRoomObjectMessage.SELECT_OBJECT
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -7,3 +7,4 @@
|
|||||||
@import './infostand/InfoStandWidgetView';
|
@import './infostand/InfoStandWidgetView';
|
||||||
@import './object-location/ObjectLocationView';
|
@import './object-location/ObjectLocationView';
|
||||||
@import './room-tools/RoomToolsWidgetView';
|
@import './room-tools/RoomToolsWidgetView';
|
||||||
|
@import './choosers/ChooserWidgetView';
|
||||||
|
@ -9,6 +9,8 @@ import { AvatarInfoWidgetView } from './avatar-info/AvatarInfoWidgetView';
|
|||||||
import { CameraWidgetView } from './camera/CameraWidgetView';
|
import { CameraWidgetView } from './camera/CameraWidgetView';
|
||||||
import { ChatInputView } from './chat-input/ChatInputView';
|
import { ChatInputView } from './chat-input/ChatInputView';
|
||||||
import { ChatWidgetView } from './chat/ChatWidgetView';
|
import { ChatWidgetView } from './chat/ChatWidgetView';
|
||||||
|
import { FurniChooserWidgetView } from './choosers/FurniChooserWidgetView';
|
||||||
|
import { UserChooserWidgetView } from './choosers/UserChooserWidgetView';
|
||||||
import { FurnitureWidgetsView } from './furniture/FurnitureWidgetsView';
|
import { FurnitureWidgetsView } from './furniture/FurnitureWidgetsView';
|
||||||
import { InfoStandWidgetView } from './infostand/InfoStandWidgetView';
|
import { InfoStandWidgetView } from './infostand/InfoStandWidgetView';
|
||||||
import { RoomThumbnailWidgetView } from './room-thumbnail/RoomThumbnailWidgetView';
|
import { RoomThumbnailWidgetView } from './room-thumbnail/RoomThumbnailWidgetView';
|
||||||
@ -246,6 +248,8 @@ export const RoomWidgetsView: FC<RoomWidgetViewProps> = props =>
|
|||||||
<InfoStandWidgetView />
|
<InfoStandWidgetView />
|
||||||
<RoomToolsWidgetView />
|
<RoomToolsWidgetView />
|
||||||
<RoomThumbnailWidgetView />
|
<RoomThumbnailWidgetView />
|
||||||
|
<FurniChooserWidgetView />
|
||||||
|
<UserChooserWidgetView />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
9
src/views/room/widgets/choosers/ChooserWidgetView.scss
Normal file
9
src/views/room/widgets/choosers/ChooserWidgetView.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.chooser-widget {
|
||||||
|
.selected-item {
|
||||||
|
background-color: cadetblue;
|
||||||
|
}
|
||||||
|
.list-item {
|
||||||
|
color: black;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
118
src/views/room/widgets/choosers/FurniChooserWidgetView.tsx
Normal file
118
src/views/room/widgets/choosers/FurniChooserWidgetView.tsx
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
|
import List from 'react-virtualized/dist/commonjs/List';
|
||||||
|
import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem';
|
||||||
|
import { RoomWidgetChooserContentEvent } from '../../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent';
|
||||||
|
import { CreateEventDispatcherHook, useUiEvent } from '../../../../hooks';
|
||||||
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
||||||
|
import { LocalizeText } from '../../../../utils';
|
||||||
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
|
import { RoomWidgetRoomObjectUpdateEvent } from '../../events';
|
||||||
|
import { RoomWidgetRequestWidgetMessage, RoomWidgetRoomObjectMessage } from '../../messages';
|
||||||
|
|
||||||
|
export const FurniChooserWidgetView: FC = props =>
|
||||||
|
{
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
const [items, setItems] = useState<RoomObjectItem[]>(null);
|
||||||
|
const [filteredItems, setFilteredItems] = useState<RoomObjectItem[]>(null);
|
||||||
|
const [selectedItem, setSelectedItem] = useState<RoomObjectItem>(null);
|
||||||
|
const [refreshTimeout, setRefreshTimeout] = useState<ReturnType<typeof setTimeout>>(null);
|
||||||
|
const [searchValue, setSearchValue] = useState('');
|
||||||
|
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
|
const onFurniChooserContent = useCallback((event: RoomWidgetChooserContentEvent) =>
|
||||||
|
{
|
||||||
|
setItems(event.items);
|
||||||
|
setIsVisible(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
|
||||||
|
{
|
||||||
|
if (!event || !isVisible) return;
|
||||||
|
|
||||||
|
if (refreshTimeout) clearTimeout(refreshTimeout);
|
||||||
|
|
||||||
|
setRefreshTimeout(setTimeout(() =>
|
||||||
|
{
|
||||||
|
widgetHandler.processWidgetMessage(new RoomWidgetRequestWidgetMessage(RoomWidgetRequestWidgetMessage.FURNI_CHOOSER));
|
||||||
|
}, 100));
|
||||||
|
|
||||||
|
}, [isVisible, refreshTimeout, widgetHandler]);
|
||||||
|
|
||||||
|
useUiEvent(RoomWidgetChooserContentEvent.FURNI_CHOOSER_CONTENT, onFurniChooserContent);
|
||||||
|
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.FURNI_ADDED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
||||||
|
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!items) return;
|
||||||
|
|
||||||
|
let filteredGroupItems = [ ...items ];
|
||||||
|
|
||||||
|
if(searchValue && searchValue.length)
|
||||||
|
{
|
||||||
|
const comparison = searchValue.toLocaleLowerCase();
|
||||||
|
|
||||||
|
filteredGroupItems = items.filter(item =>
|
||||||
|
{
|
||||||
|
if(comparison && comparison.length)
|
||||||
|
{
|
||||||
|
if(item.name.toLocaleLowerCase().includes(comparison)) return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilteredItems(filteredGroupItems);
|
||||||
|
}, [ items, searchValue, setFilteredItems ]);
|
||||||
|
|
||||||
|
|
||||||
|
const onClose = useCallback(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(false);
|
||||||
|
setItems(null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onClickItem = useCallback((item: RoomObjectItem) =>
|
||||||
|
{
|
||||||
|
setSelectedItem(item);
|
||||||
|
widgetHandler.processWidgetMessage(new RoomWidgetRoomObjectMessage(RoomWidgetRoomObjectMessage.SELECT_OBJECT, item.id, item.category));
|
||||||
|
}, [setSelectedItem, widgetHandler]);
|
||||||
|
|
||||||
|
const rowRenderer = function ({
|
||||||
|
key, // Unique key within array of rows
|
||||||
|
index, // Index of row within collection
|
||||||
|
isScrolling, // The List is currently being scrolled
|
||||||
|
isVisible, // This row is visible within the List (eg it is not an overscanned row)
|
||||||
|
style, // Style object to be applied to row (to position it)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div key={key} style={style} onClick={() => onClickItem(filteredItems[index])} className={(selectedItem === filteredItems[index] ? 'selected-item ' : '') + 'list-item'}>
|
||||||
|
{filteredItems[index].name} - {filteredItems[index].id}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="chooser-widget">
|
||||||
|
<NitroCardView>
|
||||||
|
<NitroCardHeaderView headerText={LocalizeText('widget.chooser.furni.title')} onCloseClick={onClose}></NitroCardHeaderView>
|
||||||
|
<NitroCardContentView>
|
||||||
|
<div className="d-flex mb-1">
|
||||||
|
<div className="d-flex flex-grow-1 me-1">
|
||||||
|
<input type="text" className="form-control form-control-sm" placeholder={LocalizeText('generic.search')} value={searchValue} onChange={event => setSearchValue(event.target.value)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<List width={150}
|
||||||
|
height={150}
|
||||||
|
rowCount={filteredItems.length}
|
||||||
|
rowHeight={20}
|
||||||
|
rowRenderer={rowRenderer} />
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
117
src/views/room/widgets/choosers/UserChooserWidgetView.tsx
Normal file
117
src/views/room/widgets/choosers/UserChooserWidgetView.tsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
|
import List from 'react-virtualized/dist/commonjs/List';
|
||||||
|
import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem';
|
||||||
|
import { RoomWidgetChooserContentEvent } from '../../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent';
|
||||||
|
import { CreateEventDispatcherHook, useUiEvent } from '../../../../hooks';
|
||||||
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
||||||
|
import { LocalizeText } from '../../../../utils';
|
||||||
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
|
import { RoomWidgetRoomObjectUpdateEvent } from '../../events';
|
||||||
|
import { RoomWidgetRequestWidgetMessage, RoomWidgetRoomObjectMessage } from '../../messages';
|
||||||
|
|
||||||
|
export const UserChooserWidgetView : FC = props =>
|
||||||
|
{
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
const [items, setItems] = useState<RoomObjectItem[]>(null);
|
||||||
|
const [filteredItems, setFilteredItems] = useState<RoomObjectItem[]>(null);
|
||||||
|
const [selectedItem, setSelectedItem] = useState<RoomObjectItem>(null);
|
||||||
|
const [refreshTimeout, setRefreshTimeout] = useState<ReturnType<typeof setTimeout>>(null);
|
||||||
|
const [searchValue, setSearchValue] = useState('');
|
||||||
|
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
|
const onUserChooserContent = useCallback((event: RoomWidgetChooserContentEvent) =>
|
||||||
|
{
|
||||||
|
setItems(event.items);
|
||||||
|
setIsVisible(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
|
||||||
|
{
|
||||||
|
if (!event || !isVisible) return;
|
||||||
|
|
||||||
|
if (refreshTimeout) clearTimeout(refreshTimeout);
|
||||||
|
|
||||||
|
setRefreshTimeout(setTimeout(() =>
|
||||||
|
{
|
||||||
|
widgetHandler.processWidgetMessage(new RoomWidgetRequestWidgetMessage(RoomWidgetRequestWidgetMessage.USER_CHOOSER));
|
||||||
|
}, 100));
|
||||||
|
|
||||||
|
}, [isVisible, refreshTimeout, widgetHandler]);
|
||||||
|
|
||||||
|
useUiEvent(RoomWidgetChooserContentEvent.USER_CHOOSER_CONTENT, onUserChooserContent);
|
||||||
|
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.USER_REMOVED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
||||||
|
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.USER_ADDED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!items) return;
|
||||||
|
|
||||||
|
let filteredGroupItems = [ ...items ];
|
||||||
|
|
||||||
|
if(searchValue && searchValue.length)
|
||||||
|
{
|
||||||
|
const comparison = searchValue.toLocaleLowerCase();
|
||||||
|
|
||||||
|
filteredGroupItems = items.filter(item =>
|
||||||
|
{
|
||||||
|
if(comparison && comparison.length)
|
||||||
|
{
|
||||||
|
if(item.name.toLocaleLowerCase().includes(comparison)) return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilteredItems(filteredGroupItems);
|
||||||
|
}, [ items, searchValue, setFilteredItems ]);
|
||||||
|
|
||||||
|
const onClose = useCallback(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(false);
|
||||||
|
setItems(null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onClickItem = useCallback((item: RoomObjectItem) =>
|
||||||
|
{
|
||||||
|
setSelectedItem(item);
|
||||||
|
widgetHandler.processWidgetMessage(new RoomWidgetRoomObjectMessage(RoomWidgetRoomObjectMessage.SELECT_OBJECT, item.id, item.category));
|
||||||
|
}, [setSelectedItem, widgetHandler]);
|
||||||
|
|
||||||
|
const rowRenderer = function ({
|
||||||
|
key, // Unique key within array of rows
|
||||||
|
index, // Index of row within collection
|
||||||
|
isScrolling, // The List is currently being scrolled
|
||||||
|
isVisible, // This row is visible within the List (eg it is not an overscanned row)
|
||||||
|
style, // Style object to be applied to row (to position it)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div key={key} style={style} onClick={() => onClickItem(filteredItems[index])} className={(selectedItem === filteredItems[index] ? 'selected-item ' : '') + 'list-item'}>
|
||||||
|
{filteredItems[index].name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isVisible) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="chooser-widget">
|
||||||
|
<NitroCardView>
|
||||||
|
<NitroCardHeaderView headerText={LocalizeText('widget.chooser.user.title')} onCloseClick={onClose}></NitroCardHeaderView>
|
||||||
|
<NitroCardContentView>
|
||||||
|
<div className="d-flex mb-1">
|
||||||
|
<div className="d-flex flex-grow-1 me-1">
|
||||||
|
<input type="text" className="form-control form-control-sm" placeholder={LocalizeText('generic.search')} value={searchValue} onChange={event => setSearchValue(event.target.value)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<List width={150}
|
||||||
|
height={150}
|
||||||
|
rowCount={filteredItems.length}
|
||||||
|
rowHeight={20}
|
||||||
|
rowRenderer={rowRenderer} />
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
18
src/views/room/widgets/choosers/utils/sorting.ts
Normal file
18
src/views/room/widgets/choosers/utils/sorting.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export function dynamicSort(property)
|
||||||
|
{
|
||||||
|
// Source: https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value
|
||||||
|
let sortOrder = 1;
|
||||||
|
if(property[0] === '-')
|
||||||
|
{
|
||||||
|
sortOrder = -1;
|
||||||
|
property = property.substr(1);
|
||||||
|
}
|
||||||
|
return function (a,b)
|
||||||
|
{
|
||||||
|
/* next line works with strings and numbers,
|
||||||
|
* and you may want to customize it to your needs
|
||||||
|
*/
|
||||||
|
const result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
|
||||||
|
return result * sortOrder;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user