mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-26 23:50:52 +01:00
Name change is DONE!
This commit is contained in:
parent
b1b7affa21
commit
9d664896d5
6
src/events/help/HelpNameChangeEvent.ts
Normal file
6
src/events/help/HelpNameChangeEvent.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { NitroEvent } from '@nitrots/nitro-renderer/src/core/events/NitroEvent';
|
||||
|
||||
export class HelpNameChangeEvent extends NitroEvent
|
||||
{
|
||||
public static INIT: string = 'HC_NAME_CHANGE_INIT';
|
||||
}
|
@ -12,3 +12,7 @@
|
||||
.nitro-cfh-sanction-status {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.nitro-change-username {
|
||||
width: 300px;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import { IHelpReportState, initialReportState } from './context/HelpContext.type
|
||||
import { HelpMessageHandler } from './HelpMessageHandler';
|
||||
import { DescribeReportView } from './views/DescribeReportView';
|
||||
import { HelpIndexView } from './views/HelpIndexView';
|
||||
import { NameChangeView } from './views/name-change/NameChangeView';
|
||||
import { SanctionSatusView } from './views/SanctionStatusView';
|
||||
import { SelectReportedChatsView } from './views/SelectReportedChatsView';
|
||||
import { SelectReportedUserView } from './views/SelectReportedUserView';
|
||||
@ -76,6 +77,7 @@ export const HelpView: FC<{}> = props =>
|
||||
</NitroCardView>
|
||||
}
|
||||
<SanctionSatusView />
|
||||
<NameChangeView />
|
||||
</HelpContextProvider>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
import { ChangeUserNameMessageComposer, UserNameChangeMessageEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { GetSessionDataManager, LocalizeText } from '../../../../api';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../../../hooks';
|
||||
import { NameChangeLayoutViewProps } from './NameChangeView.types';
|
||||
|
||||
export const NameChangeConfirmationView:FC<NameChangeLayoutViewProps> = props =>
|
||||
{
|
||||
const { username = '', onAction = null } = props;
|
||||
|
||||
const [ isConfirming, setIsConfirming ] = useState<boolean>(false);
|
||||
|
||||
const onUserNameChangeMessageEvent = useCallback((event: UserNameChangeMessageEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
if(!parser) return;
|
||||
|
||||
if(parser.webId !== GetSessionDataManager().userId) return;
|
||||
|
||||
onAction('close');
|
||||
}, [ onAction ]);
|
||||
|
||||
CreateMessageHook(UserNameChangeMessageEvent, onUserNameChangeMessageEvent);
|
||||
|
||||
const confirm = useCallback(() =>
|
||||
{
|
||||
if(isConfirming) return;
|
||||
|
||||
setIsConfirming(true);
|
||||
SendMessageHook(new ChangeUserNameMessageComposer(username));
|
||||
}, [ isConfirming, username ]);
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column gap-4 h-100">
|
||||
<div className="bg-muted rounded p-2 text-center">{ LocalizeText('tutorial.name_change.info.confirm') }</div>
|
||||
<div className="d-flex flex-column align-items-center gap-1 h-100">
|
||||
<div>{ LocalizeText('tutorial.name_change.confirm') }</div>
|
||||
<div className="fw-bold">{ username }</div>
|
||||
</div>
|
||||
<div className="d-flex gap-2">
|
||||
<button className="btn btn-success w-100" disabled={ isConfirming } onClick={ confirm }>{ LocalizeText('generic.ok') }</button>
|
||||
<button className="btn btn-primary w-100" onClick={ () => onAction('close') }>{ LocalizeText('cancel') }</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
19
src/views/help/views/name-change/NameChangeInitView.tsx
Normal file
19
src/views/help/views/name-change/NameChangeInitView.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { FC } from 'react';
|
||||
import { GetSessionDataManager, LocalizeText } from '../../../../api';
|
||||
import { NameChangeLayoutViewProps } from './NameChangeView.types';
|
||||
|
||||
export const NameChangeInitView:FC<NameChangeLayoutViewProps> = props =>
|
||||
{
|
||||
const { onAction = null } = props;
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column gap-4 h-100">
|
||||
<div className="bg-muted rounded p-2 text-center">{ LocalizeText('tutorial.name_change.info.main') }</div>
|
||||
<div className="fw-bold d-flex align-items-center justify-content-center h-100 w-100">{ LocalizeText('tutorial.name_change.current', ['name'], [GetSessionDataManager().userName]) }</div>
|
||||
<div className="d-flex gap-2">
|
||||
<button className="btn btn-success w-100" onClick={ () => onAction('start') }>{ LocalizeText('tutorial.name_change.change') }</button>
|
||||
<button className="btn btn-primary w-100" onClick={ () => onAction('confirmation', GetSessionDataManager().userName) }>{ LocalizeText('tutorial.name_change.keep') }</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
102
src/views/help/views/name-change/NameChangeInputView.tsx
Normal file
102
src/views/help/views/name-change/NameChangeInputView.tsx
Normal file
@ -0,0 +1,102 @@
|
||||
import { CheckUserNameMessageComposer, CheckUserNameResultMessageEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../../../hooks';
|
||||
import { NameChangeLayoutViewProps } from './NameChangeView.types';
|
||||
|
||||
const AVAILABLE: number = 0;
|
||||
const TOO_SHORT: number = 2;
|
||||
const TOO_LONG: number = 3;
|
||||
const NOT_VALID: number = 4;
|
||||
const TAKEN_WITH_SUGGESTIONS: number = 5;
|
||||
const DISABLED: number = 6;
|
||||
|
||||
export const NameChangeInputView:FC<NameChangeLayoutViewProps> = props =>
|
||||
{
|
||||
const { onAction = null } = props;
|
||||
|
||||
const [ newUsername, setNewUsername ] = useState<string>('');
|
||||
const [ canProceed, setCanProceed ] = useState<boolean>(false);
|
||||
const [ isChecking, setIsChecking ] = useState<boolean>(false);
|
||||
const [ errorCode, setErrorCode ] = useState<string>(null);
|
||||
const [ suggestions, setSuggestions ] = useState<string[]>([]);
|
||||
|
||||
const onCheckUserNameResultMessageEvent = useCallback((event: CheckUserNameResultMessageEvent) =>
|
||||
{
|
||||
setIsChecking(false);
|
||||
|
||||
const parser = event.getParser();
|
||||
|
||||
if(!parser) return;
|
||||
|
||||
switch(parser.resultCode)
|
||||
{
|
||||
case AVAILABLE:
|
||||
setCanProceed(true);
|
||||
break;
|
||||
case TOO_SHORT:
|
||||
setErrorCode('short');
|
||||
break;
|
||||
case TOO_LONG:
|
||||
setErrorCode('long');
|
||||
break;
|
||||
case NOT_VALID:
|
||||
setErrorCode('invalid');
|
||||
break;
|
||||
case TAKEN_WITH_SUGGESTIONS:
|
||||
setSuggestions(parser.nameSuggestions);
|
||||
setErrorCode('taken');
|
||||
break;
|
||||
case DISABLED:
|
||||
setErrorCode('change_not_allowed');
|
||||
}
|
||||
}, []);
|
||||
|
||||
CreateMessageHook(CheckUserNameResultMessageEvent, onCheckUserNameResultMessageEvent);
|
||||
|
||||
const check = useCallback(() =>
|
||||
{
|
||||
if(newUsername === '') return;
|
||||
|
||||
setCanProceed(false);
|
||||
setSuggestions([]);
|
||||
setErrorCode(null);
|
||||
|
||||
setIsChecking(true);
|
||||
SendMessageHook(new CheckUserNameMessageComposer(newUsername));
|
||||
}, [ newUsername ]);
|
||||
|
||||
const handleUsernameChange = useCallback((username: string) =>
|
||||
{
|
||||
setCanProceed(false);
|
||||
setSuggestions([]);
|
||||
setErrorCode(null);
|
||||
|
||||
setNewUsername(username);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column gap-3 h-100">
|
||||
<div>{ LocalizeText('tutorial.name_change.info.select') }</div>
|
||||
<div className="d-flex gap-2">
|
||||
<input type="text" className="form-control form-control-sm" value={newUsername} onChange={ (e) => handleUsernameChange(e.target.value) } />
|
||||
<button className="btn btn-primary" disabled={ newUsername === '' || isChecking } onClick={ check }>{ LocalizeText('tutorial.name_change.check') }</button>
|
||||
</div>
|
||||
{ !errorCode && !canProceed && <div className="bg-muted rounded p-2 text-center">{ LocalizeText('help.tutorial.name.info') }</div> }
|
||||
{ errorCode && <div className="bg-danger rounded p-2 text-center text-white">{ LocalizeText(`help.tutorial.name.${errorCode}`, ['name'], [newUsername]) }</div> }
|
||||
{ canProceed && <div className="bg-success rounded p-2 text-center text-white">{ LocalizeText('help.tutorial.name.available', ['name'], [newUsername]) }</div> }
|
||||
{ suggestions && <div className="d-flex flex-column gap-2">
|
||||
{
|
||||
suggestions.map((suggestion, i) =>
|
||||
{
|
||||
return (<div key={ i } className="col bg-muted rounded p-1 cursor-pointer" onClick={ () => handleUsernameChange(suggestion) }>{ suggestion }</div>);
|
||||
})
|
||||
}
|
||||
</div> }
|
||||
<div className="d-flex gap-2">
|
||||
<button className="btn btn-success w-100" disabled={ !canProceed } onClick={ () => onAction('confirmation', newUsername) }>{ LocalizeText('tutorial.name_change.pick') }</button>
|
||||
<button className="btn btn-primary w-100" onClick={ () => onAction('close') }>{ LocalizeText('cancel') }</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
68
src/views/help/views/name-change/NameChangeView.tsx
Normal file
68
src/views/help/views/name-change/NameChangeView.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
import { FC, useCallback, useMemo, useState } from 'react';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { HelpNameChangeEvent } from '../../../../events/help/HelpNameChangeEvent';
|
||||
import { useUiEvent } from '../../../../hooks';
|
||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
||||
import { NameChangeConfirmationView } from './NameChangeConfirmationView';
|
||||
import { NameChangeInitView } from './NameChangeInitView';
|
||||
import { NameChangeInputView } from './NameChangeInputView';
|
||||
|
||||
const INIT: string = 'INIT';
|
||||
const INPUT: string = 'INPUT';
|
||||
const CONFIRMATION: string = 'CONFIRMATION';
|
||||
|
||||
export const NameChangeView:FC<{}> = props =>
|
||||
{
|
||||
const [ isVisible, setIsVisible ] = useState<boolean>(false);
|
||||
const [ layout, setLayout ] = useState<string>(INIT);
|
||||
const [ newUsername, setNewUsername ] = useState<string>('');
|
||||
|
||||
const onHelpNameChangeEvent = useCallback((event: HelpNameChangeEvent) =>
|
||||
{
|
||||
setLayout(INIT);
|
||||
setIsVisible(true);
|
||||
}, []);
|
||||
|
||||
useUiEvent(HelpNameChangeEvent.INIT, onHelpNameChangeEvent);
|
||||
|
||||
const onAction = useCallback((action: string, value?: string) =>
|
||||
{
|
||||
switch(action)
|
||||
{
|
||||
case 'start':
|
||||
setLayout(INPUT);
|
||||
break;
|
||||
case 'confirmation':
|
||||
setNewUsername(value);
|
||||
setLayout(CONFIRMATION);
|
||||
break;
|
||||
case 'close':
|
||||
setNewUsername('');
|
||||
setIsVisible(false);
|
||||
break;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const titleKey = useMemo(() =>
|
||||
{
|
||||
switch(layout)
|
||||
{
|
||||
case INIT: return 'tutorial.name_change.title.main';
|
||||
case INPUT: return 'tutorial.name_change.title.select';
|
||||
case CONFIRMATION: return 'tutorial.name_change.title.confirm';
|
||||
}
|
||||
}, [layout]);
|
||||
|
||||
if(!isVisible) return null;
|
||||
|
||||
return (
|
||||
<NitroCardView className="nitro-change-username" simple={ true }>
|
||||
<NitroCardHeaderView headerText={LocalizeText(titleKey)} onCloseClick={ () => onAction('close') } />
|
||||
<NitroCardContentView className="text-black">
|
||||
{ layout === INIT && <NameChangeInitView onAction={ onAction } /> }
|
||||
{ layout === INPUT && <NameChangeInputView onAction={ onAction } /> }
|
||||
{ layout === CONFIRMATION && <NameChangeConfirmationView username={ newUsername } onAction={ onAction } /> }
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
)
|
||||
}
|
5
src/views/help/views/name-change/NameChangeView.types.ts
Normal file
5
src/views/help/views/name-change/NameChangeView.types.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface NameChangeLayoutViewProps
|
||||
{
|
||||
username?: string;
|
||||
onAction: (action: string, value?: string) => void;
|
||||
}
|
@ -2,6 +2,7 @@ import { AvatarAction, AvatarExpressionEnum, RoomControllerLevel, RoomObjectCate
|
||||
import { FC, useCallback, useMemo, useState } from 'react';
|
||||
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, GetUserProfile, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUserActionMessage } from '../../../../../../api';
|
||||
import { AvatarEditorEvent } from '../../../../../../events';
|
||||
import { HelpNameChangeEvent } from '../../../../../../events/help/HelpNameChangeEvent';
|
||||
import { dispatchUiEvent } from '../../../../../../hooks';
|
||||
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
|
||||
import { useRoomContext } from '../../../../context/RoomContext';
|
||||
@ -42,6 +43,9 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
||||
case 'decorate':
|
||||
eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(true));
|
||||
break;
|
||||
case 'change_name':
|
||||
dispatchUiEvent(new HelpNameChangeEvent(HelpNameChangeEvent.INIT));
|
||||
break;
|
||||
case 'change_looks':
|
||||
dispatchUiEvent(new AvatarEditorEvent(AvatarEditorEvent.SHOW_EDITOR));
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user