diff --git a/public/configuration.json b/public/configuration.json index aa047b94..7debfc8a 100644 --- a/public/configuration.json +++ b/public/configuration.json @@ -53,7 +53,7 @@ "avatareditor.show.clubitems.first": true, "chat.history.max.items": 100, "animation.fps": 24, - "limits.fps": true, + "limits.fps": false, "system.dispatcher.log": false, "system.currency.types": [ -1, diff --git a/src/api/nitro/room/DispatchTouchEvent.ts b/src/api/nitro/room/DispatchTouchEvent.ts index 3da67fe4..8b6c7500 100644 --- a/src/api/nitro/room/DispatchTouchEvent.ts +++ b/src/api/nitro/room/DispatchTouchEvent.ts @@ -4,11 +4,14 @@ import { GetRoomEngine } from './GetRoomEngine'; let didMouseMove = false; let lastClick = 0; let clickCount = 0; +let touchTimer: ReturnType = null; -export function DispatchTouchEvent(roomId: number, canvasId: number, event: TouchEvent) +export function DispatchTouchEvent(roomId: number, canvasId: number, event: TouchEvent, longTouch: boolean = false, altKey: boolean = false, ctrlKey: boolean = false, shiftKey: boolean = false) { let eventType = event.type; + if(longTouch) eventType = TouchEventType.TOUCH_LONG; + if(eventType === TouchEventType.TOUCH_END && !didMouseMove) { eventType = MouseEventType.MOUSE_CLICK; @@ -17,7 +20,7 @@ export function DispatchTouchEvent(roomId: number, canvasId: number, event: Touc { clickCount = 1; - if(lastClick >= Date.now() - 300) clickCount++; + if(lastClick >= (Date.now() - 300)) clickCount++; } lastClick = Date.now(); @@ -31,24 +34,7 @@ export function DispatchTouchEvent(roomId: number, canvasId: number, event: Touc } } - switch(eventType) - { - case MouseEventType.MOUSE_CLICK: - break; - case MouseEventType.DOUBLE_CLICK: - break; - case TouchEventType.TOUCH_START: - eventType = MouseEventType.MOUSE_DOWN; - - didMouseMove = false; - break; - case TouchEventType.TOUCH_MOVE: - eventType = MouseEventType.MOUSE_MOVE; - - didMouseMove = true; - break; - default: return; - } + if(touchTimer) clearTimeout(touchTimer); let x = 0; let y = 0; @@ -66,5 +52,38 @@ export function DispatchTouchEvent(roomId: number, canvasId: number, event: Touc } GetRoomEngine().setActiveRoomId(roomId); - GetRoomEngine().dispatchMouseEvent(canvasId, x, y, eventType, event.altKey, (event.ctrlKey || event.metaKey), event.shiftKey, false); + + switch(eventType) + { + case MouseEventType.MOUSE_CLICK: + break; + case MouseEventType.DOUBLE_CLICK: + break; + case TouchEventType.TOUCH_START: + touchTimer = setTimeout(() => + { + if(didMouseMove) return; + + DispatchTouchEvent(roomId, canvasId, event, true); + }, 300); + + eventType = MouseEventType.MOUSE_DOWN; + + didMouseMove = false; + break; + case TouchEventType.TOUCH_MOVE: + eventType = MouseEventType.MOUSE_MOVE; + + didMouseMove = true; + break; + case TouchEventType.TOUCH_END: + eventType = MouseEventType.MOUSE_UP; + break; + case TouchEventType.TOUCH_LONG: + eventType = MouseEventType.MOUSE_DOWN_LONG; + break; + default: return; + } + + GetRoomEngine().dispatchMouseEvent(canvasId, x, y, eventType, altKey, ctrlKey, shiftKey, false); } diff --git a/src/assets/styles/utils.scss b/src/assets/styles/utils.scss index 880f0bfa..69ce07fc 100644 --- a/src/assets/styles/utils.scss +++ b/src/assets/styles/utils.scss @@ -32,10 +32,7 @@ ul { } .cursor-pointer { - - &:hover { - cursor: pointer; - } + cursor: pointer; } .pointer-events-none { diff --git a/src/events/catalog/CatalogEvent.ts b/src/events/catalog/CatalogEvent.ts index c65d95ca..b08ca399 100644 --- a/src/events/catalog/CatalogEvent.ts +++ b/src/events/catalog/CatalogEvent.ts @@ -10,4 +10,5 @@ export class CatalogEvent extends NitroEvent public static SOLD_OUT: string = 'CE_SOLD_OUT'; public static APPROVE_NAME_RESULT: string = 'CE_APPROVE_NAME_RESULT'; public static PURCHASE_APPROVED: string = 'CE_PURCHASE_APPROVED'; + public static CATALOG_RESET: string = 'CE_RESET'; } diff --git a/src/hooks/draggable-window/DraggableWindow.scss b/src/hooks/draggable-window/DraggableWindow.scss index db44bd4a..0679e33d 100644 --- a/src/hooks/draggable-window/DraggableWindow.scss +++ b/src/hooks/draggable-window/DraggableWindow.scss @@ -1,4 +1,5 @@ .draggable-window { + visibility: hidden; .drag-handler { cursor: move; diff --git a/src/hooks/draggable-window/DraggableWindow.tsx b/src/hooks/draggable-window/DraggableWindow.tsx index b4ab9b8f..511e5efb 100644 --- a/src/hooks/draggable-window/DraggableWindow.tsx +++ b/src/hooks/draggable-window/DraggableWindow.tsx @@ -62,6 +62,8 @@ export const DraggableWindow: FC = props => element.style.top = `${ top }px`; } + element.style.visibility = 'visible'; + return () => { const index = currentWindows.indexOf(element); diff --git a/src/hooks/events/event-dispatcher.base.tsx b/src/hooks/events/event-dispatcher.base.tsx index d0053f15..99214c16 100644 --- a/src/hooks/events/event-dispatcher.base.tsx +++ b/src/hooks/events/event-dispatcher.base.tsx @@ -1,24 +1,17 @@ import { IEventDispatcher, NitroEvent } from 'nitro-renderer'; -import { useEffect, useRef } from 'react'; +import { useEffect } from 'react'; export function CreateEventDispatcherHook(type: string, eventDispatcher: IEventDispatcher, handler: (event: NitroEvent) => void): void { - const handlerRef = useRef<(event: NitroEvent) => void>(); - useEffect(() => { - handlerRef.current = handler; - }, [ handler ]); - - useEffect(() => - { - eventDispatcher.addEventListener(type, handlerRef.current); + eventDispatcher.addEventListener(type, handler); return () => { - eventDispatcher.removeEventListener(type, handlerRef.current); + eventDispatcher.removeEventListener(type, handler); } - }, [ type, eventDispatcher ]); + }, [ type, eventDispatcher, handler ]); } export function DispatchEventHook(eventDispatcher: IEventDispatcher, event: NitroEvent): void diff --git a/src/layout/card/NitroCardView.scss b/src/layout/card/NitroCardView.scss index 6a82dd3a..0aa465e5 100644 --- a/src/layout/card/NitroCardView.scss +++ b/src/layout/card/NitroCardView.scss @@ -19,7 +19,7 @@ $nitro-card-top-height: $nitro-card-header-height + $nitro-card-tabs-height; @import './tabs/NitroCardTabsView'; } - @include media-breakpoint-down(md) { + @include media-breakpoint-down(lg) { .draggable-window { top: 0 !important; @@ -31,6 +31,7 @@ $nitro-card-top-height: $nitro-card-header-height + $nitro-card-tabs-height; .nitro-card { width: 100%; + height: 100%; &.rounded { border-radius: 0 !important; diff --git a/src/layout/card/content/NitroCardContentView.scss b/src/layout/card/content/NitroCardContentView.scss index a9e2c7c4..3b95c177 100644 --- a/src/layout/card/content/NitroCardContentView.scss +++ b/src/layout/card/content/NitroCardContentView.scss @@ -3,7 +3,7 @@ padding-bottom: $container-padding-x; } -@include media-breakpoint-down(md) { +@include media-breakpoint-down(lg) { .content-area { height: 100% !important; diff --git a/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.tsx b/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.tsx index 3cc532a2..43595ae0 100644 --- a/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.tsx +++ b/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.tsx @@ -4,11 +4,11 @@ import { NitroCardTabsItemViewProps } from './NitroCardTabsItemView.types'; export const NitroCardTabsItemView: FC = props => { - const { tabText = '', isActive = false, onClick = null } = props; + const { children = null, isActive = false, onClick = null } = props; return (
  • - { tabText } + { children }
  • ); } diff --git a/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.types.ts b/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.types.ts index 94debcd4..4da57987 100644 --- a/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.types.ts +++ b/src/layout/card/tabs/tabs-item/NitroCardTabsItemView.types.ts @@ -2,7 +2,6 @@ import { MouseEventHandler } from 'react'; export interface NitroCardTabsItemViewProps { - tabText?: string; isActive?: boolean; onClick?: MouseEventHandler; } diff --git a/src/layout/scrollable-area/ScrollableAreaView.tsx b/src/layout/scrollable-area/ScrollableAreaView.tsx new file mode 100644 index 00000000..916cf293 --- /dev/null +++ b/src/layout/scrollable-area/ScrollableAreaView.tsx @@ -0,0 +1,32 @@ +import { FC, useCallback, useEffect, useRef, useState } from 'react'; +import { ScrollableAreaViewProps } from './ScrollableAreaView.types'; + +export const ScrollableAreaView: FC = props => +{ + const { className = null, children = null } = props; + const [ height, setHeight ] = useState(0); + const elementRef = useRef(); + + const resize = useCallback(() => + { + setHeight(elementRef.current.parentElement.clientHeight); + }, [ elementRef ]); + + useEffect(() => + { + resize(); + + window.addEventListener('resize', resize); + + return () => + { + window.removeEventListener('resize', resize); + } + }, [ resize ]); + + return ( +
    + { children } +
    + ); +} diff --git a/src/layout/scrollable-area/ScrollableAreaView.types.ts b/src/layout/scrollable-area/ScrollableAreaView.types.ts new file mode 100644 index 00000000..3494e60b --- /dev/null +++ b/src/layout/scrollable-area/ScrollableAreaView.types.ts @@ -0,0 +1,4 @@ +export interface ScrollableAreaViewProps +{ + className?: string; +} diff --git a/src/utils/Styles.scss b/src/utils/Styles.scss index 4275e6c6..e69de29b 100644 --- a/src/utils/Styles.scss +++ b/src/utils/Styles.scss @@ -1 +0,0 @@ -@import './currency-icon/CurrencyIcon.scss'; diff --git a/src/views/Styles.scss b/src/views/Styles.scss index 6d270b8f..55c9058d 100644 --- a/src/views/Styles.scss +++ b/src/views/Styles.scss @@ -3,6 +3,7 @@ @import './badge-image/BadgeImage'; @import './catalog/CatalogView'; @import './catalog-icon/CatalogIconView'; +@import './currency-icon/CurrencyIcon'; @import './friend-list/FriendListView'; @import './furni-image/FurniImageView'; @import './hotel-view/HotelView'; diff --git a/src/views/catalog/CatalogMessageHandler.tsx b/src/views/catalog/CatalogMessageHandler.tsx index b34357d3..c3825e3b 100644 --- a/src/views/catalog/CatalogMessageHandler.tsx +++ b/src/views/catalog/CatalogMessageHandler.tsx @@ -1,4 +1,4 @@ -import { CatalogApproveNameResultEvent, CatalogClubEvent, CatalogPageEvent, CatalogPagesEvent, CatalogPurchaseEvent, CatalogPurchaseFailedEvent, CatalogPurchaseUnavailableEvent, CatalogSearchEvent, CatalogSoldOutEvent, SellablePetPalettesEvent } from 'nitro-renderer'; +import { CatalogApproveNameResultEvent, CatalogClubEvent, CatalogPageEvent, CatalogPagesEvent, CatalogPurchaseEvent, CatalogPurchaseFailedEvent, CatalogPurchaseUnavailableEvent, CatalogSearchEvent, CatalogSoldOutEvent, CatalogUpdatedEvent, SellablePetPalettesEvent, UserSubscriptionEvent } from 'nitro-renderer'; import { FC, useCallback } from 'react'; import { CatalogNameResultEvent, CatalogPurchaseFailureEvent } from '../../events'; import { CatalogPurchasedEvent } from '../../events/catalog/CatalogPurchasedEvent'; @@ -9,6 +9,7 @@ import { CatalogMessageHandlerProps } from './CatalogMessageHandler.types'; import { useCatalogContext } from './context/CatalogContext'; import { CatalogActions } from './reducers/CatalogReducer'; import { CatalogPetPalette } from './utils/CatalogPetPalette'; +import { SubscriptionInfo } from './utils/SubscriptionInfo'; export const CatalogMessageHandler: FC = props => { @@ -106,6 +107,32 @@ export const CatalogMessageHandler: FC = props => }); }, [ dispatchCatalogState ]); + const onUserSubscriptionEvent = useCallback((event: UserSubscriptionEvent) => + { + const parser = event.getParser(); + + dispatchCatalogState({ + type: CatalogActions.SET_SUBSCRIPTION_INFO, + payload: { + subscriptionInfo: new SubscriptionInfo( + Math.max(0, parser.days), + Math.max(0, parser.months), + parser.isVip, + parser.pastClubDays, + parser.pastVIPDays + ) + } + }); + }, [ dispatchCatalogState ]); + + const onCatalogUpdatedEvent = useCallback((event: CatalogUpdatedEvent) => + { + dispatchCatalogState({ + type: CatalogActions.RESET_STATE, + payload: {} + }); + }, [ dispatchCatalogState ]); + CreateMessageHook(CatalogPagesEvent, onCatalogPagesEvent); CreateMessageHook(CatalogPageEvent, onCatalogPageEvent); CreateMessageHook(CatalogPurchaseEvent, onCatalogPurchaseEvent); @@ -116,6 +143,8 @@ export const CatalogMessageHandler: FC = props => CreateMessageHook(SellablePetPalettesEvent, onSellablePetPalettesEvent); CreateMessageHook(CatalogApproveNameResultEvent, onCatalogApproveNameResultEvent); CreateMessageHook(CatalogClubEvent, onCatalogClubEvent); + CreateMessageHook(UserSubscriptionEvent, onUserSubscriptionEvent); + CreateMessageHook(CatalogUpdatedEvent, onCatalogUpdatedEvent); return null; } diff --git a/src/views/catalog/CatalogView.tsx b/src/views/catalog/CatalogView.tsx index 0564ad91..53f3cf98 100644 --- a/src/views/catalog/CatalogView.tsx +++ b/src/views/catalog/CatalogView.tsx @@ -1,6 +1,7 @@ import { CatalogModeComposer, ICatalogPageData, RoomPreviewer } from 'nitro-renderer'; import { FC, useCallback, useEffect, useReducer, useState } from 'react'; import { GetRoomEngine } from '../../api'; +import { GetCatalogPageComposer } from '../../api/catalog/GetCatalogPageComposer'; import { CatalogEvent } from '../../events'; import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../hooks/messages/message-event'; @@ -12,14 +13,13 @@ import { CatalogContextProvider } from './context/CatalogContext'; import { CatalogActions, CatalogReducer, initialCatalog } from './reducers/CatalogReducer'; import { CatalogNavigationView } from './views/navigation/CatalogNavigationView'; import { CatalogPageView } from './views/page/CatalogPageView'; -import { CatalogSearchView } from './views/search/CatalogSearchView'; export const CatalogView: FC = props => { const [ isVisible, setIsVisible ] = useState(false); const [ roomPreviewer, setRoomPreviewer ] = useState(null); const [ catalogState, dispatchCatalogState ] = useReducer(CatalogReducer, initialCatalog); - const { root = null, currentTab = null, activeOffer = null, searchResult = null } = catalogState; + const { root = null, currentTab = null, pageParser = null, activeOffer = null, searchResult = null } = catalogState; const onCatalogEvent = useCallback((event: CatalogEvent) => { @@ -40,6 +40,7 @@ export const CatalogView: FC = props => useUiEvent(CatalogEvent.SHOW_CATALOG, onCatalogEvent); useUiEvent(CatalogEvent.HIDE_CATALOG, onCatalogEvent); useUiEvent(CatalogEvent.TOGGLE_CATALOG, onCatalogEvent); + useUiEvent(CatalogEvent.CATALOG_RESET, onCatalogEvent); useEffect(() => { @@ -51,6 +52,13 @@ export const CatalogView: FC = props => } }, [ isVisible, catalogState.root ]); + useEffect(() => + { + if(!currentTab) return; + + SendMessageHook(GetCatalogPageComposer(currentTab.pageId, -1, CatalogMode.MODE_NORMAL)); + }, [ currentTab ]); + useEffect(() => { setRoomPreviewer(new RoomPreviewer(GetRoomEngine(), ++RoomPreviewer.PREVIEW_COUNTER)); @@ -66,7 +74,7 @@ export const CatalogView: FC = props => } }, []); - function setCurrentTab(page: ICatalogPageData): void + const setCurrentTab = useCallback((page: ICatalogPageData) => { dispatchCatalogState({ type: CatalogActions.SET_CATALOG_CURRENT_TAB, @@ -74,28 +82,32 @@ export const CatalogView: FC = props => currentTab: page } }); - } + }, [ dispatchCatalogState ]); const currentNavigationPage = ((searchResult && searchResult.page) || currentTab); return ( - + { isVisible && setIsVisible(false) } /> { root && root.children.length && root.children.map((page, index) => { - return setCurrentTab(page) } /> + return ( + setCurrentTab(page) }> + { page.localization } + + ); }) }
    -
    - - -
    + { pageParser && !pageParser.frontPageItems.length && +
    + +
    }
    diff --git a/src/views/catalog/reducers/CatalogReducer.tsx b/src/views/catalog/reducers/CatalogReducer.tsx index 1a7caca4..8d8c2cd9 100644 --- a/src/views/catalog/reducers/CatalogReducer.tsx +++ b/src/views/catalog/reducers/CatalogReducer.tsx @@ -2,17 +2,20 @@ import { CatalogClubOfferData, CatalogPageOfferData, ICatalogPageData, ICatalogP import { Reducer } from 'react'; import { CatalogPetPalette } from '../utils/CatalogPetPalette'; import { ICatalogOffers, ICatalogSearchResult, SetOffersToNodes } from '../utils/CatalogUtilities'; +import { SubscriptionInfo } from '../utils/SubscriptionInfo'; export interface ICatalogState { root: ICatalogPageData; offerRoot: ICatalogOffers; currentTab: ICatalogPageData; + currentPage: ICatalogPageData; pageParser: ICatalogPageParser; activeOffer: CatalogPageOfferData; searchResult: ICatalogSearchResult; petPalettes: CatalogPetPalette[]; clubOffers: CatalogClubOfferData[]; + subscriptionInfo: SubscriptionInfo; } export interface ICatalogAction @@ -22,11 +25,13 @@ export interface ICatalogAction root?: ICatalogPageData; offerRoot?: ICatalogOffers; currentTab?: ICatalogPageData; + currentPage?: ICatalogPageData; pageParser?: ICatalogPageParser; activeOffer?: CatalogPageOfferData; searchResult?: ICatalogSearchResult; petPalette?: CatalogPetPalette; clubOffers?: CatalogClubOfferData[]; + subscriptionInfo?: SubscriptionInfo; } } @@ -34,22 +39,27 @@ export class CatalogActions { public static SET_CATALOG_ROOT: string = 'CA_SET_CATALOG_ROOT'; public static SET_CATALOG_CURRENT_TAB: string = 'CA_SET_CATALOG_CURRENT_TAB'; + public static SET_CATALOG_CURRENT_PAGE: string = 'CA_SET_CATALOG_CURRENT_PAGE'; public static SET_CATALOG_PAGE_PARSER: string = 'CA_SET_CATALOG_PAGE'; public static SET_CATALOG_ACTIVE_OFFER: string = 'CA_SET_ACTIVE_OFFER'; public static SET_SEARCH_RESULT: string = 'CA_SET_SEARCH_RESULT'; public static SET_PET_PALETTE: string = 'CA_SET_PET_PALETTE'; public static SET_CLUB_OFFERS: string = 'CA_SET_CLUB_OFFERS'; + public static SET_SUBSCRIPTION_INFO: string = 'CA_SET_SUBSCRIPTION_INFO'; + public static RESET_STATE = 'CA_RESET_STATE'; } export const initialCatalog: ICatalogState = { root: null, offerRoot: null, currentTab: null, + currentPage: null, pageParser: null, activeOffer: null, searchResult: null, petPalettes: [], - clubOffers: null + clubOffers: null, + subscriptionInfo: new SubscriptionInfo() } export const CatalogReducer: Reducer = (state, action) => @@ -72,8 +82,13 @@ export const CatalogReducer: Reducer = (state, ac return { ...state, currentTab, searchResult }; } + case CatalogActions.SET_CATALOG_CURRENT_PAGE: { + const currentPage = (action.payload.currentPage || state.currentPage || null); + + return { ...state, currentPage }; + } case CatalogActions.SET_CATALOG_PAGE_PARSER: { - let pageParser = Object.create(action.payload.pageParser); + let pageParser = (Object.create(action.payload.pageParser) as ICatalogPageParser); let activeOffer = null; if(pageParser.layoutCode === 'single_bundle') @@ -126,6 +141,14 @@ export const CatalogReducer: Reducer = (state, ac return { ...state, clubOffers }; } + case CatalogActions.SET_SUBSCRIPTION_INFO: { + const subscriptionInfo = (action.payload.subscriptionInfo || null); + + return { ...state, subscriptionInfo }; + } + case CatalogActions.RESET_STATE: { + return { ...initialCatalog }; + } default: return state; } diff --git a/src/views/catalog/utils/IPurse.ts b/src/views/catalog/utils/IPurse.ts new file mode 100644 index 00000000..bd365ba6 --- /dev/null +++ b/src/views/catalog/utils/IPurse.ts @@ -0,0 +1,14 @@ +export interface IPurse +{ + _Str_14389: boolean; + _Str_4458: number; + credits: number; + clubDays: number; + clubPeriods: number; + _Str_13571: boolean; + _Str_3738: boolean; + _Str_6288: number; + _Str_4605: number; + _Str_6312: number; + _Str_5590(_arg_1: number): number; +} diff --git a/src/views/catalog/utils/Purse.ts b/src/views/catalog/utils/Purse.ts new file mode 100644 index 00000000..a044cd05 --- /dev/null +++ b/src/views/catalog/utils/Purse.ts @@ -0,0 +1,144 @@ +import { Nitro } from 'nitro-renderer'; +import { IPurse } from './IPurse'; + +export class Purse implements IPurse +{ + private _credits: number = 0; + private _activityPoints: Map; + private _clubDays: number = 0; + private _clubPeriods: number = 0; + private _isVIP: boolean = false; + private _pastClubDays: number = 0; + private _pastVipDays: number = 0; + private _isExpiring: boolean = false; + private _minutesUntilExpiration: number = 0; + private _minutesSinceLastModified: number; + private _lastUpdated: number; + + public get credits(): number + { + return this._credits; + } + + public set credits(k: number) + { + this._lastUpdated = Nitro.instance.time; + this._credits = k; + } + + public get clubDays(): number + { + return this._clubDays; + } + + public set clubDays(k: number) + { + this._lastUpdated = Nitro.instance.time; + this._clubDays = k; + } + + public get clubPeriods(): number + { + return this._clubPeriods; + } + + public set clubPeriods(k: number) + { + this._lastUpdated = Nitro.instance.time; + this._clubPeriods = k; + } + + public get _Str_13571(): boolean + { + return (this._clubDays > 0) || (this._clubPeriods > 0); + } + + public get _Str_3738(): boolean + { + return this._isVIP; + } + + public get _Str_14389(): boolean + { + return this._isExpiring; + } + + public set _Str_14389(k: boolean) + { + this._isExpiring = k; + } + + public set _Str_3738(k: boolean) + { + this._isVIP = k; + } + + public get _Str_6288(): number + { + return this._pastClubDays; + } + + public set _Str_6288(k: number) + { + this._lastUpdated = Nitro.instance.time; + this._pastClubDays = k; + } + + public get _Str_4605(): number + { + return this._pastVipDays; + } + + public set _Str_4605(k: number) + { + this._lastUpdated = Nitro.instance.time; + this._pastVipDays = k; + } + + public get _Str_18527(): Map + { + return this._activityPoints; + } + + public set _Str_18527(k: Map) + { + this._lastUpdated = Nitro.instance.time; + this._activityPoints = k; + } + + public _Str_5590(k: number): number + { + return this._activityPoints[k]; + } + + public set _Str_4458(k: number) + { + this._lastUpdated = Nitro.instance.time; + + this._minutesUntilExpiration = k; + } + + public get _Str_4458(): number + { + const k = ((Nitro.instance.time - this._lastUpdated) / (1000 * 60)); + const _local_2 = (this._minutesUntilExpiration - k); + + return (_local_2 > 0) ? _local_2 : 0; + } + + public set _Str_6312(k: number) + { + this._lastUpdated = Nitro.instance.time; + this._minutesSinceLastModified = k; + } + + public get _Str_6312(): number + { + return this._minutesSinceLastModified; + } + + public get _Str_26225(): number + { + return this._lastUpdated; + } +} diff --git a/src/views/catalog/utils/SubscriptionInfo.ts b/src/views/catalog/utils/SubscriptionInfo.ts new file mode 100644 index 00000000..36f87abf --- /dev/null +++ b/src/views/catalog/utils/SubscriptionInfo.ts @@ -0,0 +1,17 @@ + +export class SubscriptionInfo +{ + private _lastUpdated: number; + + constructor( + public clubDays: number = 0, + public clubPeriods: number = 0, + public isVip: boolean = false, + public pastDays: number = 0, + public pastVipDays: number = 0) {} + + public get lastUpdated(): number + { + return this._lastUpdated; + } +} diff --git a/src/views/catalog/views/navigation/CatalogNavigationView.tsx b/src/views/catalog/views/navigation/CatalogNavigationView.tsx index 7d666952..5fc30357 100644 --- a/src/views/catalog/views/navigation/CatalogNavigationView.tsx +++ b/src/views/catalog/views/navigation/CatalogNavigationView.tsx @@ -1,5 +1,6 @@ import { ICatalogPageData } from 'nitro-renderer'; import { FC, useEffect } from 'react'; +import { CatalogSearchView } from '../search/CatalogSearchView'; import { CatalogNavigationViewProps } from './CatalogNavigationView.types'; import { CatalogNavigationSetView } from './set/CatalogNavigationSetView'; @@ -17,10 +18,13 @@ export const CatalogNavigationView: FC = props => }, [ page ]); return ( -
    -
    - + <> + +
    +
    + +
    -
    + ); } diff --git a/src/views/catalog/views/navigation/set/CatalogNavigationSetView.tsx b/src/views/catalog/views/navigation/set/CatalogNavigationSetView.tsx index 0acdd03e..32a8ec30 100644 --- a/src/views/catalog/views/navigation/set/CatalogNavigationSetView.tsx +++ b/src/views/catalog/views/navigation/set/CatalogNavigationSetView.tsx @@ -13,7 +13,12 @@ export const CatalogNavigationSetView: FC = props { if(!isFirstSet || !page || (page.pageId === -1)) return; - if(page && page.children.length) setActiveChild(page.children[0]); + if(page && page.children.length) + { + const child = page.children[0]; + + setActiveChild(child); + } }, [ page, isFirstSet ]); useEffect(() => diff --git a/src/views/catalog/views/page/CatalogPageView.scss b/src/views/catalog/views/page/CatalogPageView.scss index 7a00d29e..8707eda9 100644 --- a/src/views/catalog/views/page/CatalogPageView.scss +++ b/src/views/catalog/views/page/CatalogPageView.scss @@ -1,3 +1,4 @@ +@import './header/CatalogPageHeaderView'; @import './layout/CatalogLayout'; @import './offer/CatalogPageOfferView'; @import './offers/CatalogPageOffersView'; diff --git a/src/views/catalog/views/page/header/CatalogPageHeaderView.scss b/src/views/catalog/views/page/header/CatalogPageHeaderView.scss new file mode 100644 index 00000000..715ece65 --- /dev/null +++ b/src/views/catalog/views/page/header/CatalogPageHeaderView.scss @@ -0,0 +1,3 @@ +.nitro-catalog-page-header { + padding-top: $container-padding-x; +} diff --git a/src/views/catalog/views/page/header/CatalogPageHeaderView.tsx b/src/views/catalog/views/page/header/CatalogPageHeaderView.tsx new file mode 100644 index 00000000..e820357d --- /dev/null +++ b/src/views/catalog/views/page/header/CatalogPageHeaderView.tsx @@ -0,0 +1,28 @@ +import { FC } from 'react'; +import { CatalogIconView } from '../../../../catalog-icon/CatalogIconView'; +import { useCatalogContext } from '../../../context/CatalogContext'; +import { CatalogPageHeaderViewProps } from './CatalogPageHeaderView.types'; + +export const CatalogPageHeaderView: FC = props => +{ + const { catalogState = null } = useCatalogContext(); + const { currentPage = null, pageParser = null } = catalogState; + + return ( +
    +
    +
    + +
    +
    +
    + { currentPage.localization } +
    + { pageParser &&
    + { pageParser.localization.texts[0] } +
    } +
    +
    +
    + ); +} diff --git a/src/views/catalog/views/page/header/CatalogPageHeaderView.types.ts b/src/views/catalog/views/page/header/CatalogPageHeaderView.types.ts new file mode 100644 index 00000000..d98531eb --- /dev/null +++ b/src/views/catalog/views/page/header/CatalogPageHeaderView.types.ts @@ -0,0 +1,6 @@ +import { ICatalogPageParser } from 'nitro-renderer'; + +export interface CatalogPageHeaderViewProps +{ + pageParser: ICatalogPageParser; +} diff --git a/src/views/catalog/views/page/layout/CatalogLayout.scss b/src/views/catalog/views/page/layout/CatalogLayout.scss index e3ac0191..768a4b81 100644 --- a/src/views/catalog/views/page/layout/CatalogLayout.scss +++ b/src/views/catalog/views/page/layout/CatalogLayout.scss @@ -1,5 +1,7 @@ @import './default/CatalogLayoutDefaultView'; +@import './frontpage4/CatalogLayoutFrontpage4View'; @import './pets/CatalogLayoutPetView'; +@import './pets3/CatalogLayoutPets3View'; @import './single-bundle/CatalogLayoutSingleBundleView'; @import './spaces-new/CatalogLayoutSpacesView'; @import './trophies/CatalogLayoutTrophiesView'; diff --git a/src/views/catalog/views/page/layout/GetCatalogLayout.tsx b/src/views/catalog/views/page/layout/GetCatalogLayout.tsx index 15d5050f..35d9a507 100644 --- a/src/views/catalog/views/page/layout/GetCatalogLayout.tsx +++ b/src/views/catalog/views/page/layout/GetCatalogLayout.tsx @@ -1,6 +1,8 @@ import { ICatalogPageParser, RoomPreviewer } from 'nitro-renderer'; import { CatalogLayoutDefaultView } from './default/CatalogLayoutDefaultView'; +import { CatalogLayoutFrontpage4View } from './frontpage4/CatalogLayoutFrontpage4View'; import { CatalogLayoutPetView } from './pets/CatalogLayoutPetView'; +import { CatalogLayoutPets3View } from './pets3/CatalogLayoutPets3View'; import { CatalogLayoutSingleBundleView } from './single-bundle/CatalogLayoutSingleBundleView'; import { CatalogLayoutSpacesView } from './spaces-new/CatalogLayoutSpacesView'; import { CatalogLayoutTrophiesView } from './trophies/CatalogLayoutTrophiesView'; @@ -13,13 +15,13 @@ export function GetCatalogLayout(pageParser: ICatalogPageParser, roomPreviewer: case 'frontpage_featured': return null; case 'frontpage4': - return null; + return ; case 'pets': return ; case 'pets2': return null; case 'pets3': - return null; + return ; case 'vip_buy': return ; case 'guild_frontpage': diff --git a/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.scss b/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.scss new file mode 100644 index 00000000..26906368 --- /dev/null +++ b/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.scss @@ -0,0 +1,22 @@ +.nitro-catalog-layout-frontpage4 { + + .front-page-item { + position: relative; + border-radius: $border-radius; + background-position: center; + background-repeat: no-repeat; + cursor: pointer; + + .front-page-item-caption { + position: absolute; + background: rgba(0, 0, 0, .5); + color: #fff; + font-size: 16px; + border-radius: 5px; + margin: 10px; + padding: 5px 15px; + bottom: 0; + text-shadow: 2px 2px rgba(0, 0, 0, .2); + } + } +} diff --git a/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.tsx b/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.tsx new file mode 100644 index 00000000..2103c104 --- /dev/null +++ b/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.tsx @@ -0,0 +1,59 @@ +import { FC, useCallback, useMemo } from 'react'; +import { GetConfiguration } from '../../../../../../utils/GetConfiguration'; +import { CatalogLayoutFrontpage4ViewProps } from './CatalogLayoutFrontpage4View.types'; + +export const CatalogLayoutFrontpage4View: FC = props => +{ + const { pageParser = null } = props; + + const getFrontPageItem = useCallback((position: number) => + { + for(const item of pageParser.frontPageItems) + { + if(item.position !== position) continue; + + return item; + } + }, [ pageParser ]); + + const getFrontPageItemImage = useCallback((position: number) => + { + const item = getFrontPageItem(position); + + if(!item) return null; + + return item.itemPromoImage; + }, [ getFrontPageItem ]); + + const imageLibraryUrl = useMemo(() => + { + return GetConfiguration('image.library.url'); + }, []); + + if(!pageParser) return null; + + return ( +
    +
    + { pageParser.frontPageItems[0] && +
    +
    { pageParser.frontPageItems[0].itemName }
    +
    } +
    +
    + { pageParser.frontPageItems[1] && +
    +
    { pageParser.frontPageItems[1].itemName }
    +
    } + { pageParser.frontPageItems[2] && +
    +
    { pageParser.frontPageItems[2].itemName }
    +
    } + { pageParser.frontPageItems[3] && +
    +
    { pageParser.frontPageItems[3].itemName }
    +
    } +
    +
    + ); +} diff --git a/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.types.ts b/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.types.ts new file mode 100644 index 00000000..292e4989 --- /dev/null +++ b/src/views/catalog/views/page/layout/frontpage4/CatalogLayoutFrontpage4View.types.ts @@ -0,0 +1,6 @@ +import { CatalogLayoutProps } from '../CatalogLayout.types'; + +export interface CatalogLayoutFrontpage4ViewProps extends CatalogLayoutProps +{ + +} diff --git a/src/views/catalog/views/page/layout/pets/CatalogLayoutPetView.tsx b/src/views/catalog/views/page/layout/pets/CatalogLayoutPetView.tsx index 40df3770..1b44e5c5 100644 --- a/src/views/catalog/views/page/layout/pets/CatalogLayoutPetView.tsx +++ b/src/views/catalog/views/page/layout/pets/CatalogLayoutPetView.tsx @@ -7,7 +7,7 @@ import { PetImageView } from '../../../../../pet-image/PetImageView'; import { RoomPreviewerView } from '../../../../../room-previewer/RoomPreviewerView'; import { useCatalogContext } from '../../../../context/CatalogContext'; import { CatalogActions } from '../../../../reducers/CatalogReducer'; -import { GetPetAvailableColors, GetPetIndexFromLocalization } from '../../../../utils/CatalogUtilities'; +import { GetCatalogPageImage, GetCatalogPageText, GetPetAvailableColors, GetPetIndexFromLocalization } from '../../../../utils/CatalogUtilities'; import { CatalogLayoutPetViewProps } from './CatalogLayoutPetView.types'; import { CatalogLayoutPetPurchaseView } from './purchase/CatalogLayoutPetPurchaseView'; @@ -160,16 +160,24 @@ export const CatalogLayoutPetView: FC = props => }) }
    -
    - - { (petIndex > -1 && petIndex <= 7) && - } - -
    { petBreedName }
    - -
    + { (petIndex === -1) && +
    +
    + +
    +
    { GetCatalogPageText(pageParser, 0) }
    +
    } + { (petIndex >= 0) && +
    + + { (petIndex > -1 && petIndex <= 7) && + } + +
    { petBreedName }
    + +
    } ); } diff --git a/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx b/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx index a6ceab62..5ddb232c 100644 --- a/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx +++ b/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx @@ -3,8 +3,8 @@ import { FC, useCallback, useState } from 'react'; import { CatalogEvent } from '../../../../../../../events'; import { useUiEvent } from '../../../../../../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../../../../../../hooks/messages/message-event'; -import { CurrencyIcon } from '../../../../../../../utils/currency-icon/CurrencyIcon'; import { LocalizeText } from '../../../../../../../utils/LocalizeText'; +import { CurrencyIcon } from '../../../../../../currency-icon/CurrencyIcon'; import { CatalogPurchaseButtonView } from '../../../purchase/purchase-button/CatalogPurchaseButtonView'; import { CatalogPetNameApprovalView } from '../name-approval/CatalogPetNameApprovalView'; import { CatalogLayoutPetPurchaseViewProps } from './CatalogLayoutPetPurchaseView.types'; diff --git a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.scss b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.scss new file mode 100644 index 00000000..2f2bc31c --- /dev/null +++ b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.scss @@ -0,0 +1,2 @@ +.nitro-catalog-layout-pets3 { +} diff --git a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx new file mode 100644 index 00000000..cc065c60 --- /dev/null +++ b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx @@ -0,0 +1,24 @@ +import { FC } from 'react'; +import { GetCatalogPageImage, GetCatalogPageText } from '../../../../utils/CatalogUtilities'; +import { CatalogLayoutPets3ViewProps } from './CatalogLayoutPets3View.types'; + +export const CatalogLayoutPets3View: FC = props => +{ + const { pageParser = null } = props; + + return ( +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    { GetCatalogPageText(pageParser, 0) }
    +
    +
    + ); +} diff --git a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.types.ts b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.types.ts new file mode 100644 index 00000000..7575e8f5 --- /dev/null +++ b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.types.ts @@ -0,0 +1,6 @@ +import { CatalogLayoutProps } from '../CatalogLayout.types'; + +export interface CatalogLayoutPets3ViewProps extends CatalogLayoutProps +{ + +} diff --git a/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx b/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx index 2538312f..6666bcac 100644 --- a/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx +++ b/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx @@ -5,7 +5,7 @@ import { LocalizeText } from '../../../../../../utils/LocalizeText'; import { RoomPreviewerView } from '../../../../../room-previewer/RoomPreviewerView'; import { useCatalogContext } from '../../../../context/CatalogContext'; import { ProductTypeEnum } from '../../../../enums/ProductTypeEnum'; -import { GetOfferName } from '../../../../utils/CatalogUtilities'; +import { GetCatalogPageImage, GetCatalogPageText, GetOfferName } from '../../../../utils/CatalogUtilities'; import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; import { CatalogPurchaseView } from '../../purchase/CatalogPurchaseView'; import { CatalogLayoutSpacesViewProps } from './CatalogLayoutSpacesView.types'; @@ -81,6 +81,13 @@ export const CatalogLayoutSpacesView: FC = props =
    + { !product && +
    +
    + +
    +
    { GetCatalogPageText(pageParser, 0) }
    +
    } { product &&
    diff --git a/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx b/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx index 9f59569d..1f10b035 100644 --- a/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx +++ b/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx @@ -1,16 +1,16 @@ import { CatalogClubOfferData, CatalogRequestVipOffersComposer } from 'nitro-renderer'; -import { FC, useCallback, useEffect } from 'react'; +import { FC, useCallback, useEffect, useMemo } from 'react'; import { SendMessageHook } from '../../../../../../hooks/messages/message-event'; -import { CurrencyIcon } from '../../../../../../utils/currency-icon/CurrencyIcon'; import { LocalizeText } from '../../../../../../utils/LocalizeText'; +import { CurrencyIcon } from '../../../../../currency-icon/CurrencyIcon'; import { useCatalogContext } from '../../../../context/CatalogContext'; -import { GetCatalogPageImage, GetCatalogPageText } from '../../../../utils/CatalogUtilities'; +import { GetCatalogPageImage } from '../../../../utils/CatalogUtilities'; import { CatalogLayoutVipBuyViewProps } from './CatalogLayoutVipBuyView.types'; export const CatalogLayoutVipBuyView: FC = props => { const { catalogState = null } = useCatalogContext(); - const { pageParser = null, clubOffers = null } = catalogState; + const { pageParser = null, clubOffers = null, subscriptionInfo = null } = catalogState; useEffect(() => { @@ -41,6 +41,17 @@ export const CatalogLayoutVipBuyView: FC = props = return offerText; }, []); + const getSubscriptionDetails = useMemo(() => + { + if(!subscriptionInfo) return ''; + + const clubDays = subscriptionInfo.clubDays; + const clubPeriods = subscriptionInfo.clubPeriods; + const totalDays = (clubPeriods * 31) + clubDays; + + return LocalizeText('catalog.vip.extend.info', [ 'days' ], [ totalDays.toString() ]); + }, [ subscriptionInfo ]); + return (
    @@ -74,7 +85,7 @@ export const CatalogLayoutVipBuyView: FC = props =
    -
    { GetCatalogPageText(pageParser, 0) }
    +
    ); diff --git a/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx b/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx index 19fc4115..986e31e9 100644 --- a/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx +++ b/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx @@ -1,6 +1,6 @@ import { FC, useEffect, useState } from 'react'; -import { CurrencyIcon } from '../../../../../utils/currency-icon/CurrencyIcon'; import { LocalizeText } from '../../../../../utils/LocalizeText'; +import { CurrencyIcon } from '../../../../currency-icon/CurrencyIcon'; import { CatalogPurchaseViewProps } from './CatalogPurchaseView.types'; import { CatalogPurchaseButtonView } from './purchase-button/CatalogPurchaseButtonView'; diff --git a/src/utils/currency-icon/CurrencyIcon.scss b/src/views/currency-icon/CurrencyIcon.scss similarity index 100% rename from src/utils/currency-icon/CurrencyIcon.scss rename to src/views/currency-icon/CurrencyIcon.scss diff --git a/src/utils/currency-icon/CurrencyIcon.tsx b/src/views/currency-icon/CurrencyIcon.tsx similarity index 69% rename from src/utils/currency-icon/CurrencyIcon.tsx rename to src/views/currency-icon/CurrencyIcon.tsx index 14ee66b3..14f78e76 100644 --- a/src/utils/currency-icon/CurrencyIcon.tsx +++ b/src/views/currency-icon/CurrencyIcon.tsx @@ -1,7 +1,8 @@ -import { GetConfiguration } from '../GetConfiguration'; +import { FC } from 'react'; +import { GetConfiguration } from '../../utils/GetConfiguration'; import { CurrencyIconProps } from './CurrencyIcon.types'; -export function CurrencyIcon(props: CurrencyIconProps): JSX.Element +export const CurrencyIcon: FC = props => { let url = GetConfiguration('currency.asset.icon.url', ''); diff --git a/src/utils/currency-icon/CurrencyIcon.types.ts b/src/views/currency-icon/CurrencyIcon.types.ts similarity index 100% rename from src/utils/currency-icon/CurrencyIcon.types.ts rename to src/views/currency-icon/CurrencyIcon.types.ts diff --git a/src/views/hotel-view/HotelView.scss b/src/views/hotel-view/HotelView.scss index c33e619e..0825460a 100644 --- a/src/views/hotel-view/HotelView.scss +++ b/src/views/hotel-view/HotelView.scss @@ -42,8 +42,8 @@ } .left { - width: 100%; - height: 100%; + width: 1200px; + height: 800px; bottom: 0; left: 0; animation-iteration-count: 1; diff --git a/src/views/inventory/InventoryView.tsx b/src/views/inventory/InventoryView.tsx index 87f39996..cca52d96 100644 --- a/src/views/inventory/InventoryView.tsx +++ b/src/views/inventory/InventoryView.tsx @@ -105,7 +105,11 @@ export const InventoryView: FC = props => { tabs.map((name, index) => { - return setCurrentTab(name) } /> + return ( + setCurrentTab(name) }> + { LocalizeText(name) } + + ); }) } diff --git a/src/views/inventory/views/badge/InventoryBadgeView.tsx b/src/views/inventory/views/badge/InventoryBadgeView.tsx index b5509284..eb73bc95 100644 --- a/src/views/inventory/views/badge/InventoryBadgeView.tsx +++ b/src/views/inventory/views/badge/InventoryBadgeView.tsx @@ -76,8 +76,8 @@ export const InventoryBadgeView: FC = props => return ( <> -
    -
    +
    +
    diff --git a/src/views/inventory/views/badge/results/InventoryBadgeResultsView.tsx b/src/views/inventory/views/badge/results/InventoryBadgeResultsView.tsx index 61e45470..8a57631a 100644 --- a/src/views/inventory/views/badge/results/InventoryBadgeResultsView.tsx +++ b/src/views/inventory/views/badge/results/InventoryBadgeResultsView.tsx @@ -1,4 +1,5 @@ import { FC } from 'react'; +import { ScrollableAreaView } from '../../../../../layout/scrollable-area/ScrollableAreaView'; import { InventoryBadgeItemView } from '../item/InventoryBadgeItemView'; import { InventoryBadgeResultsViewProps } from './InventoryBadgeResultsView.types'; @@ -7,13 +8,15 @@ export const InventoryBadgeResultsView: FC = pro const { badges = [], activeBadges = [] } = props; return ( -
    - { badges && (badges.length > 0) && badges.map((code, index) => - { - if(activeBadges.indexOf(code) >= 0) return null; - - return - }) } +
    + + { badges && (badges.length > 0) && badges.map((code, index) => + { + if(activeBadges.indexOf(code) >= 0) return null; + + return + }) } +
    ); } diff --git a/src/views/inventory/views/bot/InventoryBotView.tsx b/src/views/inventory/views/bot/InventoryBotView.tsx index b23635ba..9c255460 100644 --- a/src/views/inventory/views/bot/InventoryBotView.tsx +++ b/src/views/inventory/views/bot/InventoryBotView.tsx @@ -81,8 +81,8 @@ export const InventoryBotView: FC = props => } return ( -
    -
    +
    +
    diff --git a/src/views/inventory/views/bot/results/InventoryBotResultsView.tsx b/src/views/inventory/views/bot/results/InventoryBotResultsView.tsx index 8a258199..14503fb8 100644 --- a/src/views/inventory/views/bot/results/InventoryBotResultsView.tsx +++ b/src/views/inventory/views/bot/results/InventoryBotResultsView.tsx @@ -1,4 +1,5 @@ import { FC } from 'react'; +import { ScrollableAreaView } from '../../../../../layout/scrollable-area/ScrollableAreaView'; import { InventoryBotItemView } from '../item/InventoryBotItemView'; import { InventoryBotResultsViewProps } from './InventoryBotResultsView.types'; @@ -7,11 +8,13 @@ export const InventoryBotResultsView: FC = props = const { botItems = [] } = props; return ( -
    - { botItems && (botItems.length > 0) && botItems.map((item, index) => - { - return - }) } +
    + + { botItems && (botItems.length > 0) && botItems.map((item, index) => + { + return + }) } +
    ); } diff --git a/src/views/inventory/views/furniture/InventoryFurnitureView.tsx b/src/views/inventory/views/furniture/InventoryFurnitureView.tsx index 29bade0e..3152404a 100644 --- a/src/views/inventory/views/furniture/InventoryFurnitureView.tsx +++ b/src/views/inventory/views/furniture/InventoryFurnitureView.tsx @@ -116,8 +116,8 @@ export const InventoryFurnitureView: FC = props => } return ( -
    -
    +
    +
    diff --git a/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.scss b/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.scss index 3e11db9b..2d4f3402 100644 --- a/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.scss +++ b/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.scss @@ -1,5 +1,2 @@ .furni-item-container { - height: 188px; - max-height: 188px; - overflow-y: auto; } diff --git a/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.tsx b/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.tsx index bde6fab8..45318dae 100644 --- a/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.tsx +++ b/src/views/inventory/views/furniture/results/InventoryFurnitureResultsView.tsx @@ -1,4 +1,5 @@ import { FC } from 'react'; +import { ScrollableAreaView } from '../../../../../layout/scrollable-area/ScrollableAreaView'; import { InventoryFurnitureItemView } from '../item/InventoryFurnitureItemView'; import { InventoryFurnitureResultsViewProps } from './InventoryFurnitureResultsView.types'; @@ -7,11 +8,13 @@ export const InventoryFurnitureResultsView: FC - { groupItems && (groupItems.length > 0) && groupItems.map((item, index) => - { - return - }) } +
    + + { groupItems && (groupItems.length > 0) && groupItems.map((item, index) => + { + return + }) } +
    ); } diff --git a/src/views/inventory/views/furniture/search/InventoryFurnitureSearchView.tsx b/src/views/inventory/views/furniture/search/InventoryFurnitureSearchView.tsx index 08f2e15f..e8d4f05c 100644 --- a/src/views/inventory/views/furniture/search/InventoryFurnitureSearchView.tsx +++ b/src/views/inventory/views/furniture/search/InventoryFurnitureSearchView.tsx @@ -1,4 +1,5 @@ import { FC, useEffect, useState } from 'react'; +import { LocalizeText } from '../../../../../utils/LocalizeText'; import { InventoryFurnitureSearchViewProps } from './InventoryFurnitureSearchView.types'; export const InventoryFurnitureSearchView: FC = props => @@ -31,7 +32,7 @@ export const InventoryFurnitureSearchView: FC return (
    - setSearchValue(event.target.value) } /> + setSearchValue(event.target.value) } />
    + +
    + + ); +} diff --git a/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.types.ts b/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.types.ts new file mode 100644 index 00000000..8fb33820 --- /dev/null +++ b/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.types.ts @@ -0,0 +1,6 @@ +import { FurnitureWidgetProps } from '../FurnitureWidget.types'; + +export interface FurnitureManipulationMenuViewProps extends FurnitureWidgetProps +{ + +} diff --git a/src/views/room/widgets/object-location/ObjectLocationView.tsx b/src/views/room/widgets/object-location/ObjectLocationView.tsx new file mode 100644 index 00000000..d8547608 --- /dev/null +++ b/src/views/room/widgets/object-location/ObjectLocationView.tsx @@ -0,0 +1,39 @@ +import { Nitro } from 'nitro-renderer'; +import { FC, useCallback, useEffect, useRef, useState } from 'react'; +import { GetRoomEngine, GetRoomSession } from '../../../../api'; +import { ObjectLocationViewProps } from './ObjectLocationView.types'; + +export const ObjectLocationView: FC = props => +{ + const { objectId = -1, objectType = -1, children = null } = props; + const [ posX, setPosX ] = useState(0); + const [ posY, setPosY ] = useState(0); + const elementRef = useRef(); + + const updatePosition = useCallback(() => + { + const roomSession = GetRoomSession(); + const objectBounds = GetRoomEngine().getRoomObjectBoundingRectangle(roomSession.roomId, objectId, objectType, 1); + + if(!objectBounds) return; + + setPosX(Math.round(((objectBounds.left + (objectBounds.width / 2)) - (elementRef.current.offsetWidth / 2)))); + setPosY(Math.round((objectBounds.top - elementRef.current.offsetHeight) + 10)); + }, [ objectId, objectType ]); + + useEffect(() => + { + Nitro.instance.ticker.add(updatePosition); + + return () => + { + Nitro.instance.ticker.remove(updatePosition); + } + }, [ updatePosition ]); + + return ( +
    + { children } +
    + ); +} diff --git a/src/views/room/widgets/object-location/ObjectLocationView.types.ts b/src/views/room/widgets/object-location/ObjectLocationView.types.ts new file mode 100644 index 00000000..807c76a9 --- /dev/null +++ b/src/views/room/widgets/object-location/ObjectLocationView.types.ts @@ -0,0 +1,5 @@ +export interface ObjectLocationViewProps +{ + objectId: number; + objectType: number; +}