Redesign: Navigator & Containers

This commit is contained in:
duckietm 2024-05-01 15:04:20 +02:00
parent 1e6da73450
commit 6426a7ad1e
55 changed files with 1312 additions and 781 deletions

View File

@ -30,12 +30,17 @@ $catalog-height: 480px;
$inventory-width: 528px;
$inventory-height: 370px;
$navigator-width: 420px;
$navigator-height: 440px;
$navigator-width: 425px;
$navigator-height: 560px;
$navigator-min-height: 205px;
$nitro-room-creator-width: 585px;
$nitro-room-creator-height: 365px;
$chat-input-style-selector-widget-width: 210px;
$chat-input-style-selector-widget-height: 200px;
$user-profile-width: 470px;
$user-profile-height: 460px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -29,7 +29,7 @@ input[type=number] {
}
.btn-primary{
color: #fff;
background-color: #1e7295;
background-color: #7fb1c5;
border: 2px solid #1a617f;
padding: 0.25rem 0.5rem;
font-size: .7875rem;
@ -43,7 +43,7 @@ input[type=number] {
}
.btn-secondary{
color: #fff;
background-color: #1e7295;
background-color: #7fb1c5;
border: 2px solid #1a617f;
padding: 0.25rem 0.5rem;
font-size: .7875rem;

View File

@ -7,13 +7,16 @@ interface NitroCardHeaderViewProps extends ColumnProps
headerText: string;
isGalleryPhoto?: boolean;
noCloseButton?: boolean;
isInfoToHabboPages?: boolean;
hideButtonClose?: boolean;
onReportPhoto?: (event: MouseEvent) => void;
onClickInfoHabboPages?: (event: MouseEvent) => void;
onCloseClick: (event: MouseEvent) => void;
}
export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
{
const { headerText = null, isGalleryPhoto = false, noCloseButton = false, onReportPhoto = null, onCloseClick = null, justifyContent = 'center', alignItems = 'center', classNames = [], children = null, ...rest } = props;
const { headerText = null, isGalleryPhoto = false, noCloseButton = false, isInfoToHabboPages = false, hideButtonClose = false, onReportPhoto = null, onClickInfoHabboPages = null, onCloseClick = null, justifyContent = 'center', alignItems = 'center', classNames = [], children = null, ...rest } = props;
const getClassNames = useMemo(() =>
{
@ -32,15 +35,18 @@ export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
return (
<Column center position="relative" classNames={ getClassNames } { ...rest }>
<Flex fullWidth center>
<Flex fullWidth center className="nitro-card-header-holder">
<span className="nitro-card-header-text">{ headerText }</span>
{ isGalleryPhoto &&
<Base position="absolute" className="end-4 nitro-card-header-report-camera" onClick={ onReportPhoto }>
<FaFlag className="fa-icon" />
</Base>
}
{ isInfoToHabboPages &&
<Base position="absolute" className="end-6 nitro-card-header-info-habbopages" onClick={ onClickInfoHabboPages }></Base>
}
<Flex center position="absolute" className="end-2 nitro-card-header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
<FaTimes className="fa-icon w-12 h-12" />
{ (!hideButtonClose) && <FaTimes className="fa-icon w-12 h-12" /> }
</Flex>
</Flex>
</Column>

View File

@ -3,7 +3,6 @@ $nitro-card-tabs-height: 42px;
.nitro-card {
resize: both;
padding: 0.5rem;
background: #ededed;
border-radius: 0.75rem!important;
border: 2px solid #454566!important;
@ -18,14 +17,15 @@ $nitro-card-tabs-height: 42px;
border: $border-width solid $border-color;
.nitro-card-header {
min-height: 28px;
max-height: 28px;
width: 100%;
padding: 1rem;
border-radius: 0.5rem;
border-image-slice: 7 fill;
border-image-width: 7px;
border-image-repeat: repeat repeat;
color: #fff;
background: #454566;
border: 2px solid #66669b;
margin-bottom: 0.25rem;
height: 34px;
min-height: 34px;
line-height: 34px;
justify-content: center;
.nitro-card-header-text {
color: $white;
@ -35,24 +35,17 @@ $nitro-card-tabs-height: 42px;
.nitro-card-header-close {
cursor: pointer;
padding: 2px 2px;
line-height: 1;
border-radius: $border-radius;
box-shadow: 0 0 0 1.6px $white;
border: 2px solid #921911;
background: repeating-linear-gradient(
rgba(245, 80, 65, 1),
rgba(245, 80, 65, 1) 50%,
rgba(194, 48, 39, 1) 50%,
rgba(194, 48, 39, 1) 100%
);
background-image: url("@/assets/images/boxes/card/close.png");
width: 19px;
height: 20px;
&:hover {
filter: brightness(1.2);
}
background-image: url("@/assets/images/boxes/card/close_hover.png");
&:active {
filter: brightness(0.8);
background-image: url("@/assets/images/boxes/card/close_click.png");
}
}
}
@ -84,26 +77,23 @@ $nitro-card-tabs-height: 42px;
background-color: #ededed;
.nav-item {
padding: 0.2rem 0.4rem;
background-color: #dedede;
color: #000;
padding: $nav-link-padding-y $nav-link-padding-x;
background-color: $muted;
color: $black;
z-index: 1;
box-shadow: 0 0 0 1pt #fff !important;
border: 2px solid #454566!important;
border-radius: 0.5rem;
border-top-left-radius: 0.5rem !important;
border-top-right-radius: 0.5rem !important;
margin-bottom: -1px;
&.active {
background-color: #e1e5ff;
background-color: $light;
border-color: $border-color $border-color $light !important;
border-bottom: 1px solid black;
&:before {
background: $white;
}
}
&:before {
content: '';
content: "";
position: absolute;
width: 93%;
height: 3px;
@ -130,12 +120,11 @@ $nitro-card-tabs-height: 42px;
position: relative;
min-height: 28px;
max-height: 28px;
width: 100%;
padding: 1rem;
border-radius: 0.5rem;
background: #454566;
border: 2px solid #66669b;
margin-bottom: 0.25rem;
box-shadow: 0 2px #366b8c;
width: 100%;
margin: 0;
font-size: 20px;
.nitro-card-header-text {
color: $white;
@ -146,25 +135,17 @@ $nitro-card-tabs-height: 42px;
.nitro-card-header-close {
cursor: pointer;
padding: 0px 2px;
line-height: 1;
@include font-size($h7-font-size);
border-radius: $border-radius;
box-shadow: 0 0 0 1.6px $white;
border: 2px solid #921911;
background: repeating-linear-gradient(
rgba(245, 80, 65, 1),
rgba(245, 80, 65, 1) 50%,
rgba(194, 48, 39, 1) 50%,
rgba(194, 48, 39, 1) 100%
);
background-image: url("@/assets/images/boxes/card/close.png");
width: 19px;
height: 20px;
&:hover {
filter: brightness(1.2);
}
background-image: url("@/assets/images/boxes/card/close_hover.png");
&:active {
filter: brightness(0.8);
background-image: url("@/assets/images/boxes/card/close_click.png");
}
}
}

View File

@ -202,6 +202,71 @@
background-color: rgba($black, 0.125);
}
.room-creator-grid-item {
height: var(--nitro-grid-column-min-height, unset);
background-position: center;
background-repeat: no-repeat;
border-image-source: url(@/assets/images/navigator/room-creator/room-bg.png);
border-image-slice:6 6 6 6 fill;
border-image-width:6px 6px 6px 6px;
overflow: hidden;
&.active {
border-image-source: url(@/assets/images/navigator/room-creator/room-bg-active.png) !important;
color: #fff !important;
.active-arrow {
background-image: url(@/assets/images/navigator/room-creator/arrow.png);
width: 18px;
height: 20px;
position: absolute;
top: 1px;
animation: MoveUpDown 1.7s linear infinite;
@keyframes MoveUpDown {
0%, 100% {
top: 1px;
}
50% {
top: 10px;
}
}
}
}
&.disabled {
cursor: not-allowed;
img {
opacity: 0.5;
filter: grayscale(1);
}
}
&.unseen {
background-color: rgba($success, 0.4);
}
.avatar-image {
background-position-y: -35px;
}
&.has-highlight {
&:after {
content: "";
z-index: 2;
position: absolute;
top: 2px;
left: 2px;
height: 1px;
width: 9px;
background-color: #fff;
opacity: 0.1;
}
}
}
#draggable-windows-container {
position: absolute;
top: 0;

View File

@ -0,0 +1,18 @@
import { FC } from 'react';
import { Flex, Text } from '..';
interface LayoutInputErrorViewProps
{
text: string;
}
export const LayoutInputErrorView: FC<LayoutInputErrorViewProps> = props =>
{
const { text = null } = props;
return (
<Flex className="nitro-input-error-popup" alignItems="center" justifyContent="center">
<Text className="px-2">{ text }</Text>
</Flex>
);
};

View File

@ -0,0 +1,29 @@
import { FC } from "react";
import { FaBolt } from "react-icons/fa";
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}
>
<FaBolt />
</Base>
);
};

View File

@ -0,0 +1,115 @@
import { FC, useMemo } from "react";
import { Base } from "../Base";
import { Column, ColumnProps } from "../Column";
import { LayoutItemCountView } from "./LayoutItemCountView";
import { LayoutLimitedEditionStyledNumberView } from "./limited-edition";
export interface RoomCreatorGridItemProps extends ColumnProps {
itemImage?: string;
itemColor?: string;
itemActive?: boolean;
itemCount?: number;
itemCountMinimum?: number;
itemUniqueSoldout?: boolean;
itemUniqueNumber?: number;
itemUnseen?: boolean;
itemHighlight?: boolean;
disabled?: boolean;
}
export const RoomCreatorGridItem: FC<RoomCreatorGridItemProps> = (props) => {
const {
itemImage = undefined,
itemColor = undefined,
itemActive = false,
itemCount = 1,
itemCountMinimum = 1,
itemUniqueSoldout = false,
itemUniqueNumber = -2,
itemUnseen = false,
itemHighlight = false,
disabled = false,
center = true,
column = true,
style = {},
classNames = [],
position = "relative",
overflow = "hidden",
children = null,
...rest
} = props;
const getClassNames = useMemo(() => {
const newClassNames: string[] = ["room-creator-grid-item"];
if (itemActive) newClassNames.push("active");
if (itemUniqueSoldout || itemUniqueNumber > 0)
newClassNames.push("unique-item");
if (itemUniqueSoldout) newClassNames.push("sold-out");
if (itemUnseen) newClassNames.push("unseen");
if (itemHighlight) newClassNames.push("has-highlight");
if (disabled) newClassNames.push("disabled");
if (itemImage === null) newClassNames.push("icon", "loading-icon");
if (classNames.length) newClassNames.push(...classNames);
return newClassNames;
}, [
itemActive,
itemUniqueSoldout,
itemUniqueNumber,
itemUnseen,
itemHighlight,
disabled,
itemImage,
classNames,
]);
const getStyle = useMemo(() => {
let newStyle = { ...style };
if (itemImage) newStyle.backgroundImage = `url(${itemImage})`;
if (itemColor) newStyle.backgroundColor = itemColor;
if (Object.keys(style).length) newStyle = { ...newStyle, ...style };
return newStyle;
}, [style, itemImage, itemColor]);
return (
<Column
center={center}
pointer
position={position}
overflow={overflow}
column={column}
classNames={getClassNames}
style={getStyle}
{...rest}
>
{itemCount > itemCountMinimum && (
<LayoutItemCountView count={itemCount} />
)}
{itemUniqueNumber > 0 && (
<>
<Base
fit
className="unique-bg-override"
style={{ backgroundImage: `url(${itemImage})` }}
/>
<div className="position-absolute bottom-0 unique-item-counter">
<LayoutLimitedEditionStyledNumberView value={itemUniqueNumber} />
</div>
</>
)}
{children}
</Column>
);
};

View File

@ -8,6 +8,7 @@ export * from './LayoutFurniImageView';
export * from './LayoutGiftTagView';
export * from './LayoutGridItem';
export * from './LayoutImage';
export * from "./LayoutInputErrorView";
export * from './LayoutItemCountView';
export * from './LayoutLoadingSpinnerView';
export * from './LayoutMiniCameraView';
@ -20,5 +21,7 @@ export * from './LayoutRarityLevelView';
export * from './LayoutRoomPreviewerView';
export * from './LayoutRoomThumbnailView';
export * from './LayoutTrophyView';
export * from "./LayoutSearchSavesView";
export * from './limited-edition';
export * from './RoomCreatorGridItem';
export * from './UserProfileIconView';

View File

@ -1,24 +1,34 @@
.nitro-navigator {
width: $navigator-width;
height: $navigator-height;
min-width: $navigator-width;
max-width: $navigator-width;
min-height: $navigator-min-height;
&.expanded {
max-width: $navigator-width + 153px;
min-width: $navigator-width + 153px;
}
.nav-form {
width: 275px;
}
.navigator-grid {
.navigator-item {
.badge {
width: 35px;
min-width: 35px;
}
}
&:not(.two-columns) {
.navigator-item {
&:nth-child(odd) {
background-color: $grid-active-bg-color;
background-color: #daecfd;
}
&:nth-child(even) {
background-color: #fff;
}
}
}
@ -37,11 +47,25 @@
.nitro-navigator-doorbell,
.nitro-navigator-password {
width: 250px;
width: 300px;
}
.nitro-room-info {
width: $room-info-width;
resize: none;
}
.text-tag {
font-size: 10px;
background-color: #CEE9FA;
}
.text-tag:hover {
background-color: #449FCF;
}
.text-embed {
font-size: 10px;
}
.nitro-room-link {
@ -60,6 +84,212 @@
}
}
.badge-empty {
background-image: url('@/assets/images/navigator/badge_empty.png');
background-repeat: no-repeat;
width: 40px;
height: 19px;
color: #fff;
}
.badge-success {
background-image: url('@/assets/images/navigator/badge_success.png');
background-repeat: no-repeat;
width: 40px;
height: 19px;
color: #fff;
}
.badge-danger {
background-image: url('@/assets/images/navigator/badge_danger.png');
background-repeat: no-repeat;
width: 40px;
height: 19px;
color: #fff;
}
.badge-warning {
background-image: url('@/assets/images/navigator/badge_warning.png');
background-repeat: no-repeat;
width: 40px;
height: 19px;
color: #fff;
}
.nav-category {
font-size: 12px;
color: #2b577b;
font-size: var(--bs-body-font-size);
}
.nav-icons {
color: #7dd8f6;
}
.minus-icon {
background-image: url('@/assets/images/navigator/minus.png');
background-repeat: no-repeat;
width: 18px;
height: 18px;
}
.plus-icon {
background-image: url('@/assets/images/navigator/plus.png');
background-repeat: no-repeat;
width: 18px;
height: 18px;
}
.nav-avatar-icon {
background-image: url('@/assets/images/navigator/avatar_icon.png');
background-repeat: no-repeat;
height: 8px;
width: 7px;
}
.nav-thumbnail {
border-image-source: url('@/assets/images/navigator/thumbnail_bg.png');
border-image-slice: 7 7 7 7 fill;
border-image-width: 7px 7px 7px 7px;
}
.nav-create-room {
background-image: url('@/assets/images/navigator/create_room.png');
background-repeat: no-repeat;
height: 60px;
width: 189px;
float: left;
cursor: pointer;
}
.nav-random-room {
background-image: url('@/assets/images/navigator/random_room.png');
background-repeat: no-repeat;
height: 60px;
width: 189px;
float: right;
margin-left: 15px;
cursor: pointer;
}
.nav-promote-room {
background-image: url('@/assets/images/navigator/promote_room.png');
background-repeat: no-repeat;
height: 60px;
width: 189px;
float: right;
margin-left: 15px;
cursor: pointer;
}
.nav-bottom {
max-height: 80px;
min-height: 80px;
}
.nav-bottom-buttons {
bottom: 18px;
left: 10px;
}
.nav-bottom-buttons-text {
font-size: 12px;
padding-top: 22px;
margin-left: 86px;
}
.nitro-room-creator {
width: $nitro-room-creator-width;
height: $nitro-room-creator-height;
textarea:focus, input:focus {
outline: none;
}
.room-creator-form-name {
height: 20px;
border: 1px solid grey;
}
.room-creator-form-desc {
height: 60px;
border: 1px solid grey;
}
.headline {
}
.content-area {
font-size: 12px;
}
.room-creator-info {
width: 240px;
}
.form-select {
width: 100%;
}
.room-creator-grid {
width: 305px;
}
}
.room-info {
width: 275px;
color: #000;
image-rendering: pixelated;
.room-info-bg {
border-image-source: url('@/assets/images/navigator/white_bg.png');
border-image-slice: 6 6 6 6 fill;
border-image-width: 6px 6px 6px 6px;
}
}
.navigator-search-button {
right: 10px;
top: 11px;
}
.button-search-saves {
padding: 4px;
height: 17px;
margin-top: -1px;
font-size: 10px;
border-radius: 4px;
background-color: #FAA700;
}
.nitro-navigator-search-saves-result {
background-color: #fff;
width: 141px;
min-height: 494px;
max-height: 350px;
border-radius: 10px;
.bg-orange {
background-color: #FAA700;
}
}
.nitro-navigator-search-delete {
cursor: pointer;
background-image: url("@/assets/images/navigator/saves-search/delete_search.png");
width: 18px;
height: 18px;
&:hover {
background-image: url("@/assets/images/navigator/saves-search/delete_search_hover.png");
&:active {
background-image: url("@/assets/images/navigator/saves-search/delete_search_click.png");
}
}
}

View File

@ -1,8 +1,7 @@
import { ConvertGlobalRoomIdMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RoomSessionEvent } from '@nitrots/nitro-renderer';
import { ConvertGlobalRoomIdMessageComposer, FindNewFriendsMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RoomSessionEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { FaPlus } from 'react-icons/fa';
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker, SendMessageComposer, TryVisitRoom } from '../../api';
import { Base, Column, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
import { AddEventLinkTracker, CreateLinkEvent, LocalizeText, RemoveLinkEventTracker, SendMessageComposer, TryVisitRoom } from '../../api';
import { Base, Column, Flex, LayoutSearchSavesView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView, Text } from '../../common';
import { useNavigator, useRoomSessionManagerEvent } from '../../hooks';
import { NavigatorDoorStateView } from './views/NavigatorDoorStateView';
import { NavigatorRoomCreatorView } from './views/NavigatorRoomCreatorView';
@ -10,6 +9,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 +19,11 @@ export const NavigatorView: FC<{}> = props =>
const [ isCreatorOpen, setCreatorOpen ] = useState(false);
const [ isRoomInfoOpen, setRoomInfoOpen ] = useState(false);
const [ isRoomLinkOpen, setRoomLinkOpen ] = useState(false);
const [ isOpenSavesSearchs, setIsOpenSavesSearchs ] = 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>();
@ -34,8 +35,6 @@ export const NavigatorView: FC<{}> = props =>
const sendSearch = useCallback((searchValue: string, contextCode: string) =>
{
setCreatorOpen(false);
SendMessageComposer(new NavigatorSearchComposer(contextCode, searchValue));
setIsLoading(true);
@ -126,9 +125,12 @@ export const NavigatorView: FC<{}> = props =>
}
return;
case 'create':
setIsVisible(true);
setCreatorOpen(true);
setCreatorOpen(value => !value);
return;
case 'close-creator':
setCreatorOpen(false);
return;
case 'search':
if(parts.length > 2)
{
@ -196,34 +198,64 @@ export const NavigatorView: FC<{}> = props =>
return (
<>
{ isVisible &&
<NitroCardView uniqueKey="navigator" className="nitro-navigator">
<NitroCardHeaderView headerText={ LocalizeText(isCreatorOpen ? 'navigator.createroom.title' : 'navigator.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardView uniqueKey="navigator" className={ `nitro-navigator ${ isOpenSavesSearchs ? 'expanded' : '' }` }>
<NitroCardHeaderView headerText={ LocalizeText('navigator.title') } isInfoToHabboPages={ true } onClickInfoHabboPages={ () => CreateLinkEvent('habbopages/navigator') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardTabsView>
<Base className="mt-1">
<LayoutSearchSavesView style={ { marginRight: !isOpenSavesSearchs ? '11px' : '91px', marginLeft: '-2px', marginTop: '1px' } } title={ LocalizeText('navigator.tooltip.left.show.hide') } onClick={ () => setIsOpenSavesSearchs(prevValue => !prevValue) } />
</Base>
{ topLevelContexts && (topLevelContexts.length > 0) && topLevelContexts.map((context, index) =>
{
return (
<NitroCardTabsItemView key={ index } isActive={ ((topLevelContext === context) && !isCreatorOpen) } onClick={ event => sendSearch('', context.code) }>
<NitroCardTabsItemView key={ index } isActive={ ((topLevelContext === context)) } onClick={ event => sendSearch('', context.code) }>
{ LocalizeText(('navigator.toplevelview.' + context.code)) }
</NitroCardTabsItemView>
);
}) }
<NitroCardTabsItemView isActive={ isCreatorOpen } onClick={ event => setCreatorOpen(true) }>
<FaPlus className="fa-icon" />
</NitroCardTabsItemView>
</NitroCardTabsView>
<NitroCardContentView position="relative">
{ isLoading &&
<Base fit position="absolute" className="top-0 start-0 z-index-1 bg-muted opacity-0-5" /> }
{ !isCreatorOpen &&
<>
{ isLoading && <Base fit position="absolute" className="top-0 start-0 z-index-1 bg-muted opacity-0-5" /> }
<Column overflow="hidden">
<Flex fullWidth fullHeight>
{ isOpenSavesSearchs &&
<Column overflow="hidden" className="pe-5">
<NavigatorSearchSavesResultView searchs={ navigatorSearches } />
</Column>
}
<Flex column={ true } className="w-100">
<NavigatorSearchView sendSearch={ sendSearch } />
<Column innerRef={ elementRef } overflow="auto">
<Column overflow="auto">
{ (searchResult && searchResult.results.map((result, index) => <NavigatorSearchResultView key={ index } searchResult={ result } />)) }
</Column>
</> }
{ isCreatorOpen && <NavigatorRoomCreatorView /> }
<Flex className="nav-bottom">
<Flex className="position-absolute bottom-3">
<Flex className="nav-create-room" onClick={ (event) => setCreatorOpen(value => !value) }>
<Text variant="white" bold className="nav-bottom-buttons-text">
{ LocalizeText('navigator.createroom.create') }
</Text>
</Flex>
{ (searchResult?.code !== 'myworld_view' && searchResult?.code !== 'roomads_view') &&
<Flex className="nav-random-room" onClick={ () => SendMessageComposer(new FindNewFriendsMessageComposer()) }>
<Text variant="white" bold className="nav-bottom-buttons-text">
{ LocalizeText('navigator.random.room') }
</Text>
</Flex>
}
{ (searchResult?.code === 'myworld_view' || searchResult?.code === 'roomads_view') &&
<Flex className="nav-promote-room" onClick={ () => CreateLinkEvent('catalog/open/room_event') }>
<Text variant="white" bold className="nav-bottom-buttons-text">
{ LocalizeText('navigator.promote.room') }
</Text>
</Flex>
}
</Flex>
</Flex>
</Flex>
</Flex>
</Column>
</NitroCardContentView>
</NitroCardView> }
{ isCreatorOpen && <NavigatorRoomCreatorView /> }
<NavigatorDoorStateView />
{ isRoomInfoOpen && <NavigatorRoomInfoView onCloseClick={ () => setRoomInfoOpen(false) } /> }
{ isRoomLinkOpen && <NavigatorRoomLinkView onCloseClick={ () => setRoomLinkOpen(false) } /> }

View File

@ -1,6 +1,6 @@
import { FC, useEffect, useState } from 'react';
import { CreateRoomSession, DoorStateType, GoToDesktop, LocalizeText } from '../../../api';
import { Button, Column, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../common';
import { Button, Column, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../common';
import { useNavigator } from '../../../hooks';
const VISIBLE_STATES = [ DoorStateType.START_DOORBELL, DoorStateType.STATE_WAITING, DoorStateType.STATE_NO_ANSWER, DoorStateType.START_PASSWORD, DoorStateType.STATE_WRONG_PASSWORD ];
@ -63,46 +63,46 @@ export const NavigatorDoorStateView: FC<{}> = props =>
const isDoorbell = (DOORBELL_STATES.indexOf(doorData.state) >= 0);
return (
<NitroCardView className="nitro-navigator-doorbell" theme="primary-slim">
<NitroCardView className="nitro-navigator-doorbell" theme="primary">
<NitroCardHeaderView headerText={ LocalizeText(isDoorbell ? 'navigator.doorbell.title' : 'navigator.password.title') } onCloseClick={ onClose } />
<NitroCardContentView>
<NitroCardContentView className="px-3 pb-4">
<Column gap={ 1 }>
<Text bold>{ doorData && doorData.roomInfo && doorData.roomInfo.roomName }</Text>
<Text small bold>{ doorData && doorData.roomInfo && doorData.roomInfo.roomName }</Text>
{ (doorData.state === DoorStateType.START_DOORBELL) &&
<Text>{ LocalizeText('navigator.doorbell.info') }</Text> }
<Text small>{ LocalizeText('navigator.doorbell.info') }</Text> }
{ (doorData.state === DoorStateType.STATE_WAITING) &&
<Text>{ LocalizeText('navigator.doorbell.waiting') }</Text> }
<Text small>{ LocalizeText('navigator.doorbell.waiting') }</Text> }
{ (doorData.state === DoorStateType.STATE_NO_ANSWER) &&
<Text>{ LocalizeText('navigator.doorbell.no.answer') }</Text> }
<Text small>{ LocalizeText('navigator.doorbell.no.answer') }</Text> }
{ (doorData.state === DoorStateType.START_PASSWORD) &&
<Text>{ LocalizeText('navigator.password.info') }</Text> }
<Text small>{ LocalizeText('navigator.password.info') }</Text> }
{ (doorData.state === DoorStateType.STATE_WRONG_PASSWORD) &&
<Text>{ LocalizeText('navigator.password.retryinfo') }</Text> }
<Text small>{ LocalizeText('navigator.password.retryinfo') }</Text> }
</Column>
{ isDoorbell &&
<Column gap={ 1 }>
<Flex fullWidth gap={ 1 } className="align-items-end mt-auto pt-3">
<Text small className="cursor-pointer" underline onClick={ onClose }>
{ LocalizeText('generic.cancel') }
</Text>
{ (doorData.state === DoorStateType.START_DOORBELL) &&
<Button variant="success" onClick={ ring }>
<Button className="ms-auto" onClick={ ring }>
{ LocalizeText('navigator.doorbell.button.ring') }
</Button> }
<Button variant="danger" onClick={ onClose }>
{ LocalizeText('generic.cancel') }
</Button>
</Column> }
</Flex> }
{ !isDoorbell &&
<>
<Column gap={ 1 }>
<Text>{ LocalizeText('navigator.password.enter') }</Text>
<Flex className="pt-3 align-items-center" gap={ 1 }>
<Text small fullWidth>{ LocalizeText('navigator.password.enter') }</Text>
<input type="password" className="form-control form-control-sm" onChange={ event => setPassword(event.target.value) } />
</Column>
<Column gap={ 1 }>
<Button variant="success" onClick={ tryEntering }>
</Flex>
<Flex fullWidth gap={ 1 } className="align-items-end mt-auto pt-3">
<Text small className="cursor-pointer" underline onClick={ onClose }>
{ LocalizeText('generic.cancel') }
</Text>
<Button className="ms-auto" onClick={ tryEntering }>
{ LocalizeText('navigator.password.button.try') }
</Button>
<Button variant="danger" onClick={ onClose }>
{ LocalizeText('generic.cancel') }
</Button>
</Column>
</Flex>
</> }
</NitroCardContentView>
</NitroCardView>

View File

@ -1,8 +1,9 @@
/* eslint-disable no-template-curly-in-string */
import { CreateFlatMessageComposer, HabboClubLevelEnum } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { GetClubMemberLevel, GetConfiguration, IRoomModel, LocalizeText, SendMessageComposer } from '../../../api';
import { Button, Column, Flex, Grid, LayoutCurrencyIcon, LayoutGridItem, Text } from '../../../common';
import { CreateLinkEvent, GetClubMemberLevel, GetConfiguration, IRoomModel, LocalizeText, SendMessageComposer } from '../../../api';
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutInputErrorView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../common';
import { RoomCreatorGridItem } from '../../../common/layout/RoomCreatorGridItem';
import { useNavigator } from '../../../hooks';
export const NavigatorRoomCreatorView: FC<{}> = props =>
@ -23,15 +24,19 @@ export const NavigatorRoomCreatorView: FC<{}> = props =>
const selectModel = (model: IRoomModel, index: number) =>
{
if(!model || (model.clubLevel > GetClubMemberLevel())) return;
if(!model) return;
if (GetClubMemberLevel() < model.clubLevel) return CreateLinkEvent('habboUI/open/hccenter');
setSelectedModelName(roomModels[index].name);
};
}
const createRoom = () =>
{
if (!name || (name.length < 3)) return;
SendMessageComposer(new CreateFlatMessageComposer(name, description, 'model_' + selectedModelName, Number(category), Number(visitorsCount), tradesSetting));
};
}
useEffect(() =>
{
@ -63,19 +68,23 @@ export const NavigatorRoomCreatorView: FC<{}> = props =>
}, []);
return (
<NitroCardView className="nitro-room-creator" theme="primary">
<NitroCardHeaderView headerText={ LocalizeText('navigator.createroom.title') } onCloseClick={ event => CreateLinkEvent('navigator/close-creator') } />
<NitroCardContentView>
<Column overflow="hidden">
<Grid overflow="hidden">
<Column size={ 6 } gap={ 1 } overflow="auto">
<Column size={ 5 } gap={ 1 } overflow="auto" className="px-2 py-1">
<Column gap={ 1 }>
<Text>{ LocalizeText('navigator.createroom.roomnameinfo') }</Text>
<input type="text" className="form-control form-control-sm" maxLength={ 60 } onChange={ event => setName(event.target.value) } placeholder={ LocalizeText('navigator.createroom.roomnameinfo') } />
<Text >{ LocalizeText('navigator.createroom.roomnameinfo') }</Text>
<input type="text" className={ `room-creator-form ${ (!name || (name.length < 3)) ? 'input-error' : '' }` } maxLength={ 60 } onChange={ event => setName(event.target.value) } placeholder={ LocalizeText('navigator.createroom.roomnameinfo') } />
{ (!name || (name.length < 3)) && <LayoutInputErrorView text={ LocalizeText('navigator.createroom.nameerr') } /> }
</Column>
<Column grow gap={ 1 }>
<Text>{ LocalizeText('navigator.createroom.roomdescinfo') }</Text>
<textarea className="flex-grow-1 form-control form-control-sm w-100" maxLength={ 255 } onChange={ event => setDescription(event.target.value) } placeholder={ LocalizeText('navigator.createroom.roomdescinfo') } />
<Text >{ LocalizeText('navigator.createroom.roomdescinfo') }</Text>
<textarea className="flex-grow-1 room-creator-form" maxLength={ 255 } onChange={ event => setDescription(event.target.value) } placeholder={ LocalizeText('navigator.createroom.roomdescinfo') } />
</Column>
<Column gap={ 1 }>
<Text>{ LocalizeText('navigator.category') }</Text>
<Text >{ LocalizeText('navigator.category') }</Text>
<select className="form-select form-select-sm" onChange={ event => setCategory(Number(event.target.value)) }>
{ categories && (categories.length > 0) && categories.map(category =>
{
@ -84,7 +93,7 @@ export const NavigatorRoomCreatorView: FC<{}> = props =>
</select>
</Column>
<Column gap={ 1 }>
<Text>{ LocalizeText('navigator.maxvisitors') }</Text>
<Text >{ LocalizeText('navigator.maxvisitors') }</Text>
<select className="form-select form-select-sm" onChange={ event => setVisitorsCount(Number(event.target.value)) }>
{ maxVisitorsList && maxVisitorsList.map(value =>
{
@ -93,30 +102,39 @@ export const NavigatorRoomCreatorView: FC<{}> = props =>
</select>
</Column>
<Column gap={ 1 }>
<Text>{ LocalizeText('navigator.tradesettings') }</Text>
<Text >{ LocalizeText('navigator.tradesettings') }</Text>
<select className="form-select form-select-sm" onChange={ event => setTradesSetting(Number(event.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>
</Column>
<Flex gap={ 2 }>
<Button fullWidth className="volter-bold-button text-black" onClick={ createRoom }>{ LocalizeText('navigator.createroom.create') }</Button>
<Button fullWidth className="volter-button text-black" onClick={ event => CreateLinkEvent('navigator/close-creator') } >{ LocalizeText('cancel') }</Button>
</Flex>
</Column>
<Column size={ 6 } gap={ 1 } overflow="auto">
<Column size={ 7 } gap={ 1 } overflow="auto">
<AutoGrid className="room-creator-grid" gap={ 1 } columnCount={ 2 } columnMinWidth={ 100 } columnMinHeight={ 50 } overflow="unset">
{
roomModels.map((model, index )=>
{
return (<LayoutGridItem fullHeight key={ model.name } onClick={ () => selectModel(model, index) } itemActive={ (selectedModelName === model.name) } overflow="unset" gap={ 0 } className="p-1" disabled={ (GetClubMemberLevel() < model.clubLevel) }>
return (<RoomCreatorGridItem fullHeight key={ model.name } onClick={ () => selectModel(model, index) } itemActive={ (selectedModelName === model.name) } overflow="unset" gap={ 0 } className="py-3">
<Flex fullHeight center overflow="hidden">
<img alt="" src={ getRoomModelImage(model.name) } />
</Flex>
<Text bold>{ model.tileSize } { LocalizeText('navigator.createroom.tilesize') }</Text>
{ !hcDisabled && model.clubLevel > HabboClubLevelEnum.NO_CLUB && <LayoutCurrencyIcon position="absolute" className="top-1 end-1" type="hc" /> }
</LayoutGridItem>);
<Text position="absolute" className="bottom-1 start-1"><Base className={ `icon ${ selectedModelName === model.name ? 'icon-tiles_room_selected' : 'icon-tiles' }` } /> { model.tileSize } { LocalizeText('navigator.createroom.tilesize') }</Text>
{ !hcDisabled && model.clubLevel > HabboClubLevelEnum.NO_CLUB && <Base className="icon icon-hc_mini position-absolute top-1 end-1" /> }
{ selectedModelName && <i className="active-arrow"/> }
</RoomCreatorGridItem>);
})
}
</AutoGrid>
</Column>
</Grid>
<Button fullWidth variant={ (!name || (name.length < 3)) ? 'danger' : 'success' } onClick={ createRoom } disabled={ (!name || (name.length < 3)) }>{ LocalizeText('navigator.createroom.create') }</Button>
</Column>
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -1,8 +1,8 @@
import { GetCustomRoomFilterMessageComposer, NavigatorSearchComposer, RoomMuteComposer, RoomSettingsComposer, SecurityLevel, ToggleStaffPickMessageComposer, UpdateHomeRoomMessageComposer } from '@nitrots/nitro-renderer';
import { AddFavouriteRoomMessageComposer, DeleteFavouriteRoomMessageComposer, GetCustomRoomFilterMessageComposer, NavigatorSearchComposer, RoomMuteComposer, RoomSettingsComposer, SecurityLevel, ToggleStaffPickMessageComposer, UpdateHomeRoomMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { FaLink } from 'react-icons/fa';
import { CreateLinkEvent, DispatchUiEvent, GetGroupInformation, GetSessionDataManager, LocalizeText, ReportType, SendMessageComposer } from '../../../api';
import { Button, classNames, Column, Flex, LayoutBadgeImageView, LayoutRoomThumbnailView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text, UserProfileIconView } from '../../../common';
import { CreateLinkEvent, DispatchUiEvent, GetConfiguration, GetGroupInformation, GetSessionDataManager, GetUserProfile, LocalizeText, ReportType, SendMessageComposer } from '../../../api';
import { Base, Button, Column, Flex, LayoutBadgeImageView, LayoutRoomThumbnailView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text, UserProfileIconView, classNames } from '../../../common';
import { RoomWidgetThumbnailEvent } from '../../../events';
import { useHelp, useNavigator } from '../../../hooks';
@ -16,6 +16,7 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
const { onCloseClick = null } = props;
const [ isRoomPicked, setIsRoomPicked ] = useState(false);
const [ isRoomMuted, setIsRoomMuted ] = useState(false);
const [ isOpenLink, setIsOpenLink ] = useState<boolean>(false);
const { report = null } = useHelp();
const { navigatorData = null } = useNavigator();
@ -53,15 +54,14 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
return;
case 'open_room_thumbnail_camera':
DispatchUiEvent(new RoomWidgetThumbnailEvent(RoomWidgetThumbnailEvent.TOGGLE_THUMBNAIL));
onCloseClick();
return;
case 'open_group_info':
GetGroupInformation(navigatorData.enteredGuestRoom.habboGroupId);
return;
case 'toggle_room_link':
CreateLinkEvent('navigator/toggle-room-link');
return;
case 'open_room_settings':
SendMessageComposer(new RoomSettingsComposer(navigatorData.enteredGuestRoom.roomId));
onCloseClick();
return;
case 'toggle_pick':
setIsRoomPicked(value => !value);
@ -73,12 +73,21 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
return;
case 'room_filter':
SendMessageComposer(new GetCustomRoomFilterMessageComposer(navigatorData.enteredGuestRoom.roomId));
onCloseClick();
return;
case 'open_floorplan_editor':
CreateLinkEvent('floor-editor/toggle');
onCloseClick();
return;
case 'report_room':
report(ReportType.ROOM, { roomId: navigatorData.enteredGuestRoom.roomId, roomName: navigatorData.enteredGuestRoom.roomName });
onCloseClick();
return;
case 'set_favourite_room':
SendMessageComposer(new AddFavouriteRoomMessageComposer(navigatorData.enteredGuestRoom.roomId));
return;
case 'set_unfavourite_room':
SendMessageComposer(new DeleteFavouriteRoomMessageComposer(navigatorData.enteredGuestRoom.roomId));
return;
case 'close':
onCloseClick();
@ -99,70 +108,86 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
if(!navigatorData.enteredGuestRoom) return null;
return (
<NitroCardView className="nitro-room-info" theme="primary-slim">
<NitroCardView className="nitro-room-info" theme="primary">
<NitroCardHeaderView headerText={ LocalizeText('navigator.roomsettings.roominfo') } onCloseClick={ () => processAction('close') } />
<NitroCardContentView className="text-black">
{ navigatorData.enteredGuestRoom &&
<>
<Flex gap={ 2 } overflow="hidden">
<LayoutRoomThumbnailView roomId={ navigatorData.enteredGuestRoom.roomId } customUrl={ navigatorData.enteredGuestRoom.officialRoomPicRef }>
{ hasPermission('settings') && <i className="icon icon-camera-small position-absolute b-0 r-0 m-1 cursor-pointer top-0" onClick={ () => processAction('open_room_thumbnail_camera') } /> }
</LayoutRoomThumbnailView>
<Column grow gap={ 1 } overflow="hidden">
<Flex gap={ 1 }>
<Column grow gap={ 1 }>
<Flex gap={ 1 }>
<i onClick={ () => processAction('set_home_room') } className={ classNames('flex-shrink-0 icon icon-house-small cursor-pointer', ((navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId) && 'gray')) } />
<Flex gap={ 1 } justifyContent="between">
<Text bold>{ navigatorData.enteredGuestRoom.roomName }</Text>
<Flex>
<i title={ navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId ? LocalizeText('navigator.roominfo.makehome.tooltip') : '' } onClick={ () => processAction('set_home_room') } className={ classNames('flex-shrink-0 icon icon-house-small', ((navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId) && 'cursor-pointer'), ((navigatorData.homeRoomId !== navigatorData.enteredGuestRoom.roomId) && 'gray')) } />
{ /* <Flex className={ navigatorData.enteredGuestRoom.ownerId !== GetSessionDataManager().userId ? 'ms-1' : 'ms-4' }>
{ (navigatorData.enteredGuestRoom.ownerId !== GetSessionDataManager().userId) &&
<i onClick={ () => processAction('set_favourite_room') } className={ classNames('flex-shrink-0 icon icon-favourite-room-active cursor-pointer') } />
<i onClick={ () => processAction('set_unfavourite_room') } className={ classNames('flex-shrink-0 icon icon-favourite-room-inactive cursor-pointer') } />
}
</Flex> */ }
</Flex>
</Flex>
{ navigatorData.enteredGuestRoom.showOwner &&
<Flex alignItems="center" gap={ 1 }>
<Text variant="muted">{ LocalizeText('navigator.roomownercaption') }</Text>
<Flex pointer title={ LocalizeText('guide.help.common.profile.tooltip') } alignItems="center" gap={ 1 } onClick={ () => GetUserProfile(navigatorData.enteredGuestRoom.ownerId) }>
<Text small variant="muted">{ LocalizeText('navigator.roomownercaption') }</Text>
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ navigatorData.enteredGuestRoom.ownerId } />
<Text>{ navigatorData.enteredGuestRoom.ownerName }</Text>
<Text small>{ navigatorData.enteredGuestRoom.ownerName }</Text>
</Flex>
</Flex> }
</Flex>
}
<Flex alignItems="center" gap={ 1 }>
<Text variant="muted">{ LocalizeText('navigator.roomrating') }</Text>
<Text>{ navigatorData.currentRoomRating }</Text>
<Text small variant="muted">{ LocalizeText('navigator.roomrating') }</Text>
<Text small>{ navigatorData.currentRoomRating }</Text>
</Flex>
{ (navigatorData.enteredGuestRoom.tags.length > 0) &&
<Flex alignItems="center" gap={ 1 }>
<Flex className="mt-1" alignItems="center" gap={ 1 }>
{ navigatorData.enteredGuestRoom.tags.map(tag =>
{
return <Text key={ tag } pointer className="bg-muted rounded p-1" onClick={ event => processAction('navigator_search_tag', tag) }>#{ tag }</Text>
return <Text key={ tag } pointer className="text-tag rounded p-1" onClick={ event => processAction('navigator_search_tag', tag) }>#{ tag }</Text>
}) }
</Flex> }
</Column>
<Column alignItems="center" gap={ 1 }>
{ hasPermission('settings') &&
<i className="icon icon-cog cursor-pointer" title={ LocalizeText('navigator.room.popup.info.room.settings') } onClick={ event => processAction('open_room_settings') } /> }
<FaLink title={ LocalizeText('navigator.embed.caption') } className="cursor-pointer fa-icon" onClick={ event => CreateLinkEvent('navigator/toggle-room-link') } />
</Flex>
}
</Column>
</Flex>
<Text overflow="auto" style={ { maxHeight: 50 } }>{ navigatorData.enteredGuestRoom.description }</Text>
<Text small overflow="auto" style={ { wordBreak: 'break-all' } }>{ navigatorData.enteredGuestRoom.description }</Text>
<Flex justifyContent="center">
<LayoutRoomThumbnailView title={ LocalizeText('tooltip.navigator.room.info.add.thumbnail') } roomId={ navigatorData.enteredGuestRoom.roomId } customUrl={ navigatorData.enteredGuestRoom.officialRoomPicRef }>
{ hasPermission('settings') && <i className="icon icon-camera-small position-absolute cursor-pointer bottom-1 end-1" onClick={ () => processAction('open_room_thumbnail_camera') } /> }
</LayoutRoomThumbnailView>
</Flex>
{ (navigatorData.enteredGuestRoom.habboGroupId > 0) &&
<Flex pointer alignItems="center" gap={ 1 } onClick={ () => processAction('open_group_info') }>
<Flex pointer alignItems="center" gap={ 2 } onClick={ () => processAction('open_group_info') }>
<LayoutBadgeImageView className="flex-none" badgeCode={ navigatorData.enteredGuestRoom.groupBadgeCode } isGroup={ true } />
<Text underline>
<Text small underline>
{ LocalizeText('navigator.guildbase', [ 'groupName' ], [ navigatorData.enteredGuestRoom.groupName ]) }
</Text>
</Flex> }
</Flex>
}
<Flex gap={ 1 } className="w-100 room-tool-item" onClick={ () => setIsOpenLink(prevValue => !prevValue) }>
<Base pointer title={ LocalizeText('room.like.button.text') } className="icon-width icon icon-link-room float-start" />
<Text underline small >{ LocalizeText('navigator.embed.caption') }</Text>
</Flex>
{ (isOpenLink) &&
<Column className="w-100">
<Text className="text-embed">{ LocalizeText('navigator.embed.info') }</Text>
<input type="text" readOnly className="form-control form-control-sm" value={ LocalizeText('navigator.embed.src', [ 'roomId' ], [ navigatorData.enteredGuestRoom.roomId.toString() ]).replace('${url.prefix}', GetConfiguration<string>('url.prefix', '')) } />
</Column>
}
</Column>
</Flex>
<Column 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 onClick={ () => processAction('open_room_settings') }>
{ LocalizeText('navigator.room.popup.info.room.settings') }
</Button>
<Button onClick={ () => processAction('room_filter') }>
{ LocalizeText('navigator.roomsettings.roomfilter') }
@ -170,9 +195,24 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
<Button onClick={ () => processAction('open_floorplan_editor') }>
{ LocalizeText('open.floor.plan.editor') }
</Button>
</> }
</>
}
{ hasPermission('settings') &&
<Button onClick={ () => processAction('toggle_mute') }>
{ LocalizeText(isRoomMuted ? 'navigator.muteall_on' : 'navigator.muteall_off') }
</Button>
}
<Flex justifyContent="center" alignItems="center">
<Button className="col-8 mt-2 mb-2 btn-danger" onClick={ () => processAction('report_room') }>
<Base className="flex-shrink-0 icon icon-report-room" />
<Base className="vr" />
<b className="px-2">{ LocalizeText('help.emergency.main.report.room') }</b>
</Button>
</Flex>
</Column>
</> }
</>
}
</NitroCardContentView>
</NitroCardView>

View File

@ -16,7 +16,7 @@ export const NavigatorRoomLinkView: FC<NavigatorRoomLinkViewProps> = props =>
if(!navigatorData.enteredGuestRoom) return null;
return (
<NitroCardView className="nitro-room-link" theme="primary-slim">
<NitroCardView className="nitro-room-link no-resize" theme="primary">
<NitroCardHeaderView headerText={ LocalizeText('navigator.embed.title') } onCloseClick={ onCloseClick } />
<NitroCardContentView className="text-black d-flex align-items-center">
<Flex gap={ 2 }>
@ -24,6 +24,7 @@ export const NavigatorRoomLinkView: FC<NavigatorRoomLinkViewProps> = props =>
<Column>
<Text bold fontSize={ 5 }>{ LocalizeText('navigator.embed.headline') }</Text>
<Text>{ LocalizeText('navigator.embed.info') }</Text>
<Text> { LocalizeText('navigator.embed.direct.info') }</Text>
<input type="text" readOnly className="form-control form-control-sm" value={ LocalizeText('navigator.embed.src', [ 'roomId' ], [ navigatorData.enteredGuestRoom.roomId.toString() ]).replace('${url.prefix}', GetConfiguration<string>('url.prefix', '')) } />
</Column>
</Flex>

View File

@ -58,7 +58,7 @@ export const NavigatorRoomSettingsModTabView: FC<NavigatorRoomSettingsTabViewPro
{
return (
<Flex key={ index } shrink alignItems="center" gap={ 1 } overflow="hidden">
<UserProfileIconView userName={ user.userName } />
<UserProfileIconView userName={ user.userId } />
<Text pointer grow onClick={ event => setSelectedUserId(user.userId) }> { user.userName }</Text>
</Flex>
);

View File

@ -15,7 +15,9 @@ export const NavigatorRoomSettingsRightsTabView: FC<NavigatorRoomSettingsTabView
const { roomData = null } = props;
const [ usersWithRights, setUsersWithRights ] = useState<Map<number, string>>(new Map());
const { onlineFriends = [], offlineFriends = [] } = useFriends();
const allFriends = [ ...onlineFriends, ...offlineFriends ];
const friendWitoutRights = allFriends.filter(friend => !usersWithRights.has(friend.id));
useMessageEvent<FlatControllersEvent>(FlatControllersEvent, event =>
@ -76,13 +78,16 @@ export const NavigatorRoomSettingsRightsTabView: FC<NavigatorRoomSettingsTabView
{
return (
<Flex key={ index } shrink alignItems="center" gap={ 1 } overflow="hidden">
<UserProfileIconView userName={ name } />
<UserProfileIconView userId={ id } />
<Text pointer grow onClick={ event => SendMessageComposer(new RoomTakeRightsComposer(id)) }> { name }</Text>
</Flex>
);
}) }
</Column>
</Flex>
<Button variant="danger" disabled={ !usersWithRights.size } onClick={ event => SendMessageComposer(new RemoveAllRightsMessageComposer(roomData.roomId)) } >
{ LocalizeText('navigator.flatctrls.clear') }
</Button>
</Column>
<Column size={ 6 }>
<Text bold>
@ -94,16 +99,13 @@ export const NavigatorRoomSettingsRightsTabView: FC<NavigatorRoomSettingsTabView
{
return (
<Flex key={ index } shrink alignItems="center" gap={ 1 } overflow="hidden">
<UserProfileIconView userName={ friend.name } />
<UserProfileIconView userId={ friend.id } />
<Text pointer grow onClick={ event => SendMessageComposer(new RoomGiveRightsComposer(friend.id)) }> { friend.name }</Text>
</Flex>
);
}) }
</Column>
</Flex>
<Button variant="danger" disabled={ !usersWithRights.size } onClick={ event => SendMessageComposer(new RemoveAllRightsMessageComposer(roomData.roomId)) } >
{ LocalizeText('navigator.flatctrls.clear') }
</Button>
</Column>
</Grid>
);

View File

@ -1,6 +1,6 @@
import { RoomBannedUsersComposer, RoomDataParser, RoomSettingsDataEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
import { FC, useState } from 'react';
import { IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
import { CreateLinkEvent, IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../common';
import { useMessageEvent } from '../../../../hooks';
import { NavigatorRoomSettingsAccessTabView } from './NavigatorRoomSettingsAccessTabView';
@ -182,7 +182,7 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
return (
<NitroCardView uniqueKey="nitro-room-settings" className="nitro-room-settings">
<NitroCardHeaderView headerText={ LocalizeText('navigator.roomsettings') } onCloseClick={ onClose } />
<NitroCardHeaderView headerText={ LocalizeText('navigator.roomsettings') } isInfoToHabboPages={ (currentTab === TABS[3]) ? true : false } onClickInfoHabboPages={ () => (currentTab === TABS[3]) ? CreateLinkEvent('habbopages/chat/options') : null }onCloseClick={ onClose } />
<NitroCardTabsView>
{ TABS.map(tab =>
{

View File

@ -1,5 +1,5 @@
import { RoomDataParser } from '@nitrots/nitro-renderer';
import { FC, useRef, useState } from 'react';
import { FC, useEffect, useRef, useState } from 'react';
import { Overlay, Popover } from 'react-bootstrap';
import { FaUser } from 'react-icons/fa';
import { LocalizeText } from '../../../../api';
@ -15,6 +15,37 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
const { roomData = null } = props;
const [ isVisible, setIsVisible ] = useState(false);
const elementRef = useRef<HTMLDivElement>();
const [ showProfile, setShowProfile ] = useState(false);
useEffect(() =>
{
if (showProfile)
{
setIsVisible(false);
}
}, [ showProfile ]);
useEffect(() =>
{
// add when mounted
document.addEventListener('mousedown', handleClick);
// return function to be called when unmounted
return () =>
{
document.removeEventListener('mousedown', handleClick);
};
}, []);
const handleClick = e =>
{
if (elementRef.current.contains(e.target))
{
// inside click
return;
}
// outside click
setIsVisible(false);
};
const getUserCounterColor = () =>
{
@ -40,11 +71,15 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
return (
<>
<Base pointer innerRef={ elementRef } className="icon icon-navigator-info" onMouseOver={ event => setIsVisible(true) } onMouseLeave={ event => setIsVisible(false) } />
<Overlay show={ isVisible } target={ elementRef.current } placement="right">
<Base pointer innerRef={ elementRef } className="icon icon-navigator-info" onClick={ event =>
{
isVisible || showProfile ? setIsVisible(false) : setIsVisible(true);
event.stopPropagation();
} } />
<Overlay show={ isVisible } target={ elementRef.current } placement="right" rootClose={ true } >
<Popover>
<NitroCardContentView overflow="hidden" className="room-info image-rendering-pixelated bg-transparent">
<Flex gap={ 2 } overflow="hidden">
<NitroCardContentView overflow="hidden" className="room-info bg-transparent">
<Flex gap={ 2 } overflow="hidden" className="room-info-bg p-2">
<LayoutRoomThumbnailView roomId={ roomData.roomId } customUrl={ roomData.officialRoomPicRef } className="d-flex flex-column align-items-center justify-content-end mb-1">
{ roomData.habboGroupId > 0 && (
<LayoutBadgeImageView badgeCode={ roomData.groupBadgeCode } isGroup={ true } className={ 'position-absolute top-0 start-0 m-1 ' }/>) }
@ -60,7 +95,10 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
{ LocalizeText('navigator.roomownercaption') }
</Text>
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ roomData.ownerId } />
<UserProfileIconView userId={ roomData.ownerId } onClick={ event =>
{
setShowProfile(true);
} } />
<Text italics>{ roomData.ownerName }</Text>
</Flex>
</Flex>
@ -73,6 +111,22 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
</Flex>
</Column>
</Flex>
<Column>
<Flex>
<Flex gap={ 1 } className="align-items-center">
<UserProfileIconView userId={ roomData.ownerId }/>
<Text bold underline>{ roomData.ownerName }</Text>
</Flex>
<Flex gap={ 1 } className="align-items-center" justifyContent="end" fullWidth>
<i className="icon icon-navigator-room-group"/>
<Text bold underline>{ roomData.groupName }</Text>
</Flex>
</Flex>
<Flex gap={ 1 }>
<Text bold>{ LocalizeText('navigator.roompopup.property.max_users') }</Text>
<Text>{ roomData.maxUserCount }</Text>
</Flex>
</Column>
</NitroCardContentView>
</Popover>
</Overlay>

View File

@ -21,19 +21,19 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
{
const num: number = (100 * (roomData.userCount / roomData.maxUserCount));
let bg = 'bg-primary';
let bg = 'badge-empty';
if(num >= 92)
{
bg = 'bg-danger';
bg = 'badge-danger';
}
else if(num >= 50)
{
bg = 'bg-warning';
bg = 'badge-warning';
}
else if(num > 0)
{
bg = 'bg-success';
bg = 'badge-success';
}
return bg;
@ -81,7 +81,7 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
}
if(thumbnail) return (
<Column pointer overflow="hidden" alignItems="center" onClick={ visitRoom } gap={ 0 } className="navigator-item p-1 bg-light rounded-3 small mb-1 flex-column border border-muted" { ...rest }>
<Column pointer overflow="hidden" alignItems="center" onClick={ visitRoom } gap={ 0 } className="nav-thumbnail p-1 rounded-3 small mb-1 flex-column" { ...rest }>
<LayoutRoomThumbnailView roomId={ roomData.roomId } customUrl={ roomData.officialRoomPicRef } className="d-flex flex-column align-items-center justify-content-end mb-1">
{ roomData.habboGroupId > 0 && <LayoutBadgeImageView badgeCode={ roomData.groupBadgeCode } isGroup={ true } className={ 'position-absolute top-0 start-0 m-1' } /> }
<Flex center className={ 'badge p-1 position-absolute m-1 ' + getUserCounterColor() } gap={ 1 }>
@ -103,9 +103,9 @@ export const NavigatorSearchResultItemView: FC<NavigatorSearchResultItemViewProp
);
return (
<Flex pointer overflow="hidden" alignItems="center" onClick={ visitRoom } gap={ 2 } className="navigator-item px-2 py-1 small" { ...rest }>
<Flex center className={ 'badge p-1 ' + getUserCounterColor() } gap={ 1 }>
<FaUser className="fa-icon" />
<Flex pointer overflow="hidden" alignItems="center" onClick={ visitRoom } gap={ 2 } className="navigator-item px-2 small" { ...rest }>
<Flex center className={ 'p-1 fw-bold ' + getUserCounterColor() } gap={ 1 }>
<div className="nav-avatar-icon"/>
{ roomData.userCount }
</Flex>
<Text truncate grow>{ roomData.roomName }</Text>

View File

@ -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 } from '../../../../common';
import { useNavigator } from '../../../../hooks';
import { NavigatorSearchResultItemView } from './NavigatorSearchResultItemView';
@ -58,20 +58,20 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
const gridHasTwoColumns = (displayMode >= NavigatorSearchResultViewDisplayMode.THUMBNAILS);
return (
<Column className="bg-white rounded border border-muted" gap={ 0 }>
<Column className="bg-white" gap={ 0 }>
<Flex fullWidth alignItems="center" justifyContent="between" className="px-2 py-1">
<Flex grow pointer alignItems="center" gap={ 1 } onClick={ event => setIsExtended(prevValue => !prevValue) }>
{ isExtended && <FaMinus className="text-secondary fa-icon" /> }
{ !isExtended && <FaPlus className="text-secondary fa-icon" /> }
<Text>{ LocalizeText(getResultTitle()) }</Text>
<div className="nav-category"> { LocalizeText(getResultTitle()) }</div>
</Flex>
<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 } /> }
{ (topLevelContext.code !== 'official_view') && <LayoutSearchSavesView title={ LocalizeText('navigator.tooltip.add.saved.search') } onClick={ () => SendMessageComposer(new NavigatorSearchSaveComposer(getResultTitle(), searchResult.data)) } /> }
</Flex>
</Flex> { isExtended &&
<>
{
@ -84,35 +84,5 @@ export const NavigatorSearchResultView: FC<NavigatorSearchResultViewProps> = pro
</>
}
</Column>
// <div className="nitro-navigator-search-result bg-white rounded mb-2 overflow-hidden">
// <div className="d-flex flex-column">
// <div className="d-flex align-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 flex-grow-1">{ 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="d-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-100 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>
);
}

View File

@ -0,0 +1,47 @@
import { NavigatorDeleteSavedSearchComposer, NavigatorSavedSearch, NavigatorSearchComposer } from '@nitrots/nitro-renderer';
import { FC, useState } from 'react';
import { LocalizeText, SendMessageComposer } from '../../../../api';
import { Base, 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);
}
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={ () => onHover(search.id) } onMouseLeave={ () => onLeave() }>
{ (isHoverText && currentIndex === search.id) &&
<Base className="icon nitro-navigator-search-delete" 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>
);
}

View File

@ -0,0 +1,30 @@
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
{
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 }>
<FaBolt color="white" />
<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,7 +1,6 @@
import { FC, KeyboardEvent, useEffect, useState } from 'react';
import { FaSearch } from 'react-icons/fa';
import { INavigatorSearchFilter, LocalizeText, SearchFilterOptions } from '../../../../api';
import { Button, Flex } from '../../../../common';
import { Flex } from '../../../../common';
import { useNavigator } from '../../../../hooks';
export interface NavigatorSearchViewProps
@ -64,7 +63,7 @@ export const NavigatorSearchView: FC<NavigatorSearchViewProps> = props =>
}, [ searchResult ]);
return (
<Flex fullWidth gap={ 1 }>
<Flex fullWidth gap={ 1 } className="mb-2">
<Flex shrink>
<select className="form-select form-select-sm" value={ searchFilterIndex } onChange={ event => setSearchFilterIndex(parseInt(event.target.value)) }>
{ SearchFilterOptions.map((filter, index) =>
@ -73,11 +72,9 @@ export const NavigatorSearchView: FC<NavigatorSearchViewProps> = props =>
}) }
</select>
</Flex>
<Flex fullWidth gap={ 1 }>
<Flex fullWidth gap={ 2 }>
<input type="text" className="form-control form-control-sm" placeholder={ LocalizeText('navigator.filter.input.placeholder') } value={ searchValue } onChange={ event => setSearchValue(event.target.value) } onKeyDown={ event => handleKeyDown(event) } />
<Button variant="primary" onClick={ processSearch }>
<FaSearch className="fa-icon" />
</Button>
<i className="icon icon-pen navigator-search-button position-absolute" onClick={ processSearch } />
</Flex>
</Flex>
);

View File

@ -39,7 +39,7 @@ export const NitroSystemAlertView: FC<NotificationDefaultAlertViewProps> = props
<Text>- Jonas (Contributing)</Text>
<Text>- Ohlucas (Sunset resources)</Text>
<Text center bold small>v1.2.0</Text>
<Button fullWidth onClick={ event => window.open('https://github.com/duckietm/Nitro-Cool-UI') }>Cool UI Git</Button>
<Button fullWidth onClick={ event => window.open('https://git.krews.org/nitro/nitro-react') }>Cool UI Git</Button>
</Column>
</Column>
</Grid>

View File

@ -1,373 +1,268 @@
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 { useState } from 'react';
import { useBetween } from 'use-between';
import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, INavigatorData, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api';
import { useMessageEvent } from '../events';
import { useNotification } from '../notification';
import { CanCreateRoomEventEvent, CantConnectMessageParser, DoorbellMessageEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, HabboWebTools, LegacyExternalInterface, NavigatorCategoryDataParser, NavigatorEventCategoryDataParser, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSavedSearch, NavigatorSearchEvent, NavigatorSearchResultSet, NavigatorSearchesEvent, 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 { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, INavigatorData, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop, } from "../../api";
import { useMessageEvent } from "../events";
import { useNotification } from "../notification";
const useNavigatorState = () =>
{
const [ categories, setCategories ] = useState<NavigatorCategoryDataParser[]>(null);
const [ eventCategories, setEventCategories ] = useState<NavigatorEventCategoryDataParser[]>(null);
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 [ navigatorData, setNavigatorData ] = useState<INavigatorData>({
settingsReceived: false,
homeRoomId: 0,
enteredGuestRoom: null,
currentRoomOwner: false,
currentRoomId: 0,
currentRoomIsStaffPick: false,
createdFlatId: 0,
avatarId: 0,
roomPicker: false,
eventMod: false,
currentRoomRating: 0,
canRate: true
});
const useNavigatorState = () => {
const [categories, setCategories] = useState<NavigatorCategoryDataParser[]>(null);
const [eventCategories, setEventCategories] = useState<NavigatorEventCategoryDataParser[]>(null);
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 [searchResultQuery, setSearchResultQuery] = useState<string>("");
const [navigatorSearches, setNavigatorSearches] = useState<NavigatorSavedSearch[]>(null);
const [navigatorData, setNavigatorData] = useState<INavigatorData>({ settingsReceived: false, homeRoomId: 0, enteredGuestRoom: null, currentRoomOwner: false, currentRoomId: 0, currentRoomIsStaffPick: false, createdFlatId: 0, avatarId: 0, roomPicker: false, eventMod: false, currentRoomRating: 0, canRate: true });
const { simpleAlert = null } = useNotification();
useMessageEvent<RoomSettingsUpdatedEvent>(RoomSettingsUpdatedEvent, event =>
{
useMessageEvent<RoomSettingsUpdatedEvent>( RoomSettingsUpdatedEvent, (event) => { const parser = event.getParser(); SendMessageComposer( new GetGuestRoomMessageComposer(parser.roomId, false, false) ); });
useMessageEvent<CanCreateRoomEventEvent>(CanCreateRoomEventEvent, (event) => {
const parser = event.getParser();
SendMessageComposer(new GetGuestRoomMessageComposer(parser.roomId, false, false));
});
useMessageEvent<CanCreateRoomEventEvent>(CanCreateRoomEventEvent, event =>
{
const parser = event.getParser();
if(parser.canCreate)
{
// show room event cvreate
if (parser.canCreate) {
// show room event create
return;
}
simpleAlert(LocalizeText(`navigator.cannotcreateevent.error.${ parser.errorCode }`), null, null, null, LocalizeText('navigator.cannotcreateevent.title'));
});
simpleAlert( LocalizeText(`navigator.cannotcreateevent.error.${parser.errorCode}`), null, null, null, LocalizeText("navigator.cannotcreateevent.title") ); });
useMessageEvent<UserInfoEvent>(UserInfoEvent, event =>
{
SendMessageComposer(new GetUserFlatCatsMessageComposer());
SendMessageComposer(new GetUserEventCatsMessageComposer());
});
useMessageEvent<UserInfoEvent>(UserInfoEvent, (event) => { SendMessageComposer(new GetUserFlatCatsMessageComposer()); SendMessageComposer(new GetUserEventCatsMessageComposer()); });
useMessageEvent<UserPermissionsEvent>(UserPermissionsEvent, event =>
{
useMessageEvent<UserPermissionsEvent>(UserPermissionsEvent, (event) => {
const parser = event.getParser();
setNavigatorData(prevValue =>
{
setNavigatorData((prevValue) => {
const newValue = { ...prevValue };
newValue.eventMod = (parser.securityLevel >= SecurityLevel.MODERATOR);
newValue.roomPicker = (parser.securityLevel >= SecurityLevel.COMMUNITY);
newValue.eventMod = parser.securityLevel >= SecurityLevel.MODERATOR;
newValue.roomPicker = parser.securityLevel >= SecurityLevel.COMMUNITY;
return newValue;
});
});
useMessageEvent<RoomForwardEvent>(RoomForwardEvent, event =>
{
useMessageEvent<RoomForwardEvent>(RoomForwardEvent, (event) => { const parser = event.getParser(); TryVisitRoom(parser.roomId); });
useMessageEvent<RoomEntryInfoMessageEvent>(
RoomEntryInfoMessageEvent, (event) => {
const parser = event.getParser();
TryVisitRoom(parser.roomId);
});
useMessageEvent<RoomEntryInfoMessageEvent>(RoomEntryInfoMessageEvent, event =>
{
const parser = event.getParser();
setNavigatorData(prevValue =>
{
setNavigatorData((prevValue) => {
const newValue = { ...prevValue };
newValue.enteredGuestRoom = null;
newValue.currentRoomOwner = parser.isOwner;
newValue.currentRoomId = parser.roomId;
return newValue;
});
// close room info
// close room settings
// close room filter
SendMessageComposer( new GetGuestRoomMessageComposer(parser.roomId, true, false) );
SendMessageComposer(new GetGuestRoomMessageComposer(parser.roomId, true, false));
if (LegacyExternalInterface.available)
LegacyExternalInterface.call("legacyTrack", "navigator", "private", [ parser.roomId, ]);
}
);
if(LegacyExternalInterface.available) LegacyExternalInterface.call('legacyTrack', 'navigator', 'private', [ parser.roomId ]);
});
useMessageEvent<GetGuestRoomResultEvent>(GetGuestRoomResultEvent, event =>
{
useMessageEvent<GetGuestRoomResultEvent>(GetGuestRoomResultEvent, (event) => {
const parser = event.getParser();
if(parser.roomEnter)
{
if (parser.roomEnter) {
setDoorData({ roomInfo: null, state: DoorStateType.NONE });
setNavigatorData(prevValue =>
{
setNavigatorData((prevValue) => {
const newValue = { ...prevValue };
newValue.enteredGuestRoom = parser.data;
newValue.currentRoomIsStaffPick = parser.staffPick;
const isCreated = (newValue.createdFlatId === parser.data.roomId);
const isCreated = newValue.createdFlatId === parser.data.roomId;
if(!isCreated && parser.data.displayRoomEntryAd)
{
if(GetConfiguration<boolean>('roomenterad.habblet.enabled', false)) HabboWebTools.openRoomEnterAd();
if (!isCreated && parser.data.displayRoomEntryAd) {
if (GetConfiguration<boolean>("roomenterad.habblet.enabled", false))
HabboWebTools.openRoomEnterAd();
}
newValue.createdFlatId = 0;
if(newValue.enteredGuestRoom && (newValue.enteredGuestRoom.habboGroupId > 0))
{
if ( newValue.enteredGuestRoom && newValue.enteredGuestRoom.habboGroupId > 0 ) {
// close event info
}
return newValue;
});
}
else if(parser.roomForward)
{
if((parser.data.ownerName !== GetSessionDataManager().userName) && !parser.isGroupMember)
{
switch(parser.data.doorMode)
{
} else if (parser.roomForward) {
if ( parser.data.ownerName !== GetSessionDataManager().userName && !parser.isGroupMember) {
switch (parser.data.doorMode) {
case RoomDataParser.DOORBELL_STATE:
setDoorData(prevValue =>
{
setDoorData((prevValue) => {
const newValue = { ...prevValue };
newValue.roomInfo = parser.data;
newValue.state = DoorStateType.START_DOORBELL;
return newValue;
});
return;
case RoomDataParser.PASSWORD_STATE:
setDoorData(prevValue =>
{
const newValue = { ...prevValue };
return;
case RoomDataParser.PASSWORD_STATE: setDoorData((prevValue) => {
const newValue = { ...prevValue };
newValue.roomInfo = parser.data;
newValue.state = DoorStateType.START_PASSWORD;
return newValue;
});
return;
}
}
if((parser.data.doorMode === RoomDataParser.NOOB_STATE) && !GetSessionDataManager().isAmbassador && !GetSessionDataManager().isRealNoob && !GetSessionDataManager().isModerator) return;
if ( parser.data.doorMode === RoomDataParser.NOOB_STATE && !GetSessionDataManager().isAmbassador && !GetSessionDataManager().isRealNoob && !GetSessionDataManager().isModerator )
return;
CreateRoomSession(parser.data.roomId);
}
else
{
setNavigatorData(prevValue =>
{
} else {
setNavigatorData((prevValue) => {
const newValue = { ...prevValue };
newValue.enteredGuestRoom = parser.data;
newValue.currentRoomIsStaffPick = parser.staffPick;
return newValue;
});
}
});
}}
);
useMessageEvent<RoomScoreEvent>(RoomScoreEvent, (event) => {
useMessageEvent<RoomScoreEvent>(RoomScoreEvent, event =>
{
const parser = event.getParser();
setNavigatorData(prevValue =>
{
setNavigatorData((prevValue) => {
const newValue = { ...prevValue };
newValue.currentRoomRating = parser.totalLikes;
newValue.canRate = parser.canLike;
return newValue;
});
});
useMessageEvent<DoorbellMessageEvent>(DoorbellMessageEvent, event =>
{
useMessageEvent<DoorbellMessageEvent>(DoorbellMessageEvent, (event) => {
const parser = event.getParser();
if(!parser.userName || (parser.userName.length === 0))
{
setDoorData(prevValue =>
{
if (!parser.userName || parser.userName.length === 0) {
setDoorData((prevValue) => {
const newValue = { ...prevValue };
newValue.state = DoorStateType.STATE_WAITING;
return newValue;
});
}
});
useMessageEvent<RoomDoorbellAcceptedEvent>(RoomDoorbellAcceptedEvent, event =>
{
useMessageEvent<RoomDoorbellAcceptedEvent>( RoomDoorbellAcceptedEvent, (event) => {
const parser = event.getParser();
if(!parser.userName || (parser.userName.length === 0))
{
setDoorData(prevValue =>
{
if (!parser.userName || parser.userName.length === 0) {
setDoorData((prevValue) => {
const newValue = { ...prevValue };
newValue.state = DoorStateType.STATE_ACCEPTED;
return newValue;
});
}
});
}}
);
useMessageEvent<FlatAccessDeniedMessageEvent>( FlatAccessDeniedMessageEvent, (event) => {
useMessageEvent<FlatAccessDeniedMessageEvent>(FlatAccessDeniedMessageEvent, event =>
{
const parser = event.getParser();
if(!parser.userName || (parser.userName.length === 0))
{
setDoorData(prevValue =>
{
if (!parser.userName || parser.userName.length === 0) {
setDoorData((prevValue) => {
const newValue = { ...prevValue };
newValue.state = DoorStateType.STATE_NO_ANSWER;
return newValue;
});
}
});
useMessageEvent<GenericErrorEvent>(GenericErrorEvent, event =>
{
const parser = event.getParser();
useMessageEvent<GenericErrorEvent>(GenericErrorEvent, (event) => {
switch(parser.errorCode)
{
case -100002:
setDoorData(prevValue =>
{
const parser = event.getParser();
switch (parser.errorCode) {
case -100002: setDoorData((prevValue) => {
const newValue = { ...prevValue };
newValue.state = DoorStateType.STATE_WRONG_PASSWORD;
return newValue;
});
return;
case 4009:
simpleAlert(LocalizeText('navigator.alert.need.to.be.vip'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
simpleAlert( LocalizeText("navigator.alert.need.to.be.vip"), NotificationAlertType.DEFAULT, null, null, LocalizeText("generic.alert.title") );
return;
case 4010:
simpleAlert(LocalizeText('navigator.alert.invalid_room_name'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
simpleAlert( LocalizeText("navigator.alert.invalid_room_name"), NotificationAlertType.DEFAULT, null, null, LocalizeText("generic.alert.title") );
return;
case 4011:
simpleAlert(LocalizeText('navigator.alert.cannot_perm_ban'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
simpleAlert( LocalizeText("navigator.alert.cannot_perm_ban"), NotificationAlertType.DEFAULT, null, null, LocalizeText("generic.alert.title") );
return;
case 4013:
simpleAlert(LocalizeText('navigator.alert.room_in_maintenance'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
case 4013:
simpleAlert( LocalizeText("navigator.alert.room_in_maintenance"), NotificationAlertType.DEFAULT, null, null, LocalizeText("generic.alert.title") );
return;
}
});
useMessageEvent<NavigatorMetadataEvent>(NavigatorMetadataEvent, event =>
{
useMessageEvent<NavigatorMetadataEvent>(NavigatorMetadataEvent, (event) => {
const parser = event.getParser();
setTopLevelContexts(parser.topLevelContexts);
setTopLevelContext(parser.topLevelContexts.length ? parser.topLevelContexts[0] : null);
setTopLevelContext( parser.topLevelContexts.length ? parser.topLevelContexts[0] : null );
});
useMessageEvent<NavigatorSearchEvent>(NavigatorSearchEvent, event =>
{
useMessageEvent<NavigatorSearchEvent>(NavigatorSearchEvent, (event) => {
const parser = event.getParser();
setTopLevelContext(prevValue =>
{
setTopLevelContext((prevValue) => {
let newValue = prevValue;
if(!newValue) newValue = ((topLevelContexts && topLevelContexts.length && topLevelContexts[0]) || null);
if(!newValue) return null;
if((parser.result.code !== newValue.code) && topLevelContexts && topLevelContexts.length)
{
for(const context of topLevelContexts)
{
if(context.code !== parser.result.code) continue;
if (!newValue) newValue = (topLevelContexts && topLevelContexts.length && topLevelContexts[0]) || null;
if (!newValue) return null;
if ( parser.result.code !== newValue.code && topLevelContexts && topLevelContexts.length ) {
for (const context of topLevelContexts) {
if (context.code !== parser.result.code) continue;
newValue = context;
}
}
for(const context of topLevelContexts)
{
if(context.code !== parser.result.code) continue;
for (const context of topLevelContexts) {
if (context.code !== parser.result.code) continue;
newValue = context;
}
return newValue;
});
setSearchResult(parser.result);
setSearchResultQuery(parser.result.data);
});
useMessageEvent<UserFlatCatsEvent>(UserFlatCatsEvent, event =>
{
useMessageEvent<UserFlatCatsEvent>(UserFlatCatsEvent, (event) => {
const parser = event.getParser();
setCategories(parser.categories);
});
useMessageEvent<UserEventCatsEvent>(UserEventCatsEvent, event =>
{
useMessageEvent<UserEventCatsEvent>(UserEventCatsEvent, (event) => {
const parser = event.getParser();
setEventCategories(parser.categories);
});
useMessageEvent<FlatCreatedEvent>(FlatCreatedEvent, event =>
{
useMessageEvent<FlatCreatedEvent>(FlatCreatedEvent, (event) => {
const parser = event.getParser();
CreateRoomSession(parser.roomId);
});
useMessageEvent<NavigatorHomeRoomEvent>(NavigatorHomeRoomEvent, event =>
{
useMessageEvent<NavigatorHomeRoomEvent>(NavigatorHomeRoomEvent, (event) => {
const parser = event.getParser();
let prevSettingsReceived = false;
setNavigatorData(prevValue =>
{
setNavigatorData((prevValue) => {
prevSettingsReceived = prevValue.settingsReceived;
const newValue = { ...prevValue };
newValue.homeRoomId = parser.homeRoomId;
newValue.settingsReceived = true;
return newValue;
});
if(prevSettingsReceived)
{
if (prevSettingsReceived) {
// refresh room info window
return;
}
@ -375,68 +270,61 @@ const useNavigatorState = () =>
let forwardType = -1;
let forwardId = -1;
if((GetConfiguration<string>('friend.id') !== undefined) && (parseInt(GetConfiguration<string>('friend.id')) > 0))
{
if ( GetConfiguration<string>("friend.id") !== undefined && parseInt(GetConfiguration<string>("friend.id")) > 0) {
forwardType = 0;
SendMessageComposer(new FollowFriendMessageComposer(parseInt(GetConfiguration<string>('friend.id'))));
SendMessageComposer( new FollowFriendMessageComposer( parseInt(GetConfiguration<string>("friend.id"))) );
}
if((GetConfiguration<number>('forward.type') !== undefined) && (GetConfiguration<number>('forward.id') !== undefined))
{
forwardType = parseInt(GetConfiguration<string>('forward.type'));
forwardId = parseInt(GetConfiguration<string>('forward.id'))
if ( GetConfiguration<number>("forward.type") !== undefined && GetConfiguration<number>("forward.id") !== undefined ) {
forwardType = parseInt(GetConfiguration<string>("forward.type"));
forwardId = parseInt(GetConfiguration<string>("forward.id"));
}
if(forwardType === 2)
{
if (forwardType === 2) {
TryVisitRoom(forwardId);
}
} else if (forwardType === -1 && parser.roomIdToEnter > 0) {
CreateLinkEvent("navigator/close");
else if((forwardType === -1) && (parser.roomIdToEnter > 0))
{
CreateLinkEvent('navigator/close');
if(parser.roomIdToEnter !== parser.homeRoomId)
{
if (parser.roomIdToEnter !== parser.homeRoomId) {
CreateRoomSession(parser.roomIdToEnter);
}
else
{
CreateRoomSession(parser.homeRoomId);
}
} else { CreateRoomSession(parser.homeRoomId); }
}
});
useMessageEvent<RoomEnterErrorEvent>(RoomEnterErrorEvent, event =>
{
useMessageEvent<RoomEnterErrorEvent>(RoomEnterErrorEvent, (event) => {
const parser = event.getParser();
switch(parser.reason)
{
switch (parser.reason) {
case CantConnectMessageParser.REASON_FULL:
simpleAlert(LocalizeText('navigator.guestroomfull.text'), NotificationAlertType.DEFAULT, null, null, LocalizeText('navigator.guestroomfull.title'));
simpleAlert( LocalizeText("navigator.guestroomfull.text"), NotificationAlertType.DEFAULT, null, null, LocalizeText("navigator.guestroomfull.title") );
break;
case CantConnectMessageParser.REASON_QUEUE_ERROR:
simpleAlert(LocalizeText(`room.queue.error.${ parser.parameter }`), NotificationAlertType.DEFAULT, null, null, LocalizeText('room.queue.error.title'));
simpleAlert( LocalizeText(`room.queue.error.${parser.parameter}`), NotificationAlertType.DEFAULT, null, null, LocalizeText("room.queue.error.title") );
break;
case CantConnectMessageParser.REASON_BANNED:
simpleAlert(LocalizeText('navigator.banned.text'), NotificationAlertType.DEFAULT, null, null, LocalizeText('navigator.banned.title'));
simpleAlert( LocalizeText("navigator.banned.text"), NotificationAlertType.DEFAULT, null, null, LocalizeText("navigator.banned.title") );
break;
default:
simpleAlert(LocalizeText('room.queue.error.title'), NotificationAlertType.DEFAULT, null, null, LocalizeText('room.queue.error.title'));
default:
simpleAlert( LocalizeText("room.queue.error.title"), NotificationAlertType.DEFAULT, null, null, LocalizeText("room.queue.error.title") );
break;
}
VisitDesktop();
});
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);