From 51558c4f3ccda81bc52142ebab1a16eb6efa44ac Mon Sep 17 00:00:00 2001 From: Bill Date: Fri, 13 Aug 2021 02:56:39 -0400 Subject: [PATCH] Add doorbell / password --- src/events/navigator/UpdateDoorStateEvent.ts | 27 ++++++ src/events/navigator/index.ts | 1 + .../navigator/NavigatorMessageHandler.tsx | 54 +++++++----- src/views/navigator/NavigatorView.scss | 18 ++++ src/views/navigator/NavigatorView.tsx | 85 ++++++++++++++++++- .../NavigatorRoomDoorbellView.tsx | 43 ++++++++++ .../NavigatorRoomDoorbellView.types.ts | 8 ++ .../NavigatorRoomPasswordView.tsx | 45 ++++++++++ .../NavigatorRoomPasswordView.types.ts | 8 ++ .../NavigatorSearchResultItemView.tsx | 27 +++++- 10 files changed, 290 insertions(+), 26 deletions(-) create mode 100644 src/events/navigator/UpdateDoorStateEvent.ts create mode 100644 src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.tsx create mode 100644 src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.types.ts create mode 100644 src/views/navigator/views/room-password/NavigatorRoomPasswordView.tsx create mode 100644 src/views/navigator/views/room-password/NavigatorRoomPasswordView.types.ts diff --git a/src/events/navigator/UpdateDoorStateEvent.ts b/src/events/navigator/UpdateDoorStateEvent.ts new file mode 100644 index 00000000..0c4bdfca --- /dev/null +++ b/src/events/navigator/UpdateDoorStateEvent.ts @@ -0,0 +1,27 @@ +import { NitroEvent, RoomDataParser } from '@nitrots/nitro-renderer'; + +export class UpdateDoorStateEvent extends NitroEvent +{ + public static START_DOORBELL: string = 'UDSE_START_DOORBELL'; + public static START_PASSWORD: string = 'UDSE_START_PASSWORD'; + public static STATE_PENDING_SERVER: string = 'UDSE_STATE_PENDING_SERVER'; + public static UPDATE_STATE: string = 'UDSE_UPDATE_STATE'; + public static STATE_WAITING: string = 'UDSE_STATE_WAITING'; + public static STATE_NO_ANSWER: string = 'UDSE_STATE_NO_ANSWER'; + public static STATE_WRONG_PASSWORD: string = 'UDSE_STATE_WRONG_PASSWORD'; + public static STATE_ACCEPTED: string = 'UDSE_STATE_ACCEPTED'; + + private _roomData: RoomDataParser + + constructor(type: string, roomData: RoomDataParser = null) + { + super(type); + + this._roomData = roomData; + } + + public get roomData(): RoomDataParser + { + return this._roomData; + } +} diff --git a/src/events/navigator/index.ts b/src/events/navigator/index.ts index c2e7371c..892c758a 100644 --- a/src/events/navigator/index.ts +++ b/src/events/navigator/index.ts @@ -1 +1,2 @@ export * from './NavigatorEvent'; +export * from './UpdateDoorStateEvent'; diff --git a/src/views/navigator/NavigatorMessageHandler.tsx b/src/views/navigator/NavigatorMessageHandler.tsx index 964007e6..f2e4e019 100644 --- a/src/views/navigator/NavigatorMessageHandler.tsx +++ b/src/views/navigator/NavigatorMessageHandler.tsx @@ -1,7 +1,8 @@ -import { GenericErrorEvent, NavigatorCategoriesComposer, NavigatorCategoriesEvent, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorSearchEvent, NavigatorSettingsComposer, RoomCreatedEvent, RoomDataParser, RoomDoorbellAcceptedEvent, RoomDoorbellEvent, RoomForwardEvent, RoomInfoComposer, RoomInfoEvent, RoomInfoOwnerEvent, RoomSettingsUpdatedEvent, UserInfoEvent } from '@nitrots/nitro-renderer'; +import { GenericErrorEvent, NavigatorCategoriesComposer, NavigatorCategoriesEvent, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorSearchEvent, NavigatorSettingsComposer, RoomCreatedEvent, RoomDataParser, RoomDoorbellAcceptedEvent, RoomDoorbellEvent, RoomDoorbellRejectedEvent, RoomForwardEvent, RoomInfoComposer, RoomInfoEvent, RoomInfoOwnerEvent, RoomSettingsUpdatedEvent, UserInfoEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; -import { GetRoomSessionManager, GetSessionDataManager } from '../../api'; -import { VisitRoom } from '../../api/navigator/VisitRoom'; +import { CreateRoomSession, GetSessionDataManager } from '../../api'; +import { UpdateDoorStateEvent } from '../../events'; +import { dispatchUiEvent } from '../../hooks'; import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; import { useNavigatorContext } from './context/NavigatorContext'; import { NavigatorMessageHandlerProps } from './NavigatorMessageHandler.types'; @@ -65,13 +66,15 @@ export const NavigatorMessageHandler: FC = props = switch(parser.data.doorMode) { case RoomDataParser.DOORBELL_STATE: + dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.START_DOORBELL, parser.data)); + return; case RoomDataParser.PASSWORD_STATE: - //showLock(); + dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.START_PASSWORD, parser.data)); return; } } - GetRoomSessionManager().createSession(parser.data.roomId); + CreateRoomSession(parser.data.roomId); } else { @@ -91,32 +94,42 @@ export const NavigatorMessageHandler: FC = props = { const parser = event.getParser(); - // if(!parser.userName || (parser.userName.length === 0)) - // { - // showLock(NavigatorLockViewStage.WAITING); - // } + if(!parser.userName || (parser.userName.length === 0)) + { + dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.STATE_WAITING)); + } }, []); const onRoomDoorbellAcceptedEvent = useCallback((event: RoomDoorbellAcceptedEvent) => { const parser = event.getParser(); - // if(!parser.userName || (parser.userName.length === 0)) - // { - // hideLock(); - // } + if(!parser.userName || (parser.userName.length === 0)) + { + dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.STATE_ACCEPTED)); + } + }, []); + + const onRoomDoorbellRejectedEvent = useCallback((event: RoomDoorbellRejectedEvent) => + { + const parser = event.getParser(); + + if(!parser.userName || (parser.userName.length === 0)) + { + dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.STATE_NO_ANSWER)); + } }, []); const onGenericErrorEvent = useCallback((event: GenericErrorEvent) => { const parser = event.getParser(); - // switch(parser.errorCode) - // { - // case -100002: - // showLock(NavigatorLockViewStage.FAILED); - // break; - // } + switch(parser.errorCode) + { + case -100002: + dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.STATE_WRONG_PASSWORD)); + break; + } }, []); const onNavigatorMetadataEvent = useCallback((event: NavigatorMetadataEvent) => @@ -159,7 +172,7 @@ export const NavigatorMessageHandler: FC = props = { const parser = event.getParser(); - VisitRoom(parser.roomId); + CreateRoomSession(parser.roomId); }, []); const onNavigatorHomeRoomEvent = useCallback((event: NavigatorHomeRoomEvent) => @@ -187,6 +200,7 @@ export const NavigatorMessageHandler: FC = props = CreateMessageHook(RoomInfoEvent, onRoomInfoEvent); CreateMessageHook(RoomDoorbellEvent, onRoomDoorbellEvent); CreateMessageHook(RoomDoorbellAcceptedEvent, onRoomDoorbellAcceptedEvent); + CreateMessageHook(RoomDoorbellRejectedEvent, onRoomDoorbellRejectedEvent); CreateMessageHook(GenericErrorEvent, onGenericErrorEvent); CreateMessageHook(NavigatorMetadataEvent, onNavigatorMetadataEvent); CreateMessageHook(NavigatorSearchEvent, onNavigatorSearchEvent); diff --git a/src/views/navigator/NavigatorView.scss b/src/views/navigator/NavigatorView.scss index e17312aa..d29e353b 100644 --- a/src/views/navigator/NavigatorView.scss +++ b/src/views/navigator/NavigatorView.scss @@ -8,4 +8,22 @@ } } +.nitro-navigator-doorbell { + width: 250px; + + .content-area { + min-height: 143px; + height: 143px; + } +} + +.nitro-navigator-password { + width: 250px; + + .content-area { + min-height: 218px; + height: 218px; + } +} + @import './views/NavigatorViews'; diff --git a/src/views/navigator/NavigatorView.tsx b/src/views/navigator/NavigatorView.tsx index 62a60ab9..320e1d11 100644 --- a/src/views/navigator/NavigatorView.tsx +++ b/src/views/navigator/NavigatorView.tsx @@ -1,8 +1,8 @@ -import { ILinkEventTracker, NavigatorInitComposer, NavigatorSearchComposer, RoomSessionEvent } from '@nitrots/nitro-renderer'; -import { FC, useCallback, useEffect, useReducer, useState } from 'react'; -import { AddEventLinkTracker, RemoveLinkEventTracker } from '../../api'; +import { ILinkEventTracker, NavigatorInitComposer, NavigatorSearchComposer, RoomDataParser, RoomSessionEvent } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react'; +import { AddEventLinkTracker, GoToDesktop, RemoveLinkEventTracker } from '../../api'; import { TryVisitRoom } from '../../api/navigator/TryVisitRoom'; -import { NavigatorEvent } from '../../events'; +import { NavigatorEvent, UpdateDoorStateEvent } from '../../events'; import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event'; import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../hooks/messages/message-event'; @@ -13,8 +13,10 @@ import { NavigatorMessageHandler } from './NavigatorMessageHandler'; import { NavigatorViewProps } from './NavigatorView.types'; import { initialNavigator, NavigatorActions, NavigatorReducer } from './reducers/NavigatorReducer'; import { NavigatorRoomCreatorView } from './views/creator/NavigatorRoomCreatorView'; +import { NavigatorRoomDoorbellView } from './views/room-doorbell/NavigatorRoomDoorbellView'; import { NavigatorRoomInfoView } from './views/room-info/NavigatorRoomInfoView'; import { NavigatorRoomLinkView } from './views/room-link/NavigatorRoomLinkView'; +import { NavigatorRoomPasswordView } from './views/room-password/NavigatorRoomPasswordView'; import { NavigatorRoomSettingsView } from './views/room-settings/NavigatorRoomSettingsView'; import { NavigatorSearchResultSetView } from './views/search-result-set/NavigatorSearchResultSetView'; import { NavigatorSearchView } from './views/search/NavigatorSearchView'; @@ -25,6 +27,7 @@ export const NavigatorView: FC = props => const [ isCreatorOpen, setCreatorOpen ] = useState(false); const [ isRoomInfoOpen, setRoomInfoOpen ] = useState(false); const [ isRoomLinkOpen, setRoomLinkOpen ] = useState(false); + const [ pendingDoorState, setPendingDoorState ] = useState<{ roomData: RoomDataParser, state: string }>(null); const [ navigatorState, dispatchNavigatorState ] = useReducer(NavigatorReducer, initialNavigator); const { needsNavigatorUpdate = false, topLevelContext = null, topLevelContexts = null } = navigatorState; @@ -56,6 +59,49 @@ export const NavigatorView: FC = props => useUiEvent(NavigatorEvent.TOGGLE_ROOM_INFO, onNavigatorEvent); useUiEvent(NavigatorEvent.TOGGLE_ROOM_LINK, onNavigatorEvent); + const onUpdateDoorStateEvent = useCallback((event: UpdateDoorStateEvent) => + { + switch(event.type) + { + case UpdateDoorStateEvent.START_DOORBELL: + setPendingDoorState({ roomData: event.roomData, state: event.type }); + return; + case UpdateDoorStateEvent.START_PASSWORD: + setPendingDoorState({ roomData: event.roomData, state: event.type }); + return; + case UpdateDoorStateEvent.STATE_WAITING: + setPendingDoorState(prevValue => + { + return { roomData: prevValue.roomData, state: event.type } + }); + return; + case UpdateDoorStateEvent.STATE_NO_ANSWER: + setPendingDoorState(prevValue => + { + if(prevValue.state === UpdateDoorStateEvent.STATE_WAITING) GoToDesktop(); + + return { roomData: prevValue.roomData, state: event.type } + }); + return; + case UpdateDoorStateEvent.STATE_WRONG_PASSWORD: + setPendingDoorState(prevValue => + { + return { roomData: prevValue.roomData, state: event.type } + }); + return; + case UpdateDoorStateEvent.STATE_ACCEPTED: + setPendingDoorState(null); + return; + } + }, []); + + useUiEvent(UpdateDoorStateEvent.START_DOORBELL, onUpdateDoorStateEvent); + useUiEvent(UpdateDoorStateEvent.START_PASSWORD, onUpdateDoorStateEvent); + useUiEvent(UpdateDoorStateEvent.STATE_WAITING, onUpdateDoorStateEvent); + useUiEvent(UpdateDoorStateEvent.STATE_NO_ANSWER, onUpdateDoorStateEvent); + useUiEvent(UpdateDoorStateEvent.STATE_WRONG_PASSWORD, onUpdateDoorStateEvent); + useUiEvent(UpdateDoorStateEvent.STATE_ACCEPTED, onUpdateDoorStateEvent); + const onRoomSessionEvent = useCallback((event: RoomSessionEvent) => { switch(event.type) @@ -102,6 +148,18 @@ export const NavigatorView: FC = props => } }, []); + const closePendingDoorState = useCallback((state: string) => + { + if(state !== null) + { + setPendingDoorState(prevValue => + { + return { roomData: prevValue.roomData, state }; + }); + } + else setPendingDoorState(null); + }, []); + useEffect(() => { const linkTracker: ILinkEventTracker = { @@ -135,9 +193,28 @@ export const NavigatorView: FC = props => sendSearch('', topLevelContexts[0].code); }, [ topLevelContexts, sendSearch ]); + const getRoomDoorState = useMemo(() => + { + if(!pendingDoorState) return null; + + switch(pendingDoorState.state) + { + case UpdateDoorStateEvent.START_DOORBELL: + case UpdateDoorStateEvent.STATE_WAITING: + case UpdateDoorStateEvent.STATE_NO_ANSWER: + return ; + case UpdateDoorStateEvent.START_PASSWORD: + case UpdateDoorStateEvent.STATE_WRONG_PASSWORD: + return ; + } + + return null; + }, [ pendingDoorState, closePendingDoorState ]); + return ( + { getRoomDoorState } { isVisible && setIsVisible(false) } /> diff --git a/src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.tsx b/src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.tsx new file mode 100644 index 00000000..7bb331b6 --- /dev/null +++ b/src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.tsx @@ -0,0 +1,43 @@ +import { FC, useCallback } from 'react'; +import { CreateRoomSession, GoToDesktop } from '../../../../api'; +import { UpdateDoorStateEvent } from '../../../../events'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { LocalizeText } from '../../../../utils'; +import { NavigatorRoomDoorbellViewProps } from './NavigatorRoomDoorbellView.types'; + +export const NavigatorRoomDoorbellView: FC = props => +{ + const { roomData = null, state = null, onClose = null } = props; + + const close = useCallback(() => + { + if(state === UpdateDoorStateEvent.STATE_WAITING) GoToDesktop(); + + onClose(null); + }, [ state, onClose ]); + + const ring = useCallback(() => + { + if(!roomData) return; + + CreateRoomSession(roomData.roomId); + + onClose(UpdateDoorStateEvent.STATE_PENDING_SERVER); + }, [ roomData, onClose ]); + + return ( + + + + { roomData && { roomData.roomName } } + { (state === UpdateDoorStateEvent.START_DOORBELL) && { LocalizeText('navigator.doorbell.info') } } + { (state === UpdateDoorStateEvent.STATE_WAITING) && { LocalizeText('navigator.doorbell.waiting') } } + { (state === UpdateDoorStateEvent.STATE_NO_ANSWER) && { LocalizeText('navigator.doorbell.no.answer') } } +
+ { (state === UpdateDoorStateEvent.START_DOORBELL) && } + +
+
+
+ ); +} diff --git a/src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.types.ts b/src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.types.ts new file mode 100644 index 00000000..f471bd21 --- /dev/null +++ b/src/views/navigator/views/room-doorbell/NavigatorRoomDoorbellView.types.ts @@ -0,0 +1,8 @@ +import { RoomDataParser } from '@nitrots/nitro-renderer'; + +export interface NavigatorRoomDoorbellViewProps +{ + roomData: RoomDataParser; + state: string; + onClose: (state: string) => void; +} diff --git a/src/views/navigator/views/room-password/NavigatorRoomPasswordView.tsx b/src/views/navigator/views/room-password/NavigatorRoomPasswordView.tsx new file mode 100644 index 00000000..247d0f71 --- /dev/null +++ b/src/views/navigator/views/room-password/NavigatorRoomPasswordView.tsx @@ -0,0 +1,45 @@ +import { FC, useCallback, useState } from 'react'; +import { CreateRoomSession } from '../../../../api'; +import { UpdateDoorStateEvent } from '../../../../events'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { LocalizeText } from '../../../../utils'; +import { NavigatorRoomPasswordViewProps } from './NavigatorRoomPasswordView.types'; + +export const NavigatorRoomPasswordView: FC = props => +{ + const { roomData = null, state = null, onClose = null } = props; + const [ password, setPassword ] = useState(''); + + const close = useCallback(() => + { + onClose(null); + }, [ onClose ]); + + const tryEntering = useCallback(() => + { + if(!roomData) return; + + CreateRoomSession(roomData.roomId, password); + + onClose(UpdateDoorStateEvent.STATE_PENDING_SERVER); + }, [ roomData, password, onClose ]); + + return ( + + + + { roomData && { roomData.roomName } } + { (state === UpdateDoorStateEvent.START_PASSWORD) && { LocalizeText('navigator.password.info') } } + { (state === UpdateDoorStateEvent.STATE_WRONG_PASSWORD) && { LocalizeText('navigator.password.retryinfo') } } +
+ + setPassword(event.target.value) } /> +
+
+ + +
+
+
+ ); +} diff --git a/src/views/navigator/views/room-password/NavigatorRoomPasswordView.types.ts b/src/views/navigator/views/room-password/NavigatorRoomPasswordView.types.ts new file mode 100644 index 00000000..4d1ea7d2 --- /dev/null +++ b/src/views/navigator/views/room-password/NavigatorRoomPasswordView.types.ts @@ -0,0 +1,8 @@ +import { RoomDataParser } from '@nitrots/nitro-renderer'; + +export interface NavigatorRoomPasswordViewProps +{ + roomData: RoomDataParser; + state: string; + onClose: (state: string) => void; +} diff --git a/src/views/navigator/views/search-result-item/NavigatorSearchResultItemView.tsx b/src/views/navigator/views/search-result-item/NavigatorSearchResultItemView.tsx index e38eebb1..946b9ed8 100644 --- a/src/views/navigator/views/search-result-item/NavigatorSearchResultItemView.tsx +++ b/src/views/navigator/views/search-result-item/NavigatorSearchResultItemView.tsx @@ -1,7 +1,10 @@ import { RoomDataParser } from '@nitrots/nitro-renderer'; import classNames from 'classnames'; import { FC, MouseEvent } from 'react'; +import { CreateRoomSession, GetSessionDataManager } from '../../../../api'; import { TryVisitRoom } from '../../../../api/navigator/TryVisitRoom'; +import { UpdateDoorStateEvent } from '../../../../events'; +import { dispatchUiEvent } from '../../../../hooks'; import { NavigatorSearchResultItemViewProps } from './NavigatorSearchResultItemView.types'; export const NavigatorSearchResultItemView: FC = props => @@ -38,7 +41,27 @@ export const NavigatorSearchResultItemView: FC { roomData.habboGroupId > 0 && } { roomData.doorMode !== RoomDataParser.OPEN_STATE && - + }