refactor choosers to use composition

This commit is contained in:
Dank074 2021-08-11 00:05:22 -05:00
parent 4706149342
commit 05fa86d464
6 changed files with 133 additions and 185 deletions

View File

@ -51,8 +51,13 @@ export class FurniChooserWidgetHandler extends RoomWidgetHandler
const roomId = this.container.roomSession.roomId; const roomId = this.container.roomSession.roomId;
const furniInRoom : RoomObjectItem[] = []; const furniInRoom : RoomObjectItem[] = [];
furniInRoom.push(...GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.WALL).map<RoomObjectItem>(roomObject => { const wallItems = GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.WALL);
const type = roomObject.type; const floorItems = GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.FLOOR);
wallItems.forEach( wallItem => {
if(!wallItem) return;
const type = wallItem.type;
let name = null; let name = null;
if(type.startsWith('poster')) if(type.startsWith('poster'))
{ {
@ -61,7 +66,7 @@ export class FurniChooserWidgetHandler extends RoomWidgetHandler
} }
else else
{ {
const furniTypeId = Number.parseInt(roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID)); const furniTypeId = Number.parseInt(wallItem.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID));
const wallItemData = GetSessionDataManager().getWallItemData(furniTypeId); const wallItemData = GetSessionDataManager().getWallItemData(furniTypeId);
if(wallItemData != null && wallItemData.name.length > 0) if(wallItemData != null && wallItemData.name.length > 0)
{ {
@ -72,16 +77,18 @@ export class FurniChooserWidgetHandler extends RoomWidgetHandler
name = type; name = type;
} }
} }
return new RoomObjectItem(roomObject.id, RoomObjectCategory.WALL, name) furniInRoom.push(new RoomObjectItem(wallItem.id, RoomObjectCategory.WALL, name));
})); });
furniInRoom.push(...GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.FLOOR).map<RoomObjectItem>(roomObject => { floorItems.forEach(roomObject => {
if(!roomObject) return;
const furniTypeId = Number.parseInt(roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID)); const furniTypeId = Number.parseInt(roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID));
const floorItemData = GetSessionDataManager().getFloorItemData(furniTypeId); const floorItemData = GetSessionDataManager().getFloorItemData(furniTypeId);
const name = floorItemData != null ? floorItemData.name : roomObject.type; const name = floorItemData != null ? floorItemData.name : roomObject.type;
return new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name); furniInRoom.push(new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name));
})); });
furniInRoom.sort(dynamicSort('name')); furniInRoom.sort(dynamicSort('name'));

View File

@ -38,15 +38,19 @@ export class UserChooserWidgetHandler extends RoomWidgetHandler
const roomId = this.container.roomSession.roomId; const roomId = this.container.roomSession.roomId;
const categoryId = RoomObjectCategory.UNIT; const categoryId = RoomObjectCategory.UNIT;
const units = []; const units : RoomObjectItem[] = [];
units.push(...GetRoomEngine().getRoomObjects(roomId, categoryId).map<RoomObjectItem>(roomObject => { const roomObjects = GetRoomEngine().getRoomObjects(roomId, categoryId);
roomObjects.forEach(roomObject => {
if(!roomObject) return;
const unitData = this.container.roomSession.userDataManager.getUserDataByIndex(roomObject.id); const unitData = this.container.roomSession.userDataManager.getUserDataByIndex(roomObject.id);
if(!unitData) return null; if(!unitData) return;
return new RoomObjectItem(unitData.roomIndex, categoryId, unitData.name); units.push(new RoomObjectItem(unitData.roomIndex, categoryId, unitData.name));
})); });
units.sort(dynamicSort('name')); units.sort(dynamicSort('name'));
dispatchUiEvent(new RoomWidgetChooserContentEvent(RoomWidgetChooserContentEvent.USER_CHOOSER_CONTENT, units)); dispatchUiEvent(new RoomWidgetChooserContentEvent(RoomWidgetChooserContentEvent.USER_CHOOSER_CONTENT, units));

View File

@ -0,0 +1,87 @@
import { FC, useCallback, useEffect, useState } from 'react';
import List from 'react-virtualized/dist/commonjs/List';
import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem';
import { CreateEventDispatcherHook } 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';
import { ChooserWidgetViewProps } from './ChooserWidgetView.type';
export const ChooserWidgetView: FC<ChooserWidgetViewProps> = props =>
{
const [filteredItems, setFilteredItems] = useState<RoomObjectItem[]>([]);
const [selectedItem, setSelectedItem] = useState<RoomObjectItem>(null);
const [refreshTimeout, setRefreshTimeout] = useState<ReturnType<typeof setTimeout>>(null);
const [searchValue, setSearchValue] = useState('');
const { title = null, onCloseClick = null, displayItemId = false, items = null, messageType = null, roomWidgetRoomObjectUpdateEvents = null } = props;
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
useEffect(() =>
{
if (!items) return;
const filteredGroupItems = items.filter(item =>
{
return item.name.toLocaleLowerCase().includes(searchValue.toLocaleLowerCase());
});
setFilteredItems(filteredGroupItems);
}, [items, searchValue, setFilteredItems]);
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
{
if (!event) return;
if (refreshTimeout) clearTimeout(refreshTimeout);
setRefreshTimeout(setTimeout(() =>
{
widgetHandler.processWidgetMessage(new RoomWidgetRequestWidgetMessage(messageType));
}, 100));
}, [refreshTimeout, messageType, widgetHandler]);
roomWidgetRoomObjectUpdateEvents.forEach(event => CreateEventDispatcherHook(event, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent));
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}
{displayItemId && (' - ' + filteredItems[index].id)}
</div>
);
}
return (
<NitroCardView>
<NitroCardHeaderView headerText={title} onCloseClick={onCloseClick}></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>
);
}

