🆙 Update the navigator
@@ -0,0 +1,11 @@
|
||||
import { AddFavouriteRoomMessageComposer, DeleteFavouriteRoomMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { SendMessageComposer } from '..';
|
||||
|
||||
export const ToggleFavoriteRoom = (roomId: number, isFavorite: boolean): void =>
|
||||
{
|
||||
if(roomId <= 0) return;
|
||||
|
||||
SendMessageComposer(isFavorite
|
||||
? new DeleteFavouriteRoomMessageComposer(roomId)
|
||||
: new AddFavouriteRoomMessageComposer(roomId));
|
||||
};
|
||||
@@ -9,4 +9,5 @@ export * from './NavigatorSearchResultViewDisplayMode';
|
||||
export * from './RoomInfoData';
|
||||
export * from './RoomSettingsUtils';
|
||||
export * from './SearchFilterOptions';
|
||||
export * from './ToggleFavoriteRoom';
|
||||
export * from './TryVisitRoom';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { CreateLinkEvent } from '@nitrots/nitro-renderer';
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './CreateLinkEvent';
|
||||
export * from './GetConfigurationValue';
|
||||
export * from './OpenUrl';
|
||||
export * from './SendMessageComposer';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { GetSessionDataManager } from '@nitrots/nitro-renderer';
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './CanManipulateFurniture';
|
||||
export * from './GetSessionDataManager';
|
||||
export * from './CreateRoomSession';
|
||||
export * from './GetCanStandUp';
|
||||
export * from './GetCanUseExpression';
|
||||
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 461 B |
|
After Width: | Height: | Size: 674 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 286 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 474 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 481 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 215 B |
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 214 B |
|
After Width: | Height: | Size: 198 B |
|
After Width: | Height: | Size: 381 B |
|
After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -41,7 +41,7 @@ export const Text: FC<TextProps> = props => {
|
||||
} = props;
|
||||
|
||||
const getClassNames = useMemo(() => {
|
||||
const newClassNames: string[] = ['inline'];
|
||||
const newClassNames: string[] = [truncate ? 'block' : 'inline'];
|
||||
|
||||
if (variant) {
|
||||
if (variant === 'primary') newClassNames.push('text-[#1e7295]');
|
||||
@@ -54,7 +54,7 @@ export const Text: FC<TextProps> = props => {
|
||||
if (variant == 'danger') newClassNames.push('text-[#a81a12]');
|
||||
if (variant == 'warning') newClassNames.push('text-[#ffc107]');
|
||||
}
|
||||
|
||||
|
||||
if (bold) newClassNames.push('font-bold');
|
||||
if (fontWeight) newClassNames.push('font-' + fontWeight);
|
||||
if (fontSize) newClassNames.push('fs-' + fontSize);
|
||||
@@ -62,7 +62,7 @@ export const Text: FC<TextProps> = props => {
|
||||
if (align) newClassNames.push('text-' + align);
|
||||
if (underline) newClassNames.push('underline');
|
||||
if (italics) newClassNames.push('italic');
|
||||
if (truncate) newClassNames.push('text-truncate');
|
||||
if (truncate) newClassNames.push('truncate', 'min-w-0');
|
||||
if (center) newClassNames.push('text-center');
|
||||
if (textEnd) newClassNames.push('text-end');
|
||||
if (small) newClassNames.push('text-sm');
|
||||
@@ -71,7 +71,7 @@ export const Text: FC<TextProps> = props => {
|
||||
if (textBreak) newClassNames.push('text-break');
|
||||
|
||||
return newClassNames;
|
||||
}, [variant, fontWeight, fontSize, fontSizeCustom, align, bold, underline, italics, truncate, center, textEnd, small, wrap, noWrap, textBreak]);
|
||||
}, [ variant, fontWeight, fontSize, fontSizeCustom, align, bold, underline, italics, truncate, center, textEnd, small, wrap, noWrap, textBreak ]);
|
||||
|
||||
const style = fontSizeCustom ? { '--font-size': `${fontSizeCustom}px` } as React.CSSProperties : undefined;
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { FC } from 'react';
|
||||
import { FaBolt } from 'react-icons/fa';
|
||||
|
||||
export interface LayoutSearchSavesViewProps
|
||||
{
|
||||
title: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export const LayoutSearchSavesView: FC<LayoutSearchSavesViewProps> = props =>
|
||||
{
|
||||
const { title = null, onClick = null } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
title={ title }
|
||||
onClick={ onClick }
|
||||
style={{ backgroundColor: '#FAA700', borderRadius: 4, padding: '2px 4px', fontSize: 10, height: 17, display: 'flex', alignItems: 'center', cursor: 'pointer', color: 'white' }}
|
||||
>
|
||||
<FaBolt />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -19,6 +19,7 @@ export * from './LayoutRarityLevelView';
|
||||
export * from './LayoutRoomObjectImageView';
|
||||
export * from './LayoutRoomPreviewerView';
|
||||
export * from './LayoutRoomThumbnailView';
|
||||
export * from './LayoutSearchSavesView';
|
||||
export * from './LayoutTrophyView';
|
||||
export * from './UserProfileIconView';
|
||||
export * from './limited-edition';
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
.button-search-saves {
|
||||
padding: 4px;
|
||||
height: 17px;
|
||||
margin-top: -1px;
|
||||
font-size: 10px;
|
||||
border-radius: 4px;
|
||||
background-color: #FAA700;
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
import { NitroCard } from '@layout/NitroCard';
|
||||
import { AddLinkEventTracker, ConvertGlobalRoomIdMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RemoveLinkEventTracker, RoomSessionEvent } from '@nitrots/nitro-renderer';
|
||||
import { AddLinkEventTracker, ConvertGlobalRoomIdMessageComposer, FindNewFriendsMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RemoveLinkEventTracker, RoomSessionEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { FaPlus } from 'react-icons/fa';
|
||||
import { LocalizeText, SendMessageComposer, TryVisitRoom } from '../../api';
|
||||
import savesSearchIcon from '../../assets/images/navigator/saves-search/search_save.png';
|
||||
import createRoomImg from '../../assets/images/navigator/create_room.png';
|
||||
import randomRoomImg from '../../assets/images/navigator/random_room.png';
|
||||
import promoteRoomImg from '../../assets/images/navigator/promote_room.png';
|
||||
import { CreateLinkEvent, LocalizeText, SendMessageComposer, TryVisitRoom } from '../../api';
|
||||
import { Flex, Text } from '../../common';
|
||||
import { useNavigator, useNitroEvent } from '../../hooks';
|
||||
import { NavigatorDoorStateView } from './views/NavigatorDoorStateView';
|
||||
import { NavigatorRoomCreatorView } from './views/NavigatorRoomCreatorView';
|
||||
@@ -10,6 +15,7 @@ import { NavigatorRoomInfoView } from './views/NavigatorRoomInfoView';
|
||||
import { NavigatorRoomLinkView } from './views/NavigatorRoomLinkView';
|
||||
import { NavigatorRoomSettingsView } from './views/room-settings/NavigatorRoomSettingsView';
|
||||
import { NavigatorSearchResultView } from './views/search/NavigatorSearchResultView';
|
||||
import { NavigatorSearchSavesResultView } from './views/search/NavigatorSearchSavesResultView';
|
||||
import { NavigatorSearchView } from './views/search/NavigatorSearchView';
|
||||
|
||||
export const NavigatorView: FC<{}> = props =>
|
||||
@@ -19,10 +25,11 @@ export const NavigatorView: FC<{}> = props =>
|
||||
const [ isCreatorOpen, setCreatorOpen ] = useState(false);
|
||||
const [ isRoomInfoOpen, setRoomInfoOpen ] = useState(false);
|
||||
const [ isRoomLinkOpen, setRoomLinkOpen ] = useState(false);
|
||||
const [ isOpenSavesSearches, setIsOpenSavesSearches ] = useState(false);
|
||||
const [ isLoading, setIsLoading ] = useState(false);
|
||||
const [ needsInit, setNeedsInit ] = useState(true);
|
||||
const [ needsSearch, setNeedsSearch ] = useState(false);
|
||||
const { searchResult = null, topLevelContext = null, topLevelContexts = null, navigatorData = null } = useNavigator();
|
||||
const { searchResult = null, topLevelContext = null, topLevelContexts = null, navigatorData = null, navigatorSearches = null } = useNavigator();
|
||||
const pendingSearch = useRef<{ value: string, code: string }>(null);
|
||||
const elementRef = useRef<HTMLDivElement>();
|
||||
|
||||
@@ -197,12 +204,18 @@ export const NavigatorView: FC<{}> = props =>
|
||||
<>
|
||||
{ isVisible &&
|
||||
<NitroCard
|
||||
className="w-navigator-w h-navigator-h min-w-navigator-w min-h-navigator-h"
|
||||
className={ `${ isOpenSavesSearches ? 'w-[600px] min-w-[600px]' : 'w-navigator-w min-w-navigator-w' } h-navigator-h min-h-navigator-h` }
|
||||
uniqueKey="navigator">
|
||||
<NitroCard.Header
|
||||
headerText={ LocalizeText(isCreatorOpen ? 'navigator.createroom.title' : 'navigator.title') }
|
||||
onCloseClick={ event => setIsVisible(false) } />
|
||||
<NitroCard.Tabs>
|
||||
<NitroCard.TabItem
|
||||
isActive={ isOpenSavesSearches }
|
||||
title={ LocalizeText('navigator.tooltip.left.show.hide') }
|
||||
onClick={ () => setIsOpenSavesSearches(prev => !prev) }>
|
||||
<img src={ savesSearchIcon } alt="" style={{ width: 18, height: 18 }} />
|
||||
</NitroCard.TabItem>
|
||||
{ topLevelContexts && (topLevelContexts.length > 0) && topLevelContexts.map((context, index) =>
|
||||
{
|
||||
return (
|
||||
@@ -222,12 +235,58 @@ export const NavigatorView: FC<{}> = props =>
|
||||
</NitroCard.Tabs>
|
||||
<NitroCard.Content isLoading={ isLoading }>
|
||||
{ !isCreatorOpen &&
|
||||
<>
|
||||
<NavigatorSearchView sendSearch={ sendSearch } />
|
||||
<div ref={ elementRef } className="flex flex-col overflow-auto gap-2">
|
||||
{ (searchResult && searchResult.results.map((result, index) => <NavigatorSearchResultView key={ index } searchResult={ result } />)) }
|
||||
<div className="flex h-full overflow-hidden gap-2">
|
||||
{ isOpenSavesSearches &&
|
||||
<div className="overflow-hidden pr-1 shrink-0">
|
||||
<NavigatorSearchSavesResultView searches={ navigatorSearches || [] } />
|
||||
</div> }
|
||||
<div className="flex flex-col w-full overflow-hidden gap-2">
|
||||
<NavigatorSearchView sendSearch={ sendSearch } />
|
||||
<div ref={ elementRef } className="flex flex-col flex-1 min-h-0 overflow-auto gap-2">
|
||||
{ (searchResult && searchResult.results.map((result, index) => <NavigatorSearchResultView key={ index } searchResult={ result } />)) }
|
||||
</div>
|
||||
<Flex className="pt-2 border-t border-muted gap-2">
|
||||
<Flex
|
||||
pointer
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
className="flex-1 h-[60px] cursor-pointer bg-no-repeat pl-16"
|
||||
style={ { backgroundImage: `url(${ createRoomImg })`, backgroundSize: '100% 100%' } }
|
||||
onClick={ () => setCreatorOpen(true) }
|
||||
>
|
||||
<Text variant="white" bold className="text-xs drop-shadow">
|
||||
{ LocalizeText('navigator.createroom.create') }
|
||||
</Text>
|
||||
</Flex>
|
||||
{ (searchResult?.code !== 'myworld_view' && searchResult?.code !== 'roomads_view') &&
|
||||
<Flex
|
||||
pointer
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
className="flex-1 h-[60px] cursor-pointer bg-no-repeat pl-16"
|
||||
style={ { backgroundImage: `url(${ randomRoomImg })`, backgroundSize: '100% 100%' } }
|
||||
onClick={ () => SendMessageComposer(new FindNewFriendsMessageComposer()) }
|
||||
>
|
||||
<Text variant="white" bold className="text-xs drop-shadow">
|
||||
{ LocalizeText('navigator.random.room') }
|
||||
</Text>
|
||||
</Flex> }
|
||||
{ (searchResult?.code === 'myworld_view' || searchResult?.code === 'roomads_view') &&
|
||||
<Flex
|
||||
pointer
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
className="flex-1 h-[60px] cursor-pointer bg-no-repeat pl-16"
|
||||
style={ { backgroundImage: `url(${ promoteRoomImg })`, backgroundSize: '100% 100%' } }
|
||||
onClick={ () => CreateLinkEvent('catalog/open/room_event') }
|
||||
>
|
||||
<Text variant="white" bold className="text-xs drop-shadow">
|
||||
{ LocalizeText('navigator.promote.room') }
|
||||
</Text>
|
||||
</Flex> }
|
||||
</Flex>
|
||||
</div>
|
||||
</> }
|
||||
</div> }
|
||||
{ isCreatorOpen && <NavigatorRoomCreatorView /> }
|
||||
</NitroCard.Content>
|
||||
</NitroCard> }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CreateLinkEvent, GetCustomRoomFilterMessageComposer, GetSessionDataManager, NavigatorSearchComposer, RemoveOwnRoomRightsRoomMessageComposer, RoomControllerLevel, RoomMuteComposer, RoomSettingsComposer, SecurityLevel, ToggleStaffPickMessageComposer, UpdateHomeRoomMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { CreateLinkEvent, GetCustomRoomFilterMessageComposer, GetGuestRoomMessageComposer, GetSessionDataManager, NavigatorSearchComposer, RemoveOwnRoomRightsRoomMessageComposer, RoomControllerLevel, RoomMuteComposer, RoomSettingsComposer, SecurityLevel, ToggleStaffPickMessageComposer, UpdateHomeRoomMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { FaLink, FaSignOutAlt } from 'react-icons/fa';
|
||||
import { DispatchUiEvent, GetGroupInformation, LocalizeText, ReportType, SendMessageComposer } from '../../../api';
|
||||
import { DispatchUiEvent, GetGroupInformation, LocalizeText, ReportType, SendMessageComposer, ToggleFavoriteRoom } from '../../../api';
|
||||
import { Button, Column, Flex, LayoutBadgeImageView, LayoutRoomThumbnailView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text, UserProfileIconView } from '../../../common';
|
||||
import { RoomWidgetThumbnailEvent } from '../../../events';
|
||||
import { useHelp, useNavigator, useRoom } from '../../../hooks';
|
||||
@@ -11,16 +11,45 @@ export interface NavigatorRoomInfoViewProps {
|
||||
onCloseClick: () => void;
|
||||
}
|
||||
|
||||
export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props => {
|
||||
export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
|
||||
{
|
||||
const { onCloseClick = null } = props;
|
||||
const [ isRoomPicked, setIsRoomPicked ] = useState(false);
|
||||
const [ isRoomMuted, setIsRoomMuted ] = useState(false);
|
||||
const { report = null } = useHelp();
|
||||
const { navigatorData = null } = useNavigator();
|
||||
const { navigatorData = null, favouriteRoomIds = [] } = useNavigator();
|
||||
const { roomSession = null } = useRoom();
|
||||
|
||||
const hasPermission = (permission: string) => {
|
||||
switch(permission) {
|
||||
const enteredRoomId = navigatorData?.enteredGuestRoom?.roomId ?? 0;
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!enteredRoomId) return;
|
||||
SendMessageComposer(new GetGuestRoomMessageComposer(enteredRoomId, false, false));
|
||||
}, [ enteredRoomId ]);
|
||||
|
||||
const isRoomInFavouritesList = useMemo(() =>
|
||||
{
|
||||
if(!enteredRoomId) return false;
|
||||
|
||||
return favouriteRoomIds.some((id: any) =>
|
||||
{
|
||||
if(id && typeof id === 'object')
|
||||
{
|
||||
if('roomId' in id) return Number(id.roomId) === enteredRoomId;
|
||||
if('id' in id) return Number(id.id) === enteredRoomId;
|
||||
}
|
||||
|
||||
return String(id) === String(enteredRoomId);
|
||||
});
|
||||
}, [ favouriteRoomIds, enteredRoomId ]);
|
||||
|
||||
const hasPermission = (permission: string) =>
|
||||
{
|
||||
if(!navigatorData?.enteredGuestRoom) return false;
|
||||
|
||||
switch(permission)
|
||||
{
|
||||
case 'settings':
|
||||
return (GetSessionDataManager().userId === navigatorData.enteredGuestRoom.ownerId || GetSessionDataManager().isModerator);
|
||||
case 'staff_pick':
|
||||
@@ -33,17 +62,21 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props => {
|
||||
}
|
||||
};
|
||||
|
||||
const processAction = (action: string, value?: string) => {
|
||||
if(!navigatorData || !navigatorData.enteredGuestRoom) return;
|
||||
const processAction = (action: string, value?: string) =>
|
||||
{
|
||||
if(!navigatorData?.enteredGuestRoom) return;
|
||||
|
||||
switch(action) {
|
||||
const roomId = navigatorData.enteredGuestRoom.roomId;
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case 'set_home_room':
|
||||
{
|
||||
let newRoomId = -1;
|
||||
if(navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId) {
|
||||
newRoomId = navigatorData.enteredGuestRoom.roomId;
|
||||
}
|
||||
if(navigatorData.homeRoomId !== roomId) newRoomId = roomId;
|
||||
if(newRoomId > 0) SendMessageComposer(new UpdateHomeRoomMessageComposer(newRoomId));
|
||||
return;
|
||||
}
|
||||
case 'navigator_search_tag':
|
||||
CreateLinkEvent(`navigator/search/${ value }`);
|
||||
SendMessageComposer(new NavigatorSearchComposer('hotel_view', `tag:${ value }`));
|
||||
@@ -58,27 +91,33 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props => {
|
||||
CreateLinkEvent('navigator/toggle-room-link');
|
||||
return;
|
||||
case 'open_room_settings':
|
||||
SendMessageComposer(new RoomSettingsComposer(navigatorData.enteredGuestRoom.roomId));
|
||||
SendMessageComposer(new RoomSettingsComposer(roomId));
|
||||
return;
|
||||
case 'toggle_pick':
|
||||
setIsRoomPicked(value => !value);
|
||||
SendMessageComposer(new ToggleStaffPickMessageComposer(navigatorData.enteredGuestRoom.roomId));
|
||||
setIsRoomPicked(prev => !prev);
|
||||
SendMessageComposer(new ToggleStaffPickMessageComposer(roomId));
|
||||
SendMessageComposer(new GetGuestRoomMessageComposer(roomId, false, false));
|
||||
return;
|
||||
case 'toggle_mute':
|
||||
setIsRoomMuted(value => !value);
|
||||
setIsRoomMuted(prev => !prev);
|
||||
SendMessageComposer(new RoomMuteComposer());
|
||||
SendMessageComposer(new GetGuestRoomMessageComposer(roomId, false, false));
|
||||
return;
|
||||
case 'room_filter':
|
||||
SendMessageComposer(new GetCustomRoomFilterMessageComposer(navigatorData.enteredGuestRoom.roomId));
|
||||
SendMessageComposer(new GetCustomRoomFilterMessageComposer(roomId));
|
||||
return;
|
||||
case 'open_floorplan_editor':
|
||||
CreateLinkEvent('floor-editor/toggle');
|
||||
return;
|
||||
case 'report_room':
|
||||
report(ReportType.ROOM, { roomId: navigatorData.enteredGuestRoom.roomId, roomName: navigatorData.enteredGuestRoom.roomName });
|
||||
report(ReportType.ROOM, { roomId, roomName: navigatorData.enteredGuestRoom.roomName });
|
||||
return;
|
||||
case 'room_favourite':
|
||||
ToggleFavoriteRoom(roomId, isRoomInFavouritesList);
|
||||
SendMessageComposer(new GetGuestRoomMessageComposer(roomId, false, false));
|
||||
return;
|
||||
case 'remove_rights':
|
||||
SendMessageComposer(new RemoveOwnRoomRightsRoomMessageComposer(navigatorData.enteredGuestRoom.roomId));
|
||||
SendMessageComposer(new RemoveOwnRoomRightsRoomMessageComposer(roomId));
|
||||
return;
|
||||
case 'close':
|
||||
onCloseClick();
|
||||
@@ -86,96 +125,105 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!navigatorData) return;
|
||||
|
||||
setIsRoomPicked(navigatorData.currentRoomIsStaffPick);
|
||||
if(navigatorData.enteredGuestRoom) setIsRoomMuted(navigatorData.enteredGuestRoom.allInRoomMuted);
|
||||
}, [ navigatorData ]);
|
||||
|
||||
if(!navigatorData.enteredGuestRoom) return null;
|
||||
if(!navigatorData?.enteredGuestRoom) return null;
|
||||
|
||||
return (
|
||||
<NitroCardView className="nitro-room-info" theme="primary-slim">
|
||||
<NitroCardHeaderView headerText={ LocalizeText('navigator.roomsettings.roominfo') } onCloseClick={ () => processAction('close') } />
|
||||
<NitroCardContentView className="text-black">
|
||||
{ navigatorData.enteredGuestRoom &&
|
||||
<>
|
||||
<Flex gap={ 2 } overflow="hidden">
|
||||
<LayoutRoomThumbnailView customUrl={ navigatorData.enteredGuestRoom.officialRoomPicRef } roomId={ navigatorData.enteredGuestRoom.roomId }>
|
||||
{ hasPermission('settings') && <i className="top-0 m-1 cursor-pointer nitro-icon icon-camera-small absolute b-0 r-0" onClick={ () => processAction('open_room_thumbnail_camera') } /> }
|
||||
</LayoutRoomThumbnailView>
|
||||
<Column grow gap={ 1 } overflow="hidden">
|
||||
<Flex gap={ 2 } overflow="hidden">
|
||||
<LayoutRoomThumbnailView customUrl={ navigatorData.enteredGuestRoom.officialRoomPicRef } roomId={ navigatorData.enteredGuestRoom.roomId }>
|
||||
{ hasPermission('settings') && <i className="top-0 m-1 cursor-pointer nitro-icon icon-camera-small absolute b-0 r-0" onClick={ () => processAction('open_room_thumbnail_camera') } /> }
|
||||
</LayoutRoomThumbnailView>
|
||||
<Column grow gap={ 1 } overflow="hidden">
|
||||
<div className="flex gap-1">
|
||||
<Column grow gap={ 0 }>
|
||||
<div className="flex gap-1">
|
||||
<Column grow gap={ 1 }>
|
||||
<div className="flex gap-1">
|
||||
<Text>{ navigatorData.enteredGuestRoom.roomName }</Text>
|
||||
</div>
|
||||
{ navigatorData.enteredGuestRoom.showOwner &&
|
||||
<div className="flex items-center gap-1">
|
||||
<Text>{ LocalizeText('navigator.roomownercaption') }</Text>
|
||||
<div className="flex items-center gap-1">
|
||||
<UserProfileIconView userId={ navigatorData.enteredGuestRoom.ownerId } />
|
||||
<Text>{ navigatorData.enteredGuestRoom.ownerName }</Text>
|
||||
</div>
|
||||
</div> }
|
||||
<div className="flex items-center gap-1">
|
||||
<Text>{ LocalizeText('navigator.roomrating') }</Text>
|
||||
<Text>{ navigatorData.currentRoomRating }</Text>
|
||||
</div>
|
||||
{ (navigatorData.enteredGuestRoom.tags.length > 0) &&
|
||||
<div className="flex items-center gap-1">
|
||||
{ navigatorData.enteredGuestRoom.tags.map(tag =>
|
||||
<Text key={ tag } pointer className="p-1 rounded bg-muted" onClick={ event => processAction('navigator_search_tag', tag) }>#{ tag }</Text>
|
||||
) }
|
||||
</div> }
|
||||
</Column>
|
||||
<Column alignItems="center" gap={ 1 }>
|
||||
<i className={ classNames('shrink-0 nitro-icon icon-house-small cursor-pointer', ((navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId) && 'gray')) } onClick={ () => processAction('set_home_room') } />
|
||||
{ hasPermission('settings') &&
|
||||
<i className="cursor-pointer nitro-icon icon-cog" title={ LocalizeText('navigator.room.popup.info.room.settings') } onClick={ event => processAction('open_room_settings') } /> }
|
||||
<FaLink className="cursor-pointer fa-icon" title={ LocalizeText('navigator.embed.caption') } onClick={ event => processAction('toggle_room_link') } />
|
||||
{ hasPermission('guest') &&
|
||||
<FaSignOutAlt className="cursor-pointer fa-icon" title={ LocalizeText('navigator.roominfo.removerights.tooltip') } onClick={ event => processAction('remove_rights') } /> }
|
||||
</Column>
|
||||
<Text bold wrap>{ navigatorData.enteredGuestRoom.roomName }</Text>
|
||||
</div>
|
||||
<Text overflow="auto" style={ { maxHeight: 50 } }>{ navigatorData.enteredGuestRoom.description }</Text>
|
||||
{ (navigatorData.enteredGuestRoom.habboGroupId > 0) &&
|
||||
<Flex pointer alignItems="center" gap={ 1 } onClick={ () => processAction('open_group_info') }>
|
||||
<LayoutBadgeImageView badgeCode={ navigatorData.enteredGuestRoom.groupBadgeCode } className="flex-none" isGroup={ true } />
|
||||
<Text underline>
|
||||
{ LocalizeText('navigator.guildbase', [ 'groupName' ], [ navigatorData.enteredGuestRoom.groupName ]) }
|
||||
</Text>
|
||||
</Flex> }
|
||||
{ navigatorData.enteredGuestRoom.showOwner &&
|
||||
<div className="flex items-center gap-1">
|
||||
<Text small bold variant="muted">{ LocalizeText('navigator.roomownercaption') }</Text>
|
||||
<div className="flex items-center gap-1">
|
||||
<UserProfileIconView userId={ navigatorData.enteredGuestRoom.ownerId } />
|
||||
<Text small>{ navigatorData.enteredGuestRoom.ownerName }</Text>
|
||||
</div>
|
||||
</div> }
|
||||
<div className="flex items-center gap-1">
|
||||
<Text small bold variant="muted">{ LocalizeText('navigator.roomrating') }</Text>
|
||||
<Text small>{ navigatorData.currentRoomRating }</Text>
|
||||
</div>
|
||||
{ (navigatorData.enteredGuestRoom.tags.length > 0) &&
|
||||
<div className="flex flex-wrap items-center gap-1 mt-1">
|
||||
{ navigatorData.enteredGuestRoom.tags.map(tag => (
|
||||
<Text key={ tag } pointer className="px-1 rounded bg-muted cursor-pointer text-xs" onClick={ () => processAction('navigator_search_tag', tag) }>
|
||||
#{ tag }
|
||||
</Text>
|
||||
)) }
|
||||
</div> }
|
||||
</Column>
|
||||
<Column alignItems="center" gap={ 1 }>
|
||||
<i
|
||||
className={ classNames('shrink-0 nitro-icon icon-house-small cursor-pointer', ((navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId) && 'gray')) }
|
||||
title={ LocalizeText('navigator.room.popup.room.info.home') }
|
||||
onClick={ () => processAction('set_home_room') }
|
||||
/>
|
||||
{ GetSessionDataManager().userId !== navigatorData.enteredGuestRoom.ownerId &&
|
||||
<i
|
||||
className={ classNames('shrink-0 nitro-icon cursor-pointer', isRoomInFavouritesList ? 'icon-group-favorite' : 'icon-group-not-favorite') }
|
||||
title={ LocalizeText('navigator.room.popup.room.info.favorite') }
|
||||
onClick={ () => processAction('room_favourite') }
|
||||
/> }
|
||||
{ hasPermission('settings') &&
|
||||
<i className="cursor-pointer nitro-icon icon-cog" title={ LocalizeText('navigator.room.popup.info.room.settings') } onClick={ () => processAction('open_room_settings') } /> }
|
||||
<FaLink className="cursor-pointer fa-icon" title={ LocalizeText('navigator.embed.caption') } onClick={ () => processAction('toggle_room_link') } />
|
||||
{ hasPermission('guest') &&
|
||||
<FaSignOutAlt className="cursor-pointer fa-icon" title={ LocalizeText('navigator.roominfo.removerights.tooltip') } onClick={ () => processAction('remove_rights') } /> }
|
||||
</Column>
|
||||
</Flex>
|
||||
<div className="flex flex-col gap-1">
|
||||
{ hasPermission('staff_pick') &&
|
||||
<Button onClick={ () => processAction('toggle_pick') }>
|
||||
{ LocalizeText(isRoomPicked ? 'navigator.staffpicks.unpick' : 'navigator.staffpicks.pick') }
|
||||
</Button> }
|
||||
<Button variant="danger" onClick={ () => processAction('report_room') }>
|
||||
{ LocalizeText('help.emergency.main.report.room') }
|
||||
</Button>
|
||||
{ hasPermission('settings') &&
|
||||
<>
|
||||
<Button onClick={ () => processAction('toggle_mute') }>
|
||||
{ LocalizeText(isRoomMuted ? 'navigator.muteall_on' : 'navigator.muteall_off') }
|
||||
</Button>
|
||||
<Button onClick={ () => processAction('room_filter') }>
|
||||
{ LocalizeText('navigator.roomsettings.roomfilter') }
|
||||
</Button>
|
||||
<Button onClick={ () => processAction('open_floorplan_editor') }>
|
||||
{ LocalizeText('open.floor.plan.editor') }
|
||||
</Button>
|
||||
</> }
|
||||
{ hasPermission('floor') && !hasPermission('settings') &&
|
||||
<Button onClick={ () => processAction('open_floorplan_editor') }>
|
||||
{ LocalizeText('open.floor.plan.editor') }
|
||||
</Button> }
|
||||
</div>
|
||||
</> }
|
||||
<Text small overflow="auto" style={ { maxHeight: 50 } }>{ navigatorData.enteredGuestRoom.description }</Text>
|
||||
{ (navigatorData.enteredGuestRoom.habboGroupId > 0) &&
|
||||
<Flex pointer alignItems="center" gap={ 1 } onClick={ () => processAction('open_group_info') }>
|
||||
<LayoutBadgeImageView badgeCode={ navigatorData.enteredGuestRoom.groupBadgeCode } className="flex-none" isGroup={ true } />
|
||||
<Text small underline>
|
||||
{ LocalizeText('navigator.guildbase', [ 'groupName' ], [ navigatorData.enteredGuestRoom.groupName ]) }
|
||||
</Text>
|
||||
</Flex> }
|
||||
</Column>
|
||||
</Flex>
|
||||
<div className="flex flex-col gap-1 mt-1">
|
||||
{ hasPermission('staff_pick') &&
|
||||
<Button onClick={ () => processAction('toggle_pick') }>
|
||||
{ LocalizeText(isRoomPicked ? 'navigator.staffpicks.unpick' : 'navigator.staffpicks.pick') }
|
||||
</Button> }
|
||||
<Button variant="danger" onClick={ () => processAction('report_room') }>
|
||||
{ LocalizeText('help.emergency.main.report.room') }
|
||||
</Button>
|
||||
{ hasPermission('settings') &&
|
||||
<>
|
||||
<Button onClick={ () => processAction('toggle_mute') }>
|
||||
{ LocalizeText(isRoomMuted ? 'navigator.muteall_on' : 'navigator.muteall_off') }
|
||||
</Button>
|
||||
<Button onClick={ () => processAction('room_filter') }>
|
||||
{ LocalizeText('navigator.roomsettings.roomfilter') }
|
||||
</Button>
|
||||
<Button onClick={ () => processAction('open_floorplan_editor') }>
|
||||
{ LocalizeText('open.floor.plan.editor') }
|
||||
</Button>
|
||||
</> }
|
||||
{ hasPermission('floor') && !hasPermission('settings') &&
|
||||
<Button onClick={ () => processAction('open_floorplan_editor') }>
|
||||
{ LocalizeText('open.floor.plan.editor') }
|
||||
</Button> }
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,106 +1,196 @@
|
||||
import { RoomDataParser } from '@nitrots/nitro-renderer';
|
||||
import { FC, useRef, useState } from 'react';
|
||||
import { RoomDataParser, RoomSettingsComposer, UpdateHomeRoomMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import React, { FC, useRef, useState } from 'react';
|
||||
import { FaUser } from 'react-icons/fa';
|
||||
|
||||
import { ArrowContainer, Popover } from 'react-tiny-popover';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { Flex, LayoutBadgeImageView, LayoutRoomThumbnailView, NitroCardContentView, Text, UserProfileIconView } from '../../../../common';
|
||||
import { GetGroupInformation, GetSessionDataManager, GetUserProfile, LocalizeText, ReportType, SendMessageComposer, ToggleFavoriteRoom } from '../../../../api';
|
||||
import { Column, Flex, LayoutBadgeImageView, LayoutRoomThumbnailView, NitroCardContentView, Text, UserProfileIconView } from '../../../../common';
|
||||
import { useHelp, useNavigator } from '../../../../hooks';
|
||||
import { classNames } from '../../../../layout';
|
||||
|
||||
export const NavigatorSearchResultItemInfoView: FC<{
|
||||
roomData: RoomDataParser;
|
||||
}> = props =>
|
||||
interface NavigatorSearchResultItemInfoViewProps
|
||||
{
|
||||
const { roomData = null } = props;
|
||||
const [ isVisible, setIsVisible ] = useState(false);
|
||||
const elementRef = useRef<HTMLDivElement>();
|
||||
roomData: RoomDataParser;
|
||||
isVisible?: boolean;
|
||||
onToggle?: (e: React.MouseEvent) => void;
|
||||
setIsPopoverActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfoViewProps> = props =>
|
||||
{
|
||||
const { roomData = null, isVisible = undefined, onToggle, setIsPopoverActive } = props;
|
||||
const elementRef = useRef<HTMLDivElement>(null);
|
||||
const [ internalVisible, setInternalVisible ] = useState(false);
|
||||
const { navigatorData = null, favouriteRoomIds = [] } = useNavigator();
|
||||
const { report = null } = useHelp();
|
||||
|
||||
const isControlled = isVisible !== undefined;
|
||||
const popoverOpen = isControlled ? isVisible : internalVisible;
|
||||
|
||||
const getUserCounterColor = () =>
|
||||
{
|
||||
const num: number = (100 * (roomData.userCount / roomData.maxUserCount));
|
||||
|
||||
let bg = 'bg-primary';
|
||||
if(num >= 92) return 'bg-danger';
|
||||
if(num >= 50) return 'bg-warning';
|
||||
if(num > 0) return 'bg-success';
|
||||
|
||||
if(num >= 92)
|
||||
{
|
||||
bg = 'bg-danger';
|
||||
}
|
||||
else if(num >= 50)
|
||||
{
|
||||
bg = 'bg-warning';
|
||||
}
|
||||
else if(num > 0)
|
||||
{
|
||||
bg = 'bg-success';
|
||||
}
|
||||
|
||||
return bg;
|
||||
return 'bg-primary';
|
||||
};
|
||||
|
||||
function dispatch(arg0: string): void
|
||||
const processAction = (action: string) =>
|
||||
{
|
||||
throw new Error('Function not implemented.');
|
||||
}
|
||||
if(!navigatorData || !roomData) return;
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case 'set_home_room':
|
||||
{
|
||||
let newRoomId = -1;
|
||||
if(navigatorData.homeRoomId !== roomData.roomId) newRoomId = roomData.roomId;
|
||||
if(newRoomId > 0) SendMessageComposer(new UpdateHomeRoomMessageComposer(newRoomId));
|
||||
return;
|
||||
}
|
||||
case 'open_room_settings':
|
||||
SendMessageComposer(new RoomSettingsComposer(roomData.roomId));
|
||||
return;
|
||||
case 'report_room':
|
||||
report(ReportType.ROOM, { roomId: roomData.roomId, roomName: roomData.roomName });
|
||||
return;
|
||||
case 'room_favourite':
|
||||
ToggleFavoriteRoom(roomData.roomId, favouriteRoomIds.includes(roomData.roomId));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const handleOwnerClick = (e: React.MouseEvent) =>
|
||||
{
|
||||
e.stopPropagation();
|
||||
GetUserProfile(roomData.ownerId);
|
||||
};
|
||||
|
||||
const handleGroupClick = (e: React.MouseEvent) =>
|
||||
{
|
||||
e.stopPropagation();
|
||||
GetGroupInformation(roomData.habboGroupId);
|
||||
};
|
||||
|
||||
const getTradeModeText = (): string =>
|
||||
{
|
||||
if(roomData.tradeMode === 1) return LocalizeText('trading.mode.free');
|
||||
return LocalizeText('trading.mode.not.allowed');
|
||||
};
|
||||
|
||||
const handleIconClick = (e: React.MouseEvent) =>
|
||||
{
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if(onToggle) onToggle(e);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
|
||||
<Popover
|
||||
ref={ elementRef } // if you'd like a ref to your popover's child, you can grab one here
|
||||
containerClassName="max-w-[276px] not-italic font-normal leading-normal text-left no-underline text-shadow-none normal-case tracking-[normal] [word-break:normal] [word-spacing:normal] whitespace-normal text-[.7875rem] [word-wrap:break-word] bg-[#dfdfdf] bg-clip-padding border border-[solid] border-[#283F5D] rounded-[.25rem] [box-shadow:0_2px_#00000073] z-1070"
|
||||
content={ ({ position, childRect, popoverRect }) => (
|
||||
<ArrowContainer // if you'd like an arrow, you can import the ArrowContainer!
|
||||
arrowColor={ 'black' }
|
||||
arrowSize={ 7 }
|
||||
arrowStyle={ { left: 'calc(-.5rem - 0px)' } }
|
||||
childRect={ childRect }
|
||||
popoverRect={ popoverRect }
|
||||
position={ position }
|
||||
|
||||
>
|
||||
<NitroCardContentView className="bg-transparent room-info image-rendering-pixelated" overflow="hidden">
|
||||
<Flex gap={ 2 } overflow="hidden">
|
||||
<LayoutRoomThumbnailView className="flex flex-col items-center mb-1 justify-content-end" customUrl={ roomData.officialRoomPicRef } roomId={ roomData.roomId }>
|
||||
{ roomData.habboGroupId > 0 && (
|
||||
<LayoutBadgeImageView badgeCode={ roomData.groupBadgeCode } className={ 'absolute top-0 inset-s-0 m-1 ' } isGroup={ true } />) }
|
||||
{ roomData.doorMode !== RoomDataParser.OPEN_STATE && (
|
||||
<i className={ 'absolute inset-e-0 mb-1 me-1 icon icon-navigator-room-' + (roomData.doorMode === RoomDataParser.DOORBELL_STATE ? 'locked' : roomData.doorMode === RoomDataParser.PASSWORD_STATE ? 'password' : roomData.doorMode === RoomDataParser.INVISIBLE_STATE ? 'invisible' : '') } />) }
|
||||
</LayoutRoomThumbnailView>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Text bold truncate className="grow" style={ { maxHeight: 13 } }>
|
||||
{ roomData.roomName }
|
||||
</Text>
|
||||
<div className="flex gap-2">
|
||||
<Text italics variant="muted">
|
||||
{ LocalizeText('navigator.roomownercaption') }
|
||||
</Text>
|
||||
<div className="flex items-center gap-1">
|
||||
<UserProfileIconView userId={ roomData.ownerId } />
|
||||
<Text italics>{ roomData.ownerName }</Text>
|
||||
</div>
|
||||
</div>
|
||||
<Text className="grow">
|
||||
{ roomData.description }
|
||||
</Text>
|
||||
<Flex className={ 'badge p-1 absolute m-1 bottom-0 inset-e-0 m-2 ' + getUserCounterColor() } gap={ 1 }>
|
||||
<FaUser className="fa-icon" />
|
||||
{ roomData.userCount }
|
||||
</Flex>
|
||||
</div>
|
||||
<Popover
|
||||
containerClassName="max-w-[276px] not-italic font-normal leading-normal text-left no-underline text-shadow-none normal-case tracking-[normal] [word-break:normal] [word-spacing:normal] whitespace-normal text-[.7875rem] [word-wrap:break-word] bg-[#dfdfdf] bg-clip-padding border border-[solid] border-[#283F5D] rounded-[.25rem] [box-shadow:0_2px_#00000073] z-[1070]"
|
||||
content={ ({ position, childRect, popoverRect }) => (
|
||||
<ArrowContainer
|
||||
arrowColor="black"
|
||||
arrowSize={ 7 }
|
||||
arrowStyle={ { left: 'calc(-.5rem - 0px)' } }
|
||||
childRect={ childRect }
|
||||
popoverRect={ popoverRect }
|
||||
position={ position }
|
||||
>
|
||||
<NitroCardContentView className="bg-transparent room-info image-rendering-pixelated" overflow="hidden" onClick={ e => e.stopPropagation() }>
|
||||
<Flex gap={ 1 } overflow="hidden" className="p-2">
|
||||
<LayoutRoomThumbnailView className="flex flex-col items-center justify-end mb-1" customUrl={ roomData.officialRoomPicRef } roomId={ roomData.roomId }>
|
||||
{ roomData.habboGroupId > 0 && (
|
||||
<LayoutBadgeImageView badgeCode={ roomData.groupBadgeCode } className="absolute top-0 inset-s-0 m-1" isGroup={ true } />) }
|
||||
{ roomData.doorMode !== RoomDataParser.OPEN_STATE && (
|
||||
<i className={ 'absolute inset-e-0 mb-1 me-1 icon icon-navigator-room-' + (roomData.doorMode === RoomDataParser.DOORBELL_STATE ? 'locked' : roomData.doorMode === RoomDataParser.PASSWORD_STATE ? 'password' : roomData.doorMode === RoomDataParser.INVISIBLE_STATE ? 'invisible' : '') } />) }
|
||||
</LayoutRoomThumbnailView>
|
||||
<Column gap={ 1 }>
|
||||
<Text bold className="grow" style={ { maxHeight: 13 } }>
|
||||
{ roomData.roomName.length > 35 ? roomData.roomName.substring(0, 35) + '…' : roomData.roomName }
|
||||
</Text>
|
||||
<Text className="grow text-xs">{ roomData.description }</Text>
|
||||
</Column>
|
||||
</Flex>
|
||||
<Column gap={ 0 } className="px-2 pb-2">
|
||||
<Flex alignItems="center" className="mb-2">
|
||||
{ roomData.ownerName && roomData.ownerName.length > 0 &&
|
||||
<Flex onClick={ handleOwnerClick } gap={ 1 } className="w-1/2 items-center cursor-pointer">
|
||||
<UserProfileIconView userId={ roomData.ownerId } />
|
||||
<Text pointer bold underline>{ roomData.ownerName }</Text>
|
||||
</Flex> }
|
||||
{ roomData.habboGroupId > 0 &&
|
||||
<Flex onClick={ handleGroupClick } gap={ 1 } className="w-1/2 items-center cursor-pointer">
|
||||
<i className="icon icon-navigator-room-group" />
|
||||
<Text bold underline className="truncate" style={ { maxWidth: 100 } }>{ roomData.groupName }</Text>
|
||||
</Flex> }
|
||||
</Flex>
|
||||
</NitroCardContentView>
|
||||
</ArrowContainer>
|
||||
) }
|
||||
isOpen={ isVisible }
|
||||
padding={ 10 }
|
||||
positions={ [ 'right' ] }
|
||||
>
|
||||
|
||||
<div ref={ elementRef } className="cursor-pointer nitro-icon icon-navigator-info" onMouseLeave={ event => setIsVisible(false) } onMouseOver={ event => setIsVisible(true) } />
|
||||
|
||||
</Popover>
|
||||
|
||||
</>
|
||||
<Flex gap={ 4 } className="w-full">
|
||||
<Column className="w-3/5" gap={ 1 }>
|
||||
<Flex gap={ 2 } alignItems="center">
|
||||
<Text bold className="text-xs">{ LocalizeText('navigator.roompopup.property.trading') }</Text>
|
||||
<Text className="text-xs">{ getTradeModeText() }</Text>
|
||||
</Flex>
|
||||
<Flex gap={ 2 } alignItems="center">
|
||||
<Text bold className="text-xs">{ LocalizeText('navigator.roompopup.property.max_users') }</Text>
|
||||
<Text className="text-xs">{ roomData.maxUserCount }</Text>
|
||||
</Flex>
|
||||
<Flex gap={ 1 } alignItems="center">
|
||||
<Flex center className={ 'rounded px-1 py-0.5 text-xs font-bold text-white ' + getUserCounterColor() } gap={ 1 }>
|
||||
<FaUser className="fa-icon" />
|
||||
{ roomData.userCount }
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Column>
|
||||
<Column alignItems="start" gap={ 2 } className="w-2/5">
|
||||
<Flex pointer alignItems="center" gap={ 2 } onClick={ () => processAction('room_favourite') }>
|
||||
<i className={ classNames('icon icon-navigator-favorite-room', favouriteRoomIds.includes(roomData.roomId) ? 'active' : '') } />
|
||||
<Text className="text-xs">{ LocalizeText('navigator.room.popup.room.info.favorite') }</Text>
|
||||
</Flex>
|
||||
<Flex pointer alignItems="center" gap={ 2 } onClick={ () => processAction('set_home_room') }>
|
||||
<i className={ classNames('icon icon-navigator-my-room', (navigatorData?.homeRoomId !== roomData.roomId) ? '' : 'active') } />
|
||||
<Text className="text-xs">{ LocalizeText('navigator.room.popup.room.info.home') }</Text>
|
||||
</Flex>
|
||||
{ GetSessionDataManager().userId === roomData.ownerId &&
|
||||
<Flex pointer alignItems="center" gap={ 2 } onClick={ () => processAction('open_room_settings') }>
|
||||
<i className="icon icon-navigator-room-settings" />
|
||||
<Text className="text-xs">{ LocalizeText('navigator.room.popup.info.room.settings') }</Text>
|
||||
</Flex> }
|
||||
{ GetSessionDataManager().userId !== roomData.ownerId &&
|
||||
<Flex pointer alignItems="center" gap={ 2 } onClick={ () => processAction('report_room') }>
|
||||
<i className="icon icon-navigator-room-report" />
|
||||
<Text className="text-xs">{ LocalizeText('navigator.room.popup.report.room') }</Text>
|
||||
</Flex> }
|
||||
</Column>
|
||||
</Flex>
|
||||
{ roomData.tags && roomData.tags.length > 0 &&
|
||||
<Flex gap={ 1 } className="mt-1">
|
||||
{ roomData.tags.map((tag, i) => (
|
||||
<Text key={ i } variant="white" className="bg-orange-500 px-1 rounded text-xs">#{ tag }</Text>
|
||||
)) }
|
||||
</Flex> }
|
||||
</Column>
|
||||
</NitroCardContentView>
|
||||
</ArrowContainer>
|
||||
) }
|
||||
isOpen={ popoverOpen }
|
||||
onClickOutside={ () =>
|
||||
{
|
||||
if(!isControlled) setInternalVisible(false);
|
||||
if(setIsPopoverActive) setIsPopoverActive(false);
|
||||
} }
|
||||
padding={ 10 }
|
||||
positions={ [ 'right', 'left', 'top', 'bottom' ] }
|
||||
>
|
||||
<div
|
||||
ref={ elementRef }
|
||||
className="cursor-pointer nitro-icon icon-navigator-info"
|
||||
onClick={ handleIconClick }
|
||||
onMouseOver={ () => { if(!isControlled) setInternalVisible(true); } }
|
||||
onMouseLeave={ () => { if(!isControlled) setInternalVisible(false); } }
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { GetSessionDataManager, RoomDataParser } from '@nitrots/nitro-renderer';
|
||||
import { FC, MouseEvent } from 'react';
|
||||
import React, { FC, MouseEvent, useEffect } from 'react';
|
||||
import { FaUser } from 'react-icons/fa';
|
||||
import { CreateRoomSession, DoorStateType, TryVisitRoom } from '../../../../api';
|
||||
import { Column, Flex, LayoutBadgeImageView, LayoutGridItemProps, LayoutRoomThumbnailView, Text } from '../../../../common';
|
||||
@@ -8,35 +8,84 @@ import { NavigatorSearchResultItemInfoView } from './NavigatorSearchResultItemIn
|
||||
|
||||
export interface NavigatorSearchResultItemViewProps extends LayoutGridItemProps
|
||||
{
|
||||
roomData: RoomDataParser
|
||||
thumbnail?: boolean
|
||||
roomData: RoomDataParser;
|
||||
thumbnail?: boolean;
|
||||
selectedRoomId?: number | null;
|
||||
setSelectedRoomId?: React.Dispatch<React.SetStateAction<number | null>>;
|
||||
isPopoverActive?: boolean;
|
||||
setIsPopoverActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProps> = props =>
|
||||
{
|
||||
const { roomData = null, children = null, thumbnail = false, ...rest } = props;
|
||||
const { roomData = null, children = null, thumbnail = false, selectedRoomId, setSelectedRoomId, isPopoverActive, setIsPopoverActive, ...rest } = props;
|
||||
const { setDoorData = null } = useNavigator();
|
||||
|
||||
const handleMouseEnter = () =>
|
||||
{
|
||||
if(isPopoverActive && setSelectedRoomId) setSelectedRoomId(roomData.roomId);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () =>
|
||||
{
|
||||
if(setSelectedRoomId && setIsPopoverActive)
|
||||
{
|
||||
setSelectedRoomId(null);
|
||||
setIsPopoverActive(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleInfoClick = (e: React.MouseEvent) =>
|
||||
{
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if(setIsPopoverActive && setSelectedRoomId)
|
||||
{
|
||||
if(!isPopoverActive)
|
||||
{
|
||||
setSelectedRoomId(roomData.roomId);
|
||||
setIsPopoverActive(true);
|
||||
}
|
||||
else if(selectedRoomId === roomData.roomId)
|
||||
{
|
||||
setSelectedRoomId(null);
|
||||
setIsPopoverActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectedRoomId(roomData.roomId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const handleClickOutside = (event: Event) =>
|
||||
{
|
||||
const target = event.target as HTMLElement;
|
||||
const navigatorItem = target.closest('.navigator-item');
|
||||
|
||||
if(!navigatorItem && setIsPopoverActive && setSelectedRoomId)
|
||||
{
|
||||
setIsPopoverActive(false);
|
||||
setSelectedRoomId(null);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
return () => document.removeEventListener('click', handleClickOutside);
|
||||
}, [ setIsPopoverActive, setSelectedRoomId ]);
|
||||
|
||||
const getUserCounterColor = () =>
|
||||
{
|
||||
const num: number = (100 * (roomData.userCount / roomData.maxUserCount));
|
||||
|
||||
let bg = 'bg-primary';
|
||||
if(num >= 92) return 'bg-danger';
|
||||
if(num >= 50) return 'bg-warning';
|
||||
if(num > 0) return 'bg-success';
|
||||
|
||||
if(num >= 92)
|
||||
{
|
||||
bg = 'bg-danger';
|
||||
}
|
||||
else if(num >= 50)
|
||||
{
|
||||
bg = 'bg-warning';
|
||||
}
|
||||
else if(num > 0)
|
||||
{
|
||||
bg = 'bg-success';
|
||||
}
|
||||
|
||||
return bg;
|
||||
return 'bg-primary';
|
||||
};
|
||||
|
||||
const visitRoom = (event: MouseEvent) =>
|
||||
@@ -46,7 +95,6 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
|
||||
if(roomData.habboGroupId !== 0)
|
||||
{
|
||||
TryVisitRoom(roomData.roomId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,10 +104,8 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
|
||||
setDoorData(prevValue =>
|
||||
{
|
||||
const newValue = { ...prevValue };
|
||||
|
||||
newValue.roomInfo = roomData;
|
||||
newValue.state = DoorStateType.START_DOORBELL;
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return;
|
||||
@@ -67,10 +113,8 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
|
||||
setDoorData(prevValue =>
|
||||
{
|
||||
const newValue = { ...prevValue };
|
||||
|
||||
newValue.roomInfo = roomData;
|
||||
newValue.state = DoorStateType.START_PASSWORD;
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return;
|
||||
@@ -81,10 +125,20 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
|
||||
};
|
||||
|
||||
if(thumbnail) return (
|
||||
<Column pointer alignItems="center" className="navigator-item p-1 bg-light rounded-3 small mb-1 flex-col border border-muted" gap={ 0 } overflow="hidden" onClick={ visitRoom } { ...rest }>
|
||||
<Column
|
||||
pointer
|
||||
overflow="hidden"
|
||||
alignItems="center"
|
||||
className="navigator-item p-1 bg-light rounded-3 small mb-1 flex-col border border-muted"
|
||||
gap={ 0 }
|
||||
onClick={ visitRoom }
|
||||
onMouseEnter={ handleMouseEnter }
|
||||
onMouseLeave={ handleMouseLeave }
|
||||
{ ...rest }
|
||||
>
|
||||
<LayoutRoomThumbnailView className="flex flex-col items-center justify-end mb-1" customUrl={ roomData.officialRoomPicRef } roomId={ roomData.roomId }>
|
||||
{ roomData.habboGroupId > 0 && <LayoutBadgeImageView badgeCode={ roomData.groupBadgeCode } className={ 'absolute top-0 inset-s-0 m-1' } isGroup={ true } /> }
|
||||
<Flex center className={ 'inline-block px-[.65em] py-[.35em] text-[.75em] font-bold leading-none text-[#fff] text-center whitespace-nowrap align-baseline rounded-[.25rem] p-1 absolute m-1 ' + getUserCounterColor() } gap={ 1 }>
|
||||
{ roomData.habboGroupId > 0 && <LayoutBadgeImageView badgeCode={ roomData.groupBadgeCode } className="absolute top-0 inset-s-0 m-1" isGroup={ true } /> }
|
||||
<Flex center className={ 'inline-block px-[.65em] py-[.35em] text-[.75em] font-bold leading-none text-white text-center whitespace-nowrap align-baseline rounded-[.25rem] p-1 absolute m-1 ' + getUserCounterColor() } gap={ 1 }>
|
||||
<FaUser className="fa-icon" />
|
||||
{ roomData.userCount }
|
||||
</Flex>
|
||||
@@ -94,23 +148,42 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
|
||||
<Flex className="w-full">
|
||||
<Text truncate className="grow!">{ roomData.roomName }</Text>
|
||||
<Flex reverse alignItems="center" gap={ 1 }>
|
||||
<NavigatorSearchResultItemInfoView roomData={ roomData } />
|
||||
<NavigatorSearchResultItemInfoView
|
||||
isVisible={ selectedRoomId === roomData.roomId }
|
||||
onToggle={ handleInfoClick }
|
||||
setIsPopoverActive={ setIsPopoverActive }
|
||||
roomData={ roomData }
|
||||
/>
|
||||
</Flex>
|
||||
{ children }
|
||||
</Flex>
|
||||
|
||||
</Column>
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex pointer alignItems="center" className="navigator-item px-2 py-1 small" gap={ 2 } overflow="hidden" onClick={ visitRoom } { ...rest }>
|
||||
<Flex center className={ 'inline-block px-[.65em] py-[.35em] text-[.75em] font-bold leading-none text-[#fff] text-center whitespace-nowrap align-baseline rounded-[.25rem] p-1 ' + getUserCounterColor() } gap={ 1 }>
|
||||
<Flex
|
||||
pointer
|
||||
alignItems="center"
|
||||
className="navigator-item px-2 py-1 small"
|
||||
gap={ 2 }
|
||||
overflow="hidden"
|
||||
onClick={ visitRoom }
|
||||
onMouseEnter={ handleMouseEnter }
|
||||
onMouseLeave={ handleMouseLeave }
|
||||
{ ...rest }
|
||||
>
|
||||
<Flex center className={ 'inline-block px-[.65em] py-[.35em] text-[.75em] font-bold leading-none text-white text-center whitespace-nowrap align-baseline rounded-[.25rem] p-1 ' + getUserCounterColor() } gap={ 1 }>
|
||||
<FaUser className="fa-icon" />
|
||||
{ roomData.userCount }
|
||||
</Flex>
|
||||
<Text grow truncate>{ roomData.roomName }</Text>
|
||||
<Flex reverse alignItems="center" gap={ 1 }>
|
||||
<NavigatorSearchResultItemInfoView roomData={ roomData } />
|
||||
<Text grow truncate className="min-w-0">{ roomData.roomName }</Text>
|
||||
<Flex reverse alignItems="center" gap={ 1 } className="shrink-0">
|
||||
<NavigatorSearchResultItemInfoView
|
||||
isVisible={ selectedRoomId === roomData.roomId && isPopoverActive }
|
||||
onToggle={ handleInfoClick }
|
||||
setIsPopoverActive={ setIsPopoverActive }
|
||||
roomData={ roomData }
|
||||
/>
|
||||
{ roomData.habboGroupId > 0 && <i className="nitro-icon icon-navigator-room-group" /> }
|
||||
{ (roomData.doorMode !== RoomDataParser.OPEN_STATE) &&
|
||||
<i className={ ('nitro-icon icon-navigator-room-' + ((roomData.doorMode === RoomDataParser.DOORBELL_STATE) ? 'locked' : (roomData.doorMode === RoomDataParser.PASSWORD_STATE) ? 'password' : (roomData.doorMode === RoomDataParser.INVISIBLE_STATE) ? 'invisible' : '')) } /> }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { NavigatorSearchComposer, NavigatorSearchResultList } from '@nitrots/nitro-renderer';
|
||||
import { NavigatorSearchComposer, NavigatorSearchResultList, NavigatorSearchSaveComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { FaBars, FaMinus, FaPlus, FaTh, FaWindowMaximize, FaWindowRestore } from 'react-icons/fa';
|
||||
import { LocalizeText, NavigatorSearchResultViewDisplayMode, SendMessageComposer } from '../../../../api';
|
||||
import { AutoGrid, AutoGridProps, Column, Flex, Grid, Text } from '../../../../common';
|
||||
import { AutoGrid, AutoGridProps, Column, Flex, Grid, LayoutSearchSavesView, Text } from '../../../../common';
|
||||
import { useNavigator } from '../../../../hooks';
|
||||
import { NavigatorSearchResultItemView } from './NavigatorSearchResultItemView';
|
||||
|
||||
@@ -16,6 +16,8 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
|
||||
const { searchResult = null, ...rest } = props;
|
||||
const [ isExtended, setIsExtended ] = useState(true);
|
||||
const [ displayMode, setDisplayMode ] = useState<number>(0);
|
||||
const [ selectedRoomId, setSelectedRoomId ] = useState<number | null>(null);
|
||||
const [ isPopoverActive, setIsPopoverActive ] = useState<boolean>(false);
|
||||
|
||||
const { topLevelContext = null } = useNavigator();
|
||||
|
||||
@@ -23,7 +25,7 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
|
||||
{
|
||||
let name = searchResult.code;
|
||||
|
||||
if(!name || !name.length || LocalizeText('navigator.searchcode.title.' + name) == ('navigator.searchcode.title.' + name)) return searchResult.data;
|
||||
if(!name || !name.length || LocalizeText('navigator.searchcode.title.' + name) === ('navigator.searchcode.title.' + name)) return searchResult.data;
|
||||
|
||||
if(name.startsWith('${')) return name.slice(2, (name.length - 1));
|
||||
|
||||
@@ -51,7 +53,6 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
|
||||
if(!searchResult) return;
|
||||
|
||||
setIsExtended(!searchResult.closed);
|
||||
|
||||
setDisplayMode(searchResult.mode);
|
||||
}, [ searchResult ]);
|
||||
|
||||
@@ -65,54 +66,46 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
|
||||
{ !isExtended && <FaPlus className="text-secondary fa-icon" /> }
|
||||
<Text>{ LocalizeText(getResultTitle()) }</Text>
|
||||
</Flex>
|
||||
<div className="flex gap-2">
|
||||
{ (displayMode === NavigatorSearchResultViewDisplayMode.LIST) && <FaTh className="text-secondary fa-icon" onClick={ toggleDisplayMode } /> }
|
||||
{ (displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS) && <FaBars className="text-secondary fa-icon" onClick={ toggleDisplayMode } /> }
|
||||
{ (searchResult.action > 0) && (searchResult.action === 1) && <FaWindowMaximize className="text-secondary fa-icon" onClick={ showMore } /> }
|
||||
{ (searchResult.action > 0) && (searchResult.action !== 1) && <FaWindowRestore className="text-secondary fa-icon" onClick={ showMore } /> }
|
||||
<div className="flex gap-2 items-center">
|
||||
{ (displayMode === NavigatorSearchResultViewDisplayMode.LIST) && <FaTh className="text-secondary fa-icon cursor-pointer" onClick={ toggleDisplayMode } /> }
|
||||
{ (displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS) && <FaBars className="text-secondary fa-icon cursor-pointer" onClick={ toggleDisplayMode } /> }
|
||||
{ (searchResult.action > 0) && (searchResult.action === 1) && <FaWindowMaximize className="text-secondary fa-icon cursor-pointer" title={ LocalizeText('navigator.more.rooms') } onClick={ showMore } /> }
|
||||
{ (searchResult.action > 0) && (searchResult.action !== 1) && <FaWindowRestore className="text-secondary fa-icon cursor-pointer" title={ LocalizeText('navigator.back') } onClick={ showMore } /> }
|
||||
<LayoutSearchSavesView
|
||||
title={ LocalizeText('navigator.tooltip.add.saved.search') }
|
||||
onClick={ () => SendMessageComposer(new NavigatorSearchSaveComposer(getResultTitle(), searchResult.data)) }
|
||||
/>
|
||||
</div>
|
||||
|
||||
</Flex> { isExtended &&
|
||||
</Flex>
|
||||
{ isExtended &&
|
||||
<>
|
||||
{
|
||||
gridHasTwoColumns ? <AutoGrid columnCount={ 3 } { ...rest } className="mx-2" columnMinHeight={ 130 } columnMinWidth={ 110 }>
|
||||
{ searchResult.rooms.length > 0 && searchResult.rooms.map((room, index) => <NavigatorSearchResultItemView key={ index } roomData={ room } thumbnail={ true } />) }
|
||||
</AutoGrid> : <Grid className="navigator-grid" columnCount={ 1 } gap={ 0 }>
|
||||
{ searchResult.rooms.length > 0 && searchResult.rooms.map((room, index) => <NavigatorSearchResultItemView key={ index } roomData={ room } />) }
|
||||
</Grid>
|
||||
}
|
||||
</>
|
||||
}
|
||||
{ gridHasTwoColumns
|
||||
? <AutoGrid columnCount={ 3 } { ...rest } className="mx-2" columnMinHeight={ 130 } columnMinWidth={ 110 }>
|
||||
{ searchResult.rooms.length > 0 && searchResult.rooms.map((room, index) => (
|
||||
<NavigatorSearchResultItemView
|
||||
key={ index }
|
||||
roomData={ room }
|
||||
thumbnail={ true }
|
||||
isPopoverActive={ isPopoverActive }
|
||||
setIsPopoverActive={ setIsPopoverActive }
|
||||
selectedRoomId={ selectedRoomId }
|
||||
setSelectedRoomId={ setSelectedRoomId }
|
||||
/>
|
||||
)) }
|
||||
</AutoGrid>
|
||||
: <Grid className="navigator-grid" columnCount={ 1 } gap={ 0 }>
|
||||
{ searchResult.rooms.length > 0 && searchResult.rooms.map((room, index) => (
|
||||
<NavigatorSearchResultItemView
|
||||
key={ index }
|
||||
roomData={ room }
|
||||
isPopoverActive={ isPopoverActive }
|
||||
setIsPopoverActive={ setIsPopoverActive }
|
||||
selectedRoomId={ selectedRoomId }
|
||||
setSelectedRoomId={ setSelectedRoomId }
|
||||
/>
|
||||
)) }
|
||||
</Grid> }
|
||||
</> }
|
||||
</Column>
|
||||
// <div className="nitro-navigator-search-result bg-white rounded mb-2 overflow-hidden">
|
||||
// <div className="flex flex-col">
|
||||
// <div className="flex items-center px-2 py-1 text-black">
|
||||
// <i className={ 'text-secondary fas ' + (isExtended ? 'fa-minus' : 'fa-plus') } onClick={ toggleExtended }></i>
|
||||
// <div className="ms-2 grow!">{ LocalizeText(getResultTitle()) }</div>
|
||||
// <i className={ 'text-secondary fas ' + classNames({ 'fa-bars': (displayMode === NavigatorSearchResultViewDisplayMode.LIST), 'fa-th': displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS })}></i>
|
||||
// </div>
|
||||
// { isExtended &&
|
||||
// <div className={ 'nitro-navigator-result-list row row-cols-' + classNames({ '1': (displayMode === NavigatorSearchResultViewDisplayMode.LIST), '2': (displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS) }) }>
|
||||
// { searchResult.rooms.length > 0 && searchResult.rooms.map((room, index) =>
|
||||
// {
|
||||
// return <NavigatorSearchResultItemView key={ index } roomData={ room } />
|
||||
// }) }
|
||||
// </div> }
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className="nitro-navigator-result-list p-2">
|
||||
// <div className="flex mb-2 small cursor-pointer" onClick={ toggleList }>
|
||||
// <i className={ "fas " + classNames({ 'fa-plus': !isExtended, 'fa-minus': isExtended })}></i>
|
||||
// <div className="align-self-center w-full ml-2">{ LocalizeText(getListCode()) }</div>
|
||||
// <i className={ "fas " + classNames({ 'fa-bars': displayMode === NavigatorResultListViewDisplayMode.LIST, 'fa-th': displayMode >= NavigatorResultListViewDisplayMode.THUMBNAILS })} onClick={ toggleDisplayMode }></i>
|
||||
// </div>
|
||||
// <div className={ 'row mr-n2 row-cols-' + classNames({ '1': displayMode === NavigatorResultListViewDisplayMode.LIST, '2': displayMode >= NavigatorResultListViewDisplayMode.THUMBNAILS }) }>
|
||||
// { isExtended && resultList && resultList.rooms.map((room, index) =>
|
||||
// {
|
||||
// return <NavigatorResultView key={ index } result={ room } />
|
||||
// })
|
||||
// }
|
||||
// </div>
|
||||
// </div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { NavigatorDeleteSavedSearchComposer, NavigatorSavedSearch, NavigatorSearchComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useState } from 'react';
|
||||
import { LocalizeText, SendMessageComposer } from '../../../../api';
|
||||
import { Flex, Text } from '../../../../common';
|
||||
|
||||
export interface NavigatorSearchSavesResultItemViewProps
|
||||
{
|
||||
search: NavigatorSavedSearch;
|
||||
}
|
||||
|
||||
export const NavigatorSearchSavesResultItemView: FC<NavigatorSearchSavesResultItemViewProps> = props =>
|
||||
{
|
||||
const { search = null } = props;
|
||||
const [ isHovered, setIsHovered ] = useState(false);
|
||||
|
||||
const getResultTitle = () =>
|
||||
{
|
||||
let name = search.code;
|
||||
|
||||
if(!name || !name.length || LocalizeText('navigator.searchcode.title.' + name) === ('navigator.searchcode.title.' + name)) return search.code;
|
||||
|
||||
if(name.startsWith('${')) return name.slice(2, (name.length - 1));
|
||||
|
||||
return ('navigator.searchcode.title.' + name);
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex grow pointer alignItems="center" gap={ 1 } onMouseEnter={ () => setIsHovered(true) } onMouseLeave={ () => setIsHovered(false) }>
|
||||
{ isHovered &&
|
||||
<i
|
||||
className="nitro-icon icon-navigator-search-delete cursor-pointer flex-shrink-0"
|
||||
title={ LocalizeText('navigator.tooltip.remove.saved.search') }
|
||||
onClick={ () => SendMessageComposer(new NavigatorDeleteSavedSearchComposer(search.id)) }
|
||||
/> }
|
||||
<Text
|
||||
small
|
||||
pointer
|
||||
variant="black"
|
||||
title={ LocalizeText('navigator.tooltip.open.saved.search') }
|
||||
onClick={ () => SendMessageComposer(new NavigatorSearchComposer(search.code.split('.').reverse()[0], search.filter)) }
|
||||
>
|
||||
{ LocalizeText(getResultTitle()) }
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
import { NavigatorSavedSearch } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { FaBolt } from 'react-icons/fa';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { Column, Flex, Text } from '../../../../common';
|
||||
import { NavigatorSearchSavesResultItemView } from './NavigatorSearchSavesResultItemView';
|
||||
|
||||
export interface NavigatorSearchSavesResultViewProps
|
||||
{
|
||||
searches: NavigatorSavedSearch[];
|
||||
}
|
||||
|
||||
export const NavigatorSearchSavesResultView: FC<NavigatorSearchSavesResultViewProps> = props =>
|
||||
{
|
||||
const { searches = [] } = props;
|
||||
|
||||
return (
|
||||
<Column className="nitro-navigator-search-saves-result min-w-[100px]">
|
||||
<Flex className="rounded px-2 py-1 bg-orange-500" gap={ 1 } alignItems="center">
|
||||
<FaBolt color="white" />
|
||||
<Text variant="white">{ LocalizeText('navigator.quick.links.title') }</Text>
|
||||
</Flex>
|
||||
<Column className="p-1 overflow-x-hidden overflow-y-auto">
|
||||
{ (searches && searches.length > 0) &&
|
||||
searches.map((search: NavigatorSavedSearch) => (
|
||||
<NavigatorSearchSavesResultItemView key={ search.id } search={ search } />
|
||||
)) }
|
||||
</Column>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
@@ -668,4 +668,18 @@
|
||||
.nitro-icon.icon-loading.with-size {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.nitro-icon.icon-navigator-search-delete {
|
||||
background-image: url("@/assets/images/navigator/saves-search/delete_search.png");
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.nitro-icon.icon-navigator-search-delete:hover {
|
||||
background-image: url("@/assets/images/navigator/saves-search/delete_search_hover.png");
|
||||
}
|
||||
|
||||
.nitro-icon.icon-navigator-search-delete:active {
|
||||
background-image: url("@/assets/images/navigator/saves-search/delete_search_click.png");
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CanCreateRoomEventEvent, CantConnectMessageParser, CreateLinkEvent, DoorbellMessageEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetSessionDataManager, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, HabboWebTools, LegacyExternalInterface, NavigatorCategoryDataParser, NavigatorEventCategoryDataParser, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchEvent, NavigatorSearchResultSet, NavigatorTopLevelContext, RoomDataParser, RoomDoorbellAcceptedEvent, RoomEnterErrorEvent, RoomEntryInfoMessageEvent, RoomForwardEvent, RoomScoreEvent, RoomSettingsUpdatedEvent, SecurityLevel, UserEventCatsEvent, UserFlatCatsEvent, UserInfoEvent, UserPermissionsEvent } from '@nitrots/nitro-renderer';
|
||||
import { CanCreateRoomEventEvent, CantConnectMessageParser, CreateLinkEvent, DoorbellMessageEvent, FavouriteChangedEvent, FavouritesEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetSessionDataManager, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, HabboWebTools, LegacyExternalInterface, NavigatorCategoryDataParser, NavigatorEventCategoryDataParser, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSavedSearch, NavigatorSearchesEvent, NavigatorSearchEvent, NavigatorSearchResultSet, NavigatorTopLevelContext, RoomDataParser, RoomDoorbellAcceptedEvent, RoomEnterErrorEvent, RoomEntryInfoMessageEvent, RoomForwardEvent, RoomScoreEvent, RoomSettingsUpdatedEvent, SecurityLevel, UserEventCatsEvent, UserFlatCatsEvent, UserInfoEvent, UserPermissionsEvent } from '@nitrots/nitro-renderer';
|
||||
import { useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { CreateRoomSession, DoorStateType, GetConfigurationValue, INavigatorData, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api';
|
||||
@@ -9,10 +9,12 @@ const useNavigatorState = () =>
|
||||
{
|
||||
const [ categories, setCategories ] = useState<NavigatorCategoryDataParser[]>(null);
|
||||
const [ eventCategories, setEventCategories ] = useState<NavigatorEventCategoryDataParser[]>(null);
|
||||
const [ favouriteRoomIds, setFavouriteRoomIds ] = useState<number[]>([]);
|
||||
const [ topLevelContext, setTopLevelContext ] = useState<NavigatorTopLevelContext>(null);
|
||||
const [ topLevelContexts, setTopLevelContexts ] = useState<NavigatorTopLevelContext[]>(null);
|
||||
const [ doorData, setDoorData ] = useState<{ roomInfo: RoomDataParser, state: number }>({ roomInfo: null, state: DoorStateType.NONE });
|
||||
const [ searchResult, setSearchResult ] = useState<NavigatorSearchResultSet>(null);
|
||||
const [ navigatorSearches, setNavigatorSearches ] = useState<NavigatorSavedSearch[]>(null);
|
||||
const [ navigatorData, setNavigatorData ] = useState<INavigatorData>({
|
||||
settingsReceived: false,
|
||||
homeRoomId: 0,
|
||||
@@ -29,6 +31,29 @@ const useNavigatorState = () =>
|
||||
});
|
||||
const { simpleAlert = null } = useNotification();
|
||||
|
||||
useMessageEvent<FavouritesEvent>(FavouritesEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const favoriteIds = (parser.favoriteRoomIds || []).map((x: any) => Number(x));
|
||||
setFavouriteRoomIds(favoriteIds);
|
||||
});
|
||||
|
||||
useMessageEvent<FavouriteChangedEvent>(FavouriteChangedEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const roomId = Number(parser.flatId);
|
||||
const added = !!parser.added;
|
||||
|
||||
setFavouriteRoomIds(prev =>
|
||||
{
|
||||
const ids = (prev || []).map((x: any) => Number(x));
|
||||
|
||||
if(added) return ids.includes(roomId) ? ids : [ ...ids, roomId ];
|
||||
|
||||
return ids.filter(id => id !== roomId);
|
||||
});
|
||||
});
|
||||
|
||||
useMessageEvent<RoomSettingsUpdatedEvent>(RoomSettingsUpdatedEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
@@ -436,7 +461,14 @@ const useNavigatorState = () =>
|
||||
|
||||
useMessageEvent<NavigatorOpenRoomCreatorEvent>(NavigatorOpenRoomCreatorEvent, event => CreateLinkEvent('navigator/show'));
|
||||
|
||||
return { categories, doorData, setDoorData, topLevelContext, topLevelContexts, searchResult, navigatorData };
|
||||
useMessageEvent<NavigatorSearchesEvent>(NavigatorSearchesEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
if(!parser) return;
|
||||
setNavigatorSearches(parser.searches);
|
||||
});
|
||||
|
||||
return { categories, doorData, setDoorData, topLevelContext, topLevelContexts, searchResult, navigatorData, favouriteRoomIds, navigatorSearches };
|
||||
};
|
||||
|
||||
export const useNavigator = () => useBetween(useNavigatorState);
|
||||
|
||||