#55 - Navigator saved searches

This commit is contained in:
oobjectt 2022-12-30 22:38:12 +01:00
parent 9693bcae0b
commit 00fab2b19e
8 changed files with 168 additions and 33 deletions

View File

@ -0,0 +1,21 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { FC } from 'react';
import { Base } from '../Base';
export interface LayoutSearchSavesViewProps
{
title: string;
onSaveSearch?: () => void;
onClick?: () => void;
}
export const LayoutSearchSavesView: FC<LayoutSearchSavesViewProps> = props =>
{
const { title = null, onSaveSearch = null, onClick = null } = props;
return (
<Base color="white" className="button-search-saves" pointer title={ title } onClickCapture={ onSaveSearch } onClick={ onClick }>
<FontAwesomeIcon icon="bolt-lightning" />
</Base>
);
}

View File

@ -18,6 +18,7 @@ export * from './LayoutProgressBar';
export * from './LayoutRarityLevelView'; export * from './LayoutRarityLevelView';
export * from './LayoutRoomPreviewerView'; export * from './LayoutRoomPreviewerView';
export * from './LayoutRoomThumbnailView'; export * from './LayoutRoomThumbnailView';
export * from './LayoutSearchSavesView';
export * from './LayoutTrophyView'; export * from './LayoutTrophyView';
export * from './limited-edition'; export * from './limited-edition';
export * from './UserProfileIconView'; export * from './UserProfileIconView';

View File

@ -60,6 +60,26 @@
} }
} }
.nitro-navigator-search-saves-result {
background-color: #fff;
width: 100px;
height: 350px;
border-radius: 10px;
.bg-orange {
background-color: #FAA700;
}
}
.room-info { .room-info {
width: 275px; width: 275px;
} }
.button-search-saves {
padding: 4px;
height: 17px;
margin-top: -1px;
font-size: 10px;
border-radius: 4px;
background-color: #FAA700;
}

View File

