diff --git a/src/views/room/RoomView.tsx b/src/views/room/RoomView.tsx index a82d4b9a..1dc5e629 100644 --- a/src/views/room/RoomView.tsx +++ b/src/views/room/RoomView.tsx @@ -7,6 +7,7 @@ import { GetRoomEngine } from '../../api/nitro/room/GetRoomEngine'; import { RoomContextProvider } from './context/RoomContext'; import { RoomWidgetUpdateRoomViewEvent } from './events/RoomWidgetUpdateRoomViewEvent'; import { IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers'; +import { DoorbellWidgetHandler } from './handlers/DoorbellWidgetHandler'; import { FurnitureContextMenuWidgetHandler } from './handlers/FurnitureContextMenuWidgetHandler'; import { FurnitureCustomStackHeightWidgetHandler } from './handlers/FurnitureCustomStackHeightWidgetHandler'; import { RoomWidgetRoomToolsHandler } from './handlers/RoomWidgetRoomToolsHandler'; @@ -44,6 +45,7 @@ export const RoomView: FC = props => widgetHandlerManager.registerHandler(new RoomWidgetChatHandler()); widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler()); widgetHandlerManager.registerHandler(new FurnitureCustomStackHeightWidgetHandler()); + widgetHandlerManager.registerHandler(new DoorbellWidgetHandler()); setWidgetHandler(widgetHandlerManager); diff --git a/src/views/room/events/RoomWidgetDoorbellEvent.ts b/src/views/room/events/RoomWidgetDoorbellEvent.ts new file mode 100644 index 00000000..9bad7fa4 --- /dev/null +++ b/src/views/room/events/RoomWidgetDoorbellEvent.ts @@ -0,0 +1,22 @@ +import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent'; + +export class RoomWidgetDoorbellEvent extends RoomWidgetUpdateEvent +{ + public static RINGING: string = 'RWDE_RINGING'; + public static REJECTED: string = 'RWDE_REJECTED'; + public static ACCEPTED: string = 'RWDE_ACCEPTED'; + + private _userName: string = ''; + + constructor(type: string, userName: string) + { + super(type); + + this._userName = userName; + } + + public get userName(): string + { + return this._userName; + } +} diff --git a/src/views/room/events/index.ts b/src/views/room/events/index.ts index 60f8d0c8..4440c0af 100644 --- a/src/views/room/events/index.ts +++ b/src/views/room/events/index.ts @@ -1,4 +1,5 @@ export * from './RoomWidgetAvatarInfoEvent'; +export * from './RoomWidgetDoorbellEvent'; export * from './RoomWidgetFloodControlEvent'; export * from './RoomWidgetObjectNameEvent'; export * from './RoomWidgetRoomEngineUpdateEvent'; diff --git a/src/views/room/handlers/DoorbellWidgetHandler.ts b/src/views/room/handlers/DoorbellWidgetHandler.ts new file mode 100644 index 00000000..b2b69ee9 --- /dev/null +++ b/src/views/room/handlers/DoorbellWidgetHandler.ts @@ -0,0 +1,60 @@ +import { NitroEvent, RoomSessionDoorbellEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer'; +import { RoomWidgetDoorbellEvent, RoomWidgetUpdateEvent } from '../events'; +import { RoomWidgetLetUserInMessage, RoomWidgetMessage } from '../messages'; +import { RoomWidgetHandler } from './RoomWidgetHandler'; + +export class DoorbellWidgetHandler extends RoomWidgetHandler +{ + public processEvent(event: NitroEvent): void + { + const doorbellEvent = (event as RoomSessionDoorbellEvent); + + switch(event.type) + { + case RoomSessionDoorbellEvent.DOORBELL: + this.container.eventDispatcher.dispatchEvent(new RoomWidgetDoorbellEvent(RoomWidgetDoorbellEvent.RINGING, doorbellEvent.userName)); + return; + case RoomSessionDoorbellEvent.RSDE_REJECTED: + this.container.eventDispatcher.dispatchEvent(new RoomWidgetDoorbellEvent(RoomWidgetDoorbellEvent.REJECTED, doorbellEvent.userName)); + return; + case RoomSessionDoorbellEvent.RSDE_ACCEPTED: + this.container.eventDispatcher.dispatchEvent(new RoomWidgetDoorbellEvent(RoomWidgetDoorbellEvent.ACCEPTED, doorbellEvent.userName)); + return; + } + } + + public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent + { + switch(message.type) + { + case RoomWidgetLetUserInMessage.LET_USER_IN: + const letUserInMessage = (message as RoomWidgetLetUserInMessage); + + this.container.roomSession.sendDoorbellApprovalMessage(letUserInMessage.userName, letUserInMessage.canEnter); + break; + } + + return null; + } + + public get type(): string + { + return RoomWidgetEnum.DOORBELL; + } + + public get eventTypes(): string[] + { + return [ + RoomSessionDoorbellEvent.DOORBELL, + RoomSessionDoorbellEvent.RSDE_REJECTED, + RoomSessionDoorbellEvent.RSDE_ACCEPTED + ]; + } + + public get messageTypes(): string[] + { + return [ + RoomWidgetLetUserInMessage.LET_USER_IN + ]; + } +} diff --git a/src/views/room/messages/RoomWidgetLetUserInMessage.ts b/src/views/room/messages/RoomWidgetLetUserInMessage.ts new file mode 100644 index 00000000..9001fe2a --- /dev/null +++ b/src/views/room/messages/RoomWidgetLetUserInMessage.ts @@ -0,0 +1,27 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetLetUserInMessage extends RoomWidgetMessage +{ + public static LET_USER_IN: string = 'RWLUIM_LET_USER_IN'; + + private _userName: string; + private _canEnter: boolean; + + constructor(userName: string, canEnter: boolean) + { + super(RoomWidgetLetUserInMessage.LET_USER_IN); + + this._userName = userName; + this._canEnter = canEnter; + } + + public get userName(): string + { + return this._userName; + } + + public get canEnter(): boolean + { + return this._canEnter; + } +} diff --git a/src/views/room/messages/index.ts b/src/views/room/messages/index.ts index 873903a7..732e5665 100644 --- a/src/views/room/messages/index.ts +++ b/src/views/room/messages/index.ts @@ -7,6 +7,7 @@ export * from './RoomWidgetChatTypingMessage'; export * from './RoomWidgetDanceMessage'; export * from './RoomWidgetFurniActionMessage'; export * from './RoomWidgetFurniToWidgetMessage'; +export * from './RoomWidgetLetUserInMessage'; export * from './RoomWidgetMessage'; export * from './RoomWidgetRequestWidgetMessage'; export * from './RoomWidgetRoomObjectMessage'; diff --git a/src/views/room/widgets/RoomWidgets.scss b/src/views/room/widgets/RoomWidgets.scss index ed284cd9..3308120c 100644 --- a/src/views/room/widgets/RoomWidgets.scss +++ b/src/views/room/widgets/RoomWidgets.scss @@ -3,6 +3,7 @@ @import './chat/ChatWidgetView'; @import './chat-input/ChatInputView'; @import './context-menu/ContextMenu'; +@import './doorbell/DoorbellWidgetView'; @import './furniture/FurnitureWidgets'; @import './infostand/InfoStandWidgetView'; @import './object-location/ObjectLocationView'; diff --git a/src/views/room/widgets/RoomWidgetsView.tsx b/src/views/room/widgets/RoomWidgetsView.tsx index 2ed8ba9d..aa20bf27 100644 --- a/src/views/room/widgets/RoomWidgetsView.tsx +++ b/src/views/room/widgets/RoomWidgetsView.tsx @@ -9,6 +9,7 @@ import { AvatarInfoWidgetView } from './avatar-info/AvatarInfoWidgetView'; import { CameraWidgetView } from './camera/CameraWidgetView'; import { ChatInputView } from './chat-input/ChatInputView'; import { ChatWidgetView } from './chat/ChatWidgetView'; +import { DoorbellWidgetView } from './doorbell/DoorbellWidgetView'; import { FurnitureWidgetsView } from './furniture/FurnitureWidgetsView'; import { InfoStandWidgetView } from './infostand/InfoStandWidgetView'; import { RoomThumbnailWidgetView } from './room-thumbnail/RoomThumbnailWidgetView'; @@ -242,6 +243,7 @@ export const RoomWidgetsView: FC = props => + diff --git a/src/views/room/widgets/doorbell/DoorbellWidgetView.scss b/src/views/room/widgets/doorbell/DoorbellWidgetView.scss new file mode 100644 index 00000000..125a5e69 --- /dev/null +++ b/src/views/room/widgets/doorbell/DoorbellWidgetView.scss @@ -0,0 +1,22 @@ +.nitro-widget-doorbell { + width: 250px; + + .content-area { + min-height: 143px; + height: 143px; + } + + .doorbell-user-list { + + .list-item { + background: $grid-active-bg-color; + } + + .col:nth-child(even) { + + .list-item { + background: $white !important; + } + } + } +} diff --git a/src/views/room/widgets/doorbell/DoorbellWidgetView.tsx b/src/views/room/widgets/doorbell/DoorbellWidgetView.tsx new file mode 100644 index 00000000..7dad34dd --- /dev/null +++ b/src/views/room/widgets/doorbell/DoorbellWidgetView.tsx @@ -0,0 +1,88 @@ +import { FC, useCallback, useState } from 'react'; +import { CreateEventDispatcherHook } from '../../../../hooks'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { LocalizeText } from '../../../../utils'; +import { useRoomContext } from '../../context/RoomContext'; +import { RoomWidgetDoorbellEvent } from '../../events'; +import { RoomWidgetLetUserInMessage } from '../../messages'; + +export const DoorbellWidgetView: FC<{}> = props => +{ + const [ isVisible, setIsVisible ] = useState(false); + const [ users, setUsers ] = useState([]); + const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); + + const addUser = useCallback((userName: string) => + { + if(users.indexOf(userName) >= 0) return; + + const newUsers = [ ...users, userName ]; + + setUsers(newUsers); + setIsVisible(true); + }, [ users ]); + + const removeUser = useCallback((userName: string) => + { + const index = users.indexOf(userName); + + if(index === -1) return; + + const newUsers = [ ...users ]; + + newUsers.splice(index, 1); + + setUsers(newUsers); + + if(!newUsers.length) setIsVisible(false); + }, [ users ]); + + const onRoomWidgetDoorbellEvent = useCallback((event: RoomWidgetDoorbellEvent) => + { + switch(event.type) + { + case RoomWidgetDoorbellEvent.RINGING: + addUser(event.userName); + return; + case RoomWidgetDoorbellEvent.REJECTED: + case RoomWidgetDoorbellEvent.ACCEPTED: + removeUser(event.userName); + return; + } + }, [ addUser, removeUser ]); + + CreateEventDispatcherHook(RoomWidgetDoorbellEvent.RINGING, eventDispatcher, onRoomWidgetDoorbellEvent); + CreateEventDispatcherHook(RoomWidgetDoorbellEvent.REJECTED, eventDispatcher, onRoomWidgetDoorbellEvent); + CreateEventDispatcherHook(RoomWidgetDoorbellEvent.ACCEPTED, eventDispatcher, onRoomWidgetDoorbellEvent); + + const answer = useCallback((userName: string, flag: boolean) => + { + widgetHandler.processWidgetMessage(new RoomWidgetLetUserInMessage(userName, flag)); + + removeUser(userName); + }, [ widgetHandler, removeUser ]); + + if(!users.length) return null; + + return ( + + setIsVisible(false) } /> + +
+ { (users.length > 0) && users.map(userName => + { + return ( +
+ { userName } +
+ + +
+
+ ); + }) } +
+
+
+ ); +}