Room Creator

This commit is contained in:
MyNameIsBatman 2021-06-29 23:15:32 -03:00
parent 9a94f59844
commit e00dd44888
6 changed files with 236 additions and 11 deletions

View File

@ -1,6 +1,7 @@
import { GenericErrorEvent, NavigatorCategoriesComposer, NavigatorMetadataEvent, NavigatorSearchEvent, NavigatorSettingsComposer, RoomDataParser, RoomDoorbellAcceptedEvent, RoomDoorbellEvent, RoomForwardEvent, RoomInfoComposer, RoomInfoEvent, RoomInfoOwnerEvent, UserInfoEvent } from 'nitro-renderer';
import { GenericErrorEvent, NavigatorCategoriesComposer, NavigatorCategoriesEvent, NavigatorMetadataEvent, NavigatorSearchEvent, NavigatorSettingsComposer, RoomCreatedEvent, RoomDataParser, RoomDoorbellAcceptedEvent, RoomDoorbellEvent, RoomForwardEvent, RoomInfoComposer, RoomInfoEvent, RoomInfoOwnerEvent, UserInfoEvent } from 'nitro-renderer';
import { FC, useCallback } from 'react';
import { GetRoomSessionManager, GetSessionDataManager } from '../../api';
import { VisitRoom } from '../../api/navigator/VisitRoom';
import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event';
import { useNavigatorContext } from './context/NavigatorContext';
import { NavigatorMessageHandlerProps } from './NavigatorMessageHandler.types';
@ -126,6 +127,25 @@ export const NavigatorMessageHandler: FC<NavigatorMessageHandlerProps> = props =
});
}, [ dispatchNavigatorState ]);
const onNavigatorCategoriesEvent = useCallback((event: NavigatorCategoriesEvent) =>
{
const parser = event.getParser();
dispatchNavigatorState({
type: NavigatorActions.SET_CATEGORIES,
payload: {
categories: parser.categories
}
});
}, [ dispatchNavigatorState ]);
const onRoomCreatedEvent = useCallback((event: RoomCreatedEvent) =>
{
const parser = event.getParser();
VisitRoom(parser.roomId);
}, []);
CreateMessageHook(UserInfoEvent, onUserInfoEvent);
CreateMessageHook(RoomForwardEvent, onRoomForwardEvent);
CreateMessageHook(RoomInfoOwnerEvent, onRoomInfoOwnerEvent);
@ -135,6 +155,8 @@ export const NavigatorMessageHandler: FC<NavigatorMessageHandlerProps> = props =
CreateMessageHook(GenericErrorEvent, onGenericErrorEvent);
CreateMessageHook(NavigatorMetadataEvent, onNavigatorMetadataEvent);
CreateMessageHook(NavigatorSearchEvent, onNavigatorSearchEvent);
CreateMessageHook(NavigatorCategoriesEvent, onNavigatorCategoriesEvent);
CreateMessageHook(RoomCreatedEvent, onRoomCreatedEvent);
return null;
}

View File