@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ConvertGlobalRoomIdMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RoomSessionEvent } from '@nitrots/nitro-renderer'; import { ConvertGlobalRoomIdMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RoomSessionEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker, SendMessageComposer, TryVisitRoom } from '../../api'; import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker, SendMessageComposer, TryVisitRoom } from '../../api';
import { Base, Column, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common'; import { Base, Column, Flex, LayoutSearchSavesView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
import { useNavigator, useRoomSessionManagerEvent } from '../../hooks'; import { useNavigator, useRoomSessionManagerEvent } from '../../hooks';
import { NavigatorDoorStateView } from './views/NavigatorDoorStateView'; import { NavigatorDoorStateView } from './views/NavigatorDoorStateView';
import { NavigatorRoomCreatorView } from './views/NavigatorRoomCreatorView'; import { NavigatorRoomCreatorView } from './views/NavigatorRoomCreatorView';
@ -10,6 +10,7 @@ import { NavigatorRoomInfoView } from './views/NavigatorRoomInfoView';
import { NavigatorRoomLinkView } from './views/NavigatorRoomLinkView'; import { NavigatorRoomLinkView } from './views/NavigatorRoomLinkView';
import { NavigatorRoomSettingsView } from './views/room-settings/NavigatorRoomSettingsView'; import { NavigatorRoomSettingsView } from './views/room-settings/NavigatorRoomSettingsView';
import { NavigatorSearchResultView } from './views/search/NavigatorSearchResultView'; import { NavigatorSearchResultView } from './views/search/NavigatorSearchResultView';
import { NavigatorSearchSavesResultView } from './views/search/NavigatorSearchSavesResultView';
import { NavigatorSearchView } from './views/search/NavigatorSearchView'; import { NavigatorSearchView } from './views/search/NavigatorSearchView';
export const NavigatorView: FC<{}> = props => export const NavigatorView: FC<{}> = props =>
@ -19,10 +20,11 @@ export const NavigatorView: FC<{}> = props =>
const [ isCreatorOpen, setCreatorOpen ] = useState(false); const [ isCreatorOpen, setCreatorOpen ] = useState(false);
const [ isRoomInfoOpen, setRoomInfoOpen ] = useState(false); const [ isRoomInfoOpen, setRoomInfoOpen ] = useState(false);
const [ isRoomLinkOpen, setRoomLinkOpen ] = useState(false); const [ isRoomLinkOpen, setRoomLinkOpen ] = useState(false);
const [ isOpenSavesSearchs, setIsOpenSavesSearchs ] = useState(false);
const [ isLoading, setIsLoading ] = useState(false); const [ isLoading, setIsLoading ] = useState(false);
const [ needsInit, setNeedsInit ] = useState(true); const [ needsInit, setNeedsInit ] = useState(true);
const [ needsSearch, setNeedsSearch ] = useState(false); 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 pendingSearch = useRef<{ value: string, code: string }>(null);
const elementRef = useRef<HTMLDivElement>(); const elementRef = useRef<HTMLDivElement>();
@ -199,6 +201,9 @@ export const NavigatorView: FC<{}> = props =>
<NitroCardView uniqueKey="navigator" className="nitro-navigator"> <NitroCardView uniqueKey="navigator" className="nitro-navigator">
<NitroCardHeaderView headerText={ LocalizeText(isCreatorOpen ? 'navigator.createroom.title' : 'navigator.title') } onCloseClick={ event => setIsVisible(false) } /> <NitroCardHeaderView headerText={ LocalizeText(isCreatorOpen ? 'navigator.createroom.title' : 'navigator.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardTabsView> <NitroCardTabsView>
<Base className="mt-1">
<LayoutSearchSavesView title={ LocalizeText('navigator.tooltip.left.show.hide') } onClick={ () => setIsOpenSavesSearchs(prevValue => !prevValue) } />
</Base>
{ topLevelContexts && (topLevelContexts.length > 0) && topLevelContexts.map((context, index) => { topLevelContexts && (topLevelContexts.length > 0) && topLevelContexts.map((context, index) =>
{ {
return ( return (
@ -216,10 +221,18 @@ export const NavigatorView: FC<{}> = props =>
<Base fit position="absolute" className="top-0 start-0 z-index-1 bg-muted opacity-0-5" /> } <Base fit position="absolute" className="top-0 start-0 z-index-1 bg-muted opacity-0-5" /> }
{ !isCreatorOpen && { !isCreatorOpen &&
<> <>
<NavigatorSearchView sendSearch={ sendSearch } /> <Flex gap={ 1 }>
<Column innerRef={ elementRef } overflow="auto"> { (isOpenSavesSearchs) &&
{ (searchResult && searchResult.results.map((result, index) => <NavigatorSearchResultView key={ index } searchResult={ result } />)) } <Column>
</Column> <NavigatorSearchSavesResultView searchs={ navigatorSearches } />
</Column> }
<Column fullWidth>
<NavigatorSearchView sendSearch={ sendSearch } />
<Column innerRef={ elementRef } overflow="auto">
{ (searchResult && searchResult.results.map((result, index) => <NavigatorSearchResultView key={ index } searchResult={ result } />)) }
</Column>
</Column>
</Flex>
</> } </> }
{ isCreatorOpen && <NavigatorRoomCreatorView /> } { isCreatorOpen && <NavigatorRoomCreatorView /> }
</NitroCardContentView> </NitroCardContentView>

View File

@ -1,8 +1,8 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { NavigatorSearchComposer, NavigatorSearchResultList } from '@nitrots/nitro-renderer'; import { NavigatorSearchComposer, NavigatorSearchResultList, NavigatorSearchSaveComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { LocalizeText, NavigatorSearchResultViewDisplayMode, SendMessageComposer } from '../../../../api'; 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 { useNavigator } from '../../../../hooks';
import { NavigatorSearchResultItemView } from './NavigatorSearchResultItemView'; import { NavigatorSearchResultItemView } from './NavigatorSearchResultItemView';
@ -16,8 +16,7 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
const { searchResult = null, ...rest } = props; const { searchResult = null, ...rest } = props;
const [ isExtended, setIsExtended ] = useState(true); const [ isExtended, setIsExtended ] = useState(true);
const [ displayMode, setDisplayMode ] = useState<number>(0); const [ displayMode, setDisplayMode ] = useState<number>(0);
const { topLevelContext = null, searchResultQuery = null } = useNavigator();
const { topLevelContext = null } = useNavigator();
const getResultTitle = () => const getResultTitle = () =>
{ {
@ -67,6 +66,8 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
<Flex gap={ 2 }> <Flex gap={ 2 }>
<FontAwesomeIcon icon={ ((displayMode === NavigatorSearchResultViewDisplayMode.LIST) ? 'th' : (displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS) ? 'bars' : null) } className="text-secondary" onClick={ toggleDisplayMode } /> <FontAwesomeIcon icon={ ((displayMode === NavigatorSearchResultViewDisplayMode.LIST) ? 'th' : (displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS) ? 'bars' : null) } className="text-secondary" onClick={ toggleDisplayMode } />
{ (searchResult.action > 0) && <FontAwesomeIcon icon={ searchResult.action == 1 ? 'window-maximize' : 'window-restore' } className="text-secondary" onClick={ showMore } /> } { (searchResult.action > 0) && <FontAwesomeIcon icon={ searchResult.action == 1 ? 'window-maximize' : 'window-restore' } className="text-secondary" onClick={ showMore } /> }
{ (topLevelContext.code !== 'official_view') &&
<LayoutSearchSavesView title={ LocalizeText('navigator.tooltip.add.saved.search') } onSaveSearch={ () => SendMessageComposer(new NavigatorSearchSaveComposer(getResultTitle(), searchResultQuery)) } /> }
</Flex> </Flex>
</Flex> { isExtended && </Flex> { isExtended &&

View File

@ -0,0 +1,37 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
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 [ isHoverText, setIsHoverText ] = useState<boolean>(false);
const [ currentIndex, setCurrentIndex ] = useState<number>(0);
const onHover = (searchId: number) =>
{
setCurrentIndex(searchId);
setIsHoverText(true);
}
const onLeave = () =>
{
setCurrentIndex(0);
setIsHoverText(false);
}
return (
<Flex grow pointer alignItems="center" gap={ 1 } onMouseEnter={ () => onHover(search.id) } onMouseLeave={ () => onLeave() }>
{ (isHoverText && currentIndex === search.id) &&
<FontAwesomeIcon color="red" icon="subtract" title={ LocalizeText('navigator.tooltip.remove.saved.search') } onClick={ () => SendMessageComposer(new NavigatorDeleteSavedSearchComposer(search.id)) } /> }
<Text pointer variant="black" title={ LocalizeText('navigator.tooltip.open.saved.search') } onClick={ () => SendMessageComposer(new NavigatorSearchComposer(search.code.split('.').reverse()[0], search.filter)) }>{ search.filter !== '' ? LocalizeText('navigator.searchcode.title.query') + ': ' + (!search.filter.split(':')[1] ? search.filter : search.filter.split(':')[1]) : LocalizeText(`${ search.code }`) }</Text>
</Flex>
);
}

View File

@ -0,0 +1,30 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { NavigatorSavedSearch } from '@nitrots/nitro-renderer';
import { FC } from 'react';
import { LocalizeText } from '../../../../api';
import { Column, Flex, Text } from '../../../../common';
import { NavigatorSearchSavesResultItemView } from './NavigatorSearchSavesResultItemView';
export interface NavigatorSearchSavesResultViewProps
{
searchs: NavigatorSavedSearch[]
}
export const NavigatorSearchSavesResultView: FC<NavigatorSearchSavesResultViewProps> = props =>
{
const { searchs = [] } = props;
return (
<Column className="nitro-navigator-search-saves-result">
<Flex className="badge p-1 bg-orange" gap={ 1 }>
<FontAwesomeIcon color="white" icon="bolt-lightning" />
<Text variant="white">{ LocalizeText('navigator.quick.links.title') }</Text>
</Flex>
<Column className="p-1" style={ { overflowX: 'hidden', overflowY: 'auto' } }>
{ (searchs && searchs.length > 0) &&
searchs.map((search: NavigatorSavedSearch) => <NavigatorSearchSavesResultItemView key={ search.id } search={ search } />)
}
</Column>
</Column>
);
}

View File

@ -1,4 +1,4 @@
import { CanCreateRoomEventEvent, CantConnectMessageParser, DoorbellMessageEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, 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, DoorbellMessageEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, 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 { useState } from 'react';
import { useBetween } from 'use-between'; import { useBetween } from 'use-between';
import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, INavigatorData, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api'; import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, INavigatorData, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api';
@ -13,6 +13,8 @@ const useNavigatorState = () =>
const [ topLevelContexts, setTopLevelContexts ] = useState<NavigatorTopLevelContext[]>(null); const [ topLevelContexts, setTopLevelContexts ] = useState<NavigatorTopLevelContext[]>(null);
const [ doorData, setDoorData ] = useState<{ roomInfo: RoomDataParser, state: number }>({ roomInfo: null, state: DoorStateType.NONE }); const [ doorData, setDoorData ] = useState<{ roomInfo: RoomDataParser, state: number }>({ roomInfo: null, state: DoorStateType.NONE });
const [ searchResult, setSearchResult ] = useState<NavigatorSearchResultSet>(null); const [ searchResult, setSearchResult ] = useState<NavigatorSearchResultSet>(null);
const [ searchResultQuery, setSearchResultQuery ] = useState<string>('');
const [ navigatorSearches, setNavigatorSearches ] = useState<NavigatorSavedSearch[]>(null);
const [ navigatorData, setNavigatorData ] = useState<INavigatorData>({ const [ navigatorData, setNavigatorData ] = useState<INavigatorData>({
settingsReceived: false, settingsReceived: false,
homeRoomId: 0, homeRoomId: 0,
@ -325,6 +327,7 @@ const useNavigatorState = () =>
}); });
setSearchResult(parser.result); setSearchResult(parser.result);
setSearchResultQuery(parser.result.data);
}); });
useMessageEvent<UserFlatCatsEvent>(UserFlatCatsEvent, event => useMessageEvent<UserFlatCatsEvent>(UserFlatCatsEvent, event =>
@ -436,7 +439,16 @@ const useNavigatorState = () =>
useMessageEvent<NavigatorOpenRoomCreatorEvent>(NavigatorOpenRoomCreatorEvent, event => CreateLinkEvent('navigator/show')); 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, navigatorSearches, searchResultQuery };
} }
export const useNavigator = () => useBetween(useNavigatorState); export const useNavigator = () => useBetween(useNavigatorState);