View File

@ -0,0 +1,12 @@
import { MouseEvent } from 'react';
import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem';
export interface ChooserWidgetViewProps
{
title: string;
onCloseClick: (event: MouseEvent) => void;
displayItemId: boolean;
items: RoomObjectItem[];
messageType: string;
roomWidgetRoomObjectUpdateEvents: string[];
}

View File

@ -1,23 +1,16 @@
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import List from 'react-virtualized/dist/commonjs/List';
import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem'; import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem';
import { RoomWidgetChooserContentEvent } from '../../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent'; import { RoomWidgetChooserContentEvent } from '../../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent';
import { CreateEventDispatcherHook, useUiEvent } from '../../../../hooks'; import { useUiEvent } from '../../../../hooks';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
import { LocalizeText } from '../../../../utils'; import { LocalizeText } from '../../../../utils';
import { useRoomContext } from '../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../events';
import { RoomWidgetRequestWidgetMessage, RoomWidgetRoomObjectMessage } from '../../messages'; import { RoomWidgetRequestWidgetMessage } from '../../messages';
import { ChooserWidgetView } from './ChooserWidgetView';
export const FurniChooserWidgetView: FC = props => export const FurniChooserWidgetView: FC = props =>
{ {
const [isVisible, setIsVisible] = useState(false); const [isVisible, setIsVisible] = useState(false);
const [items, setItems] = useState<RoomObjectItem[]>(null); 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) => const onFurniChooserContent = useCallback((event: RoomWidgetChooserContentEvent) =>
{ {
@ -25,46 +18,7 @@ export const FurniChooserWidgetView: FC = props =>
setIsVisible(true); 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); 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(() => const onClose = useCallback(() =>
@ -73,46 +27,11 @@ export const FurniChooserWidgetView: FC = props =>
setItems(null); 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; if (!isVisible) return null;
return ( return (
<div className="chooser-widget"> <div className="chooser-widget">
<NitroCardView> <ChooserWidgetView title={LocalizeText('widget.chooser.furni.title')} displayItemId={true} onCloseClick={onClose} items={items} messageType={RoomWidgetRequestWidgetMessage.FURNI_CHOOSER} roomWidgetRoomObjectUpdateEvents={[RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED, RoomWidgetRoomObjectUpdateEvent.FURNI_ADDED]}></ChooserWidgetView>
<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> </div>
) )
} }

View File

@ -1,23 +1,16 @@
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import List from 'react-virtualized/dist/commonjs/List';
import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem'; import { RoomObjectItem } from '../../../../events/room-widgets/choosers/RoomObjectItem';
import { RoomWidgetChooserContentEvent } from '../../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent'; import { RoomWidgetChooserContentEvent } from '../../../../events/room-widgets/choosers/RoomWidgetChooserContentEvent';
import { CreateEventDispatcherHook, useUiEvent } from '../../../../hooks'; import { useUiEvent } from '../../../../hooks';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
import { LocalizeText } from '../../../../utils'; import { LocalizeText } from '../../../../utils';
import { useRoomContext } from '../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../events';
import { RoomWidgetRequestWidgetMessage, RoomWidgetRoomObjectMessage } from '../../messages'; import { RoomWidgetRequestWidgetMessage } from '../../messages';
import { ChooserWidgetView } from './ChooserWidgetView';
export const UserChooserWidgetView : FC = props => export const UserChooserWidgetView : FC = props =>
{ {
const [isVisible, setIsVisible] = useState(false); const [isVisible, setIsVisible] = useState(false);
const [items, setItems] = useState<RoomObjectItem[]>(null); 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) => const onUserChooserContent = useCallback((event: RoomWidgetChooserContentEvent) =>
{ {
@ -25,93 +18,19 @@ export const UserChooserWidgetView : FC = props =>
setIsVisible(true); 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); 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(() => const onClose = useCallback(() =>
{ {
setIsVisible(false); setIsVisible(false);
setItems(null); 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; if(!isVisible) return null;
return ( return (
<div className="chooser-widget"> <div className="chooser-widget">
<NitroCardView> <ChooserWidgetView title={LocalizeText('widget.chooser.user.title')} displayItemId={false} onCloseClick={onClose} items={items} messageType={RoomWidgetRequestWidgetMessage.USER_CHOOSER} roomWidgetRoomObjectUpdateEvents={[RoomWidgetRoomObjectUpdateEvent.USER_REMOVED, RoomWidgetRoomObjectUpdateEvent.USER_ADDED]}></ChooserWidgetView>
<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> </div>
); );
} }