@ -10,6 +10,7 @@ import { NavigatorContextProvider } from './context/NavigatorContext';
import { NavigatorMessageHandler } from './NavigatorMessageHandler';
import { NavigatorViewProps } from './NavigatorView.types';
import { initialNavigator, NavigatorActions, NavigatorReducer } from './reducers/NavigatorReducer';
import { NavigatorRoomCreatorView } from './views/creator/NavigatorRoomCreatorView';
import { NavigatorSearchResultSetView } from './views/search-result-set/NavigatorSearchResultSetView';
import { NavigatorSearchView } from './views/search/NavigatorSearchView';
@ -46,6 +47,7 @@ export const NavigatorView: FC<NavigatorViewProps> = props =>
{
case RoomSessionEvent.CREATED:
setIsVisible(false);
setCreatorOpen(false);
return;
}
}, []);
@ -54,6 +56,7 @@ export const NavigatorView: FC<NavigatorViewProps> = props =>
const sendSearch = useCallback((searchValue: string, contextCode: string) =>
{
setCreatorOpen(false);
SendMessageHook(new NavigatorSearchComposer(contextCode, searchValue));
}, []);
@ -83,7 +86,7 @@ export const NavigatorView: FC<NavigatorViewProps> = props =>
<NavigatorMessageHandler />
{ isVisible &&
<NitroCardView className="nitro-navigator">
<NitroCardHeaderView headerText={ LocalizeText('navigator.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardHeaderView headerText={ LocalizeText(isCreatorOpen ? 'navigator.createroom.title' : 'navigator.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardTabsView>
{ topLevelContexts.map((context, index) =>
{
@ -93,14 +96,17 @@ export const NavigatorView: FC<NavigatorViewProps> = props =>
</NitroCardTabsItemView>
);
}) }
<NitroCardTabsItemView>
<NitroCardTabsItemView isActive={ isCreatorOpen } onClick={ () => setCreatorOpen(true) }>
<i className="fas fa-plus" />
</NitroCardTabsItemView>
</NitroCardTabsView>
<NitroCardContentView>
<div className="d-flex flex-column h-100">
<NavigatorSearchView sendSearch={ sendSearch } />
<NavigatorSearchResultSetView />
{ !isCreatorOpen && <>
<NavigatorSearchView sendSearch={ sendSearch } />
<NavigatorSearchResultSetView />
</> }
{ isCreatorOpen && <NavigatorRoomCreatorView /> }
</div>
</NitroCardContentView>
</NitroCardView> }

View File

@ -1,4 +1,4 @@
import { NavigatorSearchResultSet, NavigatorTopLevelContext } from 'nitro-renderer';
import { NavigatorCategoryDataParser, NavigatorSearchResultSet, NavigatorTopLevelContext } from 'nitro-renderer';
import { Reducer } from 'react';
export interface INavigatorState
@ -7,6 +7,7 @@ export interface INavigatorState
topLevelContext: NavigatorTopLevelContext;
topLevelContexts: NavigatorTopLevelContext[];
searchResult: NavigatorSearchResultSet;
categories: NavigatorCategoryDataParser[];
}
export interface INavigatorAction
@ -17,6 +18,7 @@ export interface INavigatorAction
topLevelContext?: NavigatorTopLevelContext;
topLevelContexts?: NavigatorTopLevelContext[];
searchResult?: NavigatorSearchResultSet;
categories?: NavigatorCategoryDataParser[];
}
}
@ -26,13 +28,15 @@ export class NavigatorActions
public static SET_TOP_LEVEL_CONTEXT: string = 'NA_SET_TOP_LEVEL_CONTEXT';
public static SET_TOP_LEVEL_CONTEXTS: string = 'NA_SET_TOP_LEVEL_CONTEXTS';
public static SET_SEARCH_RESULT: string = 'NA_SET_SEARCH_RESULT';
public static SET_CATEGORIES: string = 'NA_SET_CATEGORIES';
}
export const initialNavigator: INavigatorState = {
needsNavigatorUpdate: true,
topLevelContext: null,
topLevelContexts: null,
searchResult: null
searchResult: null,
categories: null
}
export const NavigatorReducer: Reducer<INavigatorState, INavigatorAction> = (state, action) =>
@ -81,6 +85,11 @@ export const NavigatorReducer: Reducer<INavigatorState, INavigatorAction> = (sta
return { ...state, topLevelContext, searchResult };
}
case NavigatorActions.SET_CATEGORIES: {
const categories = (action.payload.categories || state.categories || null);
return { ...state, categories };
}
default:
return state;
}

View File

@ -0,0 +1,26 @@
.room-model-list {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
> div {
border-color: $grid-border-color !important;
background-color: $grid-bg-color;
&.active {
border-color: $grid-active-border-color !important;
background-color: $grid-active-bg-color;
}
&.disabled {
cursor: not-allowed;
img {
opacity: .5;
filter: grayscale(1);
}
}
}
}

View File

