Add doorbell / password

This commit is contained in:
Bill 2021-08-13 02:56:39 -04:00
parent cfcea786fa
commit 51558c4f3c
10 changed files with 290 additions and 26 deletions

View File

@ -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;
}
}

View File

@ -1 +1,2 @@
export * from './NavigatorEvent';
export * from './UpdateDoorStateEvent';

View File

@ -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<NavigatorMessageHandlerProps> = 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<NavigatorMessageHandlerProps> = 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<NavigatorMessageHandlerProps> = props =
{
const parser = event.getParser();
VisitRoom(parser.roomId);
CreateRoomSession(parser.roomId);
}, []);
const onNavigatorHomeRoomEvent = useCallback((event: NavigatorHomeRoomEvent) =>
@ -187,6 +200,7 @@ export const NavigatorMessageHandler: FC<NavigatorMessageHandlerProps> = props =
CreateMessageHook(RoomInfoEvent, onRoomInfoEvent);
CreateMessageHook(RoomDoorbellEvent, onRoomDoorbellEvent);
CreateMessageHook(RoomDoorbellAcceptedEvent, onRoomDoorbellAcceptedEvent);
CreateMessageHook(RoomDoorbellRejectedEvent, onRoomDoorbellRejectedEvent);
CreateMessageHook(GenericErrorEvent, onGenericErrorEvent);
CreateMessageHook(NavigatorMetadataEvent, onNavigatorMetadataEvent);
CreateMessageHook(NavigatorSearchEvent, onNavigatorSearchEvent);

View File

@ -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';

View File

@ -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<NavigatorViewProps> = 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<NavigatorViewProps> = 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<NavigatorViewProps> = 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<NavigatorViewProps> = 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 <NavigatorRoomDoorbellView roomData={ pendingDoorState.roomData } state={ pendingDoorState.state } onClose={ closePendingDoorState } />;
case UpdateDoorStateEvent.START_PASSWORD:
case UpdateDoorStateEvent.STATE_WRONG_PASSWORD:
return <NavigatorRoomPasswordView roomData={ pendingDoorState.roomData } state={ pendingDoorState.state } onClose={ closePendingDoorState } />;
}
return null;
}, [ pendingDoorState, closePendingDoorState ]);
return (
<NavigatorContextProvider value={ { navigatorState, dispatchNavigatorState } }>
<NavigatorMessageHandler />
{ getRoomDoorState }
{ isVisible &&
<NitroCardView uniqueKey="navigator" className="nitro-navigator">
<NitroCardHeaderView headerText={ LocalizeText(isCreatorOpen ? 'navigator.createroom.title' : 'navigator.title') } onCloseClick={ event => setIsVisible(false) } />

View File

@ -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<NavigatorRoomDoorbellViewProps> = 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 (
<NitroCardView className="nitro-navigator-doorbell" simple={ true }>
<NitroCardHeaderView headerText={ LocalizeText('navigator.doorbell.title') } onCloseClick={ close } />
<NitroCardContentView className="text-black d-flex flex-column">
{ roomData && <span className="fw-bold">{ roomData.roomName }</span> }
{ (state === UpdateDoorStateEvent.START_DOORBELL) && <span>{ LocalizeText('navigator.doorbell.info') }</span> }
{ (state === UpdateDoorStateEvent.STATE_WAITING) && <span>{ LocalizeText('navigator.doorbell.waiting') }</span> }
{ (state === UpdateDoorStateEvent.STATE_NO_ANSWER) && <span>{ LocalizeText('navigator.doorbell.no.answer') }</span> }
<div className="d-flex flex-column mt-1">
{ (state === UpdateDoorStateEvent.START_DOORBELL) && <button type="button" className="btn btn-success btn-sm" onClick={ ring }>{ LocalizeText('navigator.doorbell.button.ring') }</button> }
<button type="button" className="btn btn-danger btn-sm mt-1" onClick={ close }>{ LocalizeText('generic.cancel') }</button>
</div>
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -0,0 +1,8 @@
import { RoomDataParser } from '@nitrots/nitro-renderer';
export interface NavigatorRoomDoorbellViewProps
{
roomData: RoomDataParser;
state: string;
onClose: (state: string) => void;
}

View File

@ -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<NavigatorRoomPasswordViewProps> = 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 (
<NitroCardView className="nitro-navigator-password" simple={ true }>
<NitroCardHeaderView headerText={ LocalizeText('navigator.password.title') } onCloseClick={ close } />
<NitroCardContentView className="text-black d-flex flex-column">
{ roomData && <span className="fw-bold">{ roomData.roomName }</span> }
{ (state === UpdateDoorStateEvent.START_PASSWORD) && <span>{ LocalizeText('navigator.password.info') }</span> }
{ (state === UpdateDoorStateEvent.STATE_WRONG_PASSWORD) && <span>{ LocalizeText('navigator.password.retryinfo') }</span> }
<div className="form-group mt-1">
<label>{ LocalizeText('navigator.password.enter') }</label>
<input type="password" className="form-control form-control-sm" onChange={ event => setPassword(event.target.value) } />
</div>
<div className="d-flex flex-column mt-1">
<button type="button" className="btn btn-success btn-sm" onClick={ tryEntering }>{ LocalizeText('navigator.password.button.try') }</button>
<button type="button" className="btn btn-danger btn-sm mt-1" onClick={ close }>{ LocalizeText('generic.cancel') }</button>
</div>
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -0,0 +1,8 @@
import { RoomDataParser } from '@nitrots/nitro-renderer';
export interface NavigatorRoomPasswordViewProps
{
roomData: RoomDataParser;
state: string;
onClose: (state: string) => void;
}

View File

@ -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<NavigatorSearchResultItemViewProps> = props =>
@ -37,8 +40,28 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
}
function visitRoom(): void
{
if(roomData.ownerId !== GetSessionDataManager().userId)
{
if(roomData.habboGroupId !== 0)
{
TryVisitRoom(roomData.roomId);
return;
}
switch(roomData.doorMode)
{
case RoomDataParser.DOORBELL_STATE:
dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.START_DOORBELL, roomData));
return;
case RoomDataParser.PASSWORD_STATE:
dispatchUiEvent(new UpdateDoorStateEvent(UpdateDoorStateEvent.START_PASSWORD, roomData));
return;
}
}
CreateRoomSession(roomData.roomId);
}
return (
@ -58,7 +81,7 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
<i className="fas fa-info-circle text-secondary" onClick={ openInfo }></i>
{ roomData.habboGroupId > 0 && <i className="fas fa-users mr-2"></i> }
{ roomData.doorMode !== RoomDataParser.OPEN_STATE &&
<i className={ 'mr-2 fas ' + classNames( {'fa-lock': roomData.doorMode === RoomDataParser.DOORBELL_STATE, 'fa-key': roomData.doorMode === RoomDataParser.PASSWORD_STATE })}></i>
<i className={ 'me-2 fas ' + classNames( {'fa-lock': roomData.doorMode === RoomDataParser.DOORBELL_STATE, 'fa-key': roomData.doorMode === RoomDataParser.PASSWORD_STATE })}></i>
}
</div>
</div>