@ -1,7 +1,129 @@
import { FC } from 'react';
import { NavigatorRoomCreatorViewProps } from './NavigatorRoomCreatorView.types';
import classNames from 'classnames';
import { HabboClubLevelEnum, RoomCreateComposer } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { GetConfiguration, GetSessionDataManager } from '../../../../api';
import { SendMessageHook } from '../../../../hooks/messages';
import { LocalizeText } from '../../../../utils/LocalizeText';
import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
import { useNavigatorContext } from '../../context/NavigatorContext';
import { NavigatorRoomCreatorViewProps, NAVIGATOR_ROOM_MODELS } from './NavigatorRoomCreatorView.types';
export const NavigatorRoomCreatorView: FC<NavigatorRoomCreatorViewProps> = props =>
{
return null;
const { navigatorState = null } = useNavigatorContext();
const { categories = null } = navigatorState;
const [ maxVisitorsList, setMaxVisitorsList ] = useState(null);
const [ name, setName ] = useState(null);
const [ description, setDescription ] = useState(null);
const [ category, setCategory ] = useState(null);
const [ visitorsCount, setVisitorsCount ] = useState(null);
const [ tradesSetting, setTradesSetting ] = useState(0);
const [ selectedModelName, setSelectedModelName ] = useState(NAVIGATOR_ROOM_MODELS[0].name);
useEffect(() =>
{
if(!maxVisitorsList)
{
const list = [];
for(let i = 10; i <= 100; i = i + 10)
{
list.push(i);
}
setMaxVisitorsList(list);
setVisitorsCount(list[0]);
}
}, []);
useEffect(() =>
{
if(categories) setCategory(categories[0].id);
}, [ categories ]);
const getRoomModelImage = useCallback((name: string) =>
{
return GetConfiguration<string>('images.url') + `/navigator/models/model_${ name }.png`;
}, []);
const selectModel = useCallback((name: string) =>
{
const model = NAVIGATOR_ROOM_MODELS.find(model => model.name === name);
if(!model) return;
if(model.clubLevel > GetSessionDataManager().clubLevel) return;
setSelectedModelName(name);
}, [ setSelectedModelName ]);
const createRoom = useCallback(() =>
{
if(!name || name.length < 3) return;
SendMessageHook(new RoomCreateComposer(name, description, 'model_' + selectedModelName, Number(category), Number(visitorsCount), tradesSetting));
}, [ name, description, category, visitorsCount, tradesSetting, selectedModelName ]);
return (
<div className="text-black d-flex flex-column h-100 justify-content-center">
<div className="row row-cols-2 mb-2">
<div className="col mb-2">
<div className="form-group">
<label>{ LocalizeText('navigator.createroom.roomnameinfo') }</label>
<input type="text" className="form-control form-control-sm" onChange={ (e) => setName(e.target.value) } />
</div>
</div>
<div className="col">
<div className="form-group">
<label>{ LocalizeText('navigator.category') }</label>
<select className="form-select form-select-sm" onChange={ (e) => setCategory(e.target.value) }>
{ categories && categories.map(category =>
{
return <option key={ category.id } value={ category.id }>{ LocalizeText(category.name) }</option>
}) }
</select>
</div>
</div>
<div className="col">
<div className="form-group">
<label>{ LocalizeText('navigator.maxvisitors') }</label>
<select className="form-select form-select-sm" onChange={ (e) => setVisitorsCount(e.target.value) }>
{ maxVisitorsList && maxVisitorsList.map(value =>
{
return <option key={ value } value={ value }>{ value }</option>
}) }
</select>
</div>
</div>
<div className="col">
<div className="form-group">
<label>{ LocalizeText('navigator.tradesettings') }</label>
<select className="form-select form-select-sm" onChange={ (e) => setTradesSetting(Number(e.target.value)) }>
<option value="0">{ LocalizeText('${navigator.roomsettings.trade_not_allowed}') }</option>
<option value="1">{ LocalizeText('${navigator.roomsettings.trade_not_with_Controller}') }</option>
<option value="2">{ LocalizeText('${navigator.roomsettings.trade_allowed}') }</option>
</select>
</div>
</div>
</div>
<div className="form-group mb-3">
<label>{ LocalizeText('navigator.createroom.roomdescinfo') }</label>
<input type="text" className="form-control form-control-sm" onChange={ (e) => setDescription(e.target.value) } />
</div>
<div className="room-model-list pb-2 mb-2">
{
NAVIGATOR_ROOM_MODELS.map(model =>
{
return (<div key={ model.name } onClick={ () => selectModel(model.name) } className={ 'h-100 cursor-pointer d-flex flex-column justify-content-center align-items-center p-1 me-2 rounded border border-2' + classNames({' active': selectedModelName === model.name, ' disabled': GetSessionDataManager().clubLevel < model.clubLevel}) }>
<img src={ getRoomModelImage(model.name) } />
<div>{ model.tileSize } { LocalizeText('navigator.createroom.tilesize') }</div>
{ model.clubLevel > HabboClubLevelEnum.NO_CLUB && <CurrencyIcon type="hc" /> }
</div>);
})
}
</div>
<button className="btn btn-success float-end" onClick={ () => createRoom() } disabled={ !name || name.length < 3 }>{ LocalizeText('navigator.createroom.create') }</button>
</div>
);
}

View File

@ -1,4 +1,44 @@
import { HabboClubLevelEnum } from 'nitro-renderer';
export interface NavigatorRoomCreatorViewProps
{
}
export const NAVIGATOR_ROOM_MODELS: { clubLevel: number, tileSize: number, name: string }[] = [
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 104, name: 'a'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 94, name: 'b'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 36, name: 'c'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 84, name: 'd'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 80, name: 'e'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 80, name: 'f'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 416, name: 'i'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 320, name: 'j'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 448, name: 'k'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 352, name: 'l'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 384, name: 'm'},
{ clubLevel: HabboClubLevelEnum.NO_CLUB, tileSize: 372, name: 'n'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 80, name: 'g'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 74, name: 'h'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 416, name: 'o'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 352, name: 'p'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 304, name: 'q'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 336, name: 'r'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 748, name: 'u'},
{ clubLevel: HabboClubLevelEnum.CLUB, tileSize: 438, name: 'v'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 540, name: 't'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 512, name: 'w'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 396, name: 'x'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 440, name: 'y'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 456, name: 'z'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 208, name: '0'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 1009, name: '1'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 1044, name: '2'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 183, name: '3'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 254, name: '4'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 1024, name: '5'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 801, name: '6'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 354, name: '7'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 888, name: '8'},
{ clubLevel: HabboClubLevelEnum.VIP, tileSize: 926, name: '9'}
];