mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-30 00:50:50 +01:00
Update catalog state
This commit is contained in:
parent
dc89f4117a
commit
560a520e75
10
src/api/catalog/BuilderFurniPlaceableStatus.ts
Normal file
10
src/api/catalog/BuilderFurniPlaceableStatus.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export class BuilderFurniPlaceableStatus
|
||||||
|
{
|
||||||
|
public static OKAY: number = 0;
|
||||||
|
public static MISSING_OFFER: number = 1;
|
||||||
|
public static FURNI_LIMIT_REACHED: number = 2;
|
||||||
|
public static NOT_IN_ROOM: number = 3;
|
||||||
|
public static NOT_ROOM_OWNER: number = 4;
|
||||||
|
public static GUILD_ROOM: number = 5;
|
||||||
|
public static VISITORS_IN_ROOM: number = 6;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { SellablePetPaletteData } from '@nitrots/nitro-renderer';
|
import { SellablePetPaletteData } from '@nitrots/nitro-renderer';
|
||||||
import { GetRoomEngine } from '../../../api';
|
import { GetRoomEngine } from '../nitro';
|
||||||
import { ICatalogNode } from './ICatalogNode';
|
import { ICatalogNode } from './ICatalogNode';
|
||||||
|
|
||||||
export const GetPixelEffectIcon = (id: number) =>
|
export const GetPixelEffectIcon = (id: number) =>
|
@ -1,5 +1,5 @@
|
|||||||
import { GetProductOfferComposer, IFurnitureData } from '@nitrots/nitro-renderer';
|
import { GetProductOfferComposer, IFurnitureData } from '@nitrots/nitro-renderer';
|
||||||
import { GetProductDataForLocalization, SendMessageComposer } from '../../../api';
|
import { GetProductDataForLocalization, SendMessageComposer } from '..';
|
||||||
import { ICatalogPage } from './ICatalogPage';
|
import { ICatalogPage } from './ICatalogPage';
|
||||||
import { IProduct } from './IProduct';
|
import { IProduct } from './IProduct';
|
||||||
import { IPurchasableOffer } from './IPurchasableOffer';
|
import { IPurchasableOffer } from './IPurchasableOffer';
|
@ -1,4 +1,4 @@
|
|||||||
import { GetFurnitureData, GetProductDataForLocalization, LocalizeText, ProductTypeEnum } from '../../../api';
|
import { GetFurnitureData, GetProductDataForLocalization, LocalizeText, ProductTypeEnum } from '..';
|
||||||
import { ICatalogPage } from './ICatalogPage';
|
import { ICatalogPage } from './ICatalogPage';
|
||||||
import { IProduct } from './IProduct';
|
import { IProduct } from './IProduct';
|
||||||
import { IPurchasableOffer } from './IPurchasableOffer';
|
import { IPurchasableOffer } from './IPurchasableOffer';
|
@ -1,4 +1,4 @@
|
|||||||
import { GetConfiguration } from '../../../api';
|
import { GetConfiguration } from '../nitro';
|
||||||
import { IPageLocalization } from './IPageLocalization';
|
import { IPageLocalization } from './IPageLocalization';
|
||||||
|
|
||||||
export class PageLocalization implements IPageLocalization
|
export class PageLocalization implements IPageLocalization
|
41
src/api/catalog/PlacedObjectPurchaseData.ts
Normal file
41
src/api/catalog/PlacedObjectPurchaseData.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { IFurnitureData, IProductData } from '@nitrots/nitro-renderer';
|
||||||
|
import { IPurchasableOffer } from './IPurchasableOffer';
|
||||||
|
|
||||||
|
export class PlacedObjectPurchaseData
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
public readonly roomId: number,
|
||||||
|
public readonly objectId: number,
|
||||||
|
public readonly category: number,
|
||||||
|
public readonly wallLocation: string,
|
||||||
|
public readonly x: number,
|
||||||
|
public readonly y: number,
|
||||||
|
public readonly direction: number,
|
||||||
|
public readonly offer: IPurchasableOffer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public get offerId(): number
|
||||||
|
{
|
||||||
|
return this.offer.offerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get productClassId(): number
|
||||||
|
{
|
||||||
|
return this.offer.product.productClassId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get productData(): IProductData
|
||||||
|
{
|
||||||
|
return this.offer.product.productData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get furniData(): IFurnitureData
|
||||||
|
{
|
||||||
|
return this.offer.product.furnitureData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get extraParam(): string
|
||||||
|
{
|
||||||
|
return this.offer.product.extraParam;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
import { IFurnitureData, IObjectData, IProductData } from '@nitrots/nitro-renderer';
|
import { IFurnitureData, IObjectData, IProductData } from '@nitrots/nitro-renderer';
|
||||||
import { GetConfiguration, GetRoomEngine, GetSessionDataManager, ProductTypeEnum } from '../../../api';
|
import { GetConfiguration, GetRoomEngine, GetSessionDataManager } from '../nitro';
|
||||||
import { GetPixelEffectIcon, GetSubscriptionProductIcon } from './CatalogUtilities';
|
import { GetPixelEffectIcon, GetSubscriptionProductIcon } from './CatalogUtilities';
|
||||||
import { IProduct } from './IProduct';
|
import { IProduct } from './IProduct';
|
||||||
import { IPurchasableOffer } from './IPurchasableOffer';
|
import { IPurchasableOffer } from './IPurchasableOffer';
|
||||||
|
import { ProductTypeEnum } from './ProductTypeEnum';
|
||||||
|
|
||||||
export class Product implements IProduct
|
export class Product implements IProduct
|
||||||
{
|
{
|
@ -1 +1,24 @@
|
|||||||
|
export * from './BuilderFurniPlaceableStatus';
|
||||||
|
export * from './CatalogNode';
|
||||||
|
export * from './CatalogPage';
|
||||||
|
export * from './CatalogPageName';
|
||||||
|
export * from './CatalogPetPalette';
|
||||||
|
export * from './CatalogPurchaseState';
|
||||||
|
export * from './CatalogType';
|
||||||
|
export * from './CatalogUtilities';
|
||||||
|
export * from './FurnitureOffer';
|
||||||
|
export * from './GiftWrappingConfiguration';
|
||||||
|
export * from './ICatalogNode';
|
||||||
|
export * from './ICatalogOptions';
|
||||||
|
export * from './ICatalogPage';
|
||||||
|
export * from './IPageLocalization';
|
||||||
|
export * from './IProduct';
|
||||||
|
export * from './IPurchasableOffer';
|
||||||
|
export * from './IPurchaseOptions';
|
||||||
|
export * from './Offer';
|
||||||
|
export * from './PageLocalization';
|
||||||
|
export * from './PlacedObjectPurchaseData';
|
||||||
|
export * from './Product';
|
||||||
export * from './ProductTypeEnum';
|
export * from './ProductTypeEnum';
|
||||||
|
export * from './RequestedPage';
|
||||||
|
export * from './SearchResult';
|
||||||
|
@ -95,7 +95,7 @@ export class FurnitureItem implements IFurnitureItem
|
|||||||
return this._extra;
|
return this._extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get _Str_16260(): boolean
|
public get recyclable(): boolean
|
||||||
{
|
{
|
||||||
return this._recyclable;
|
return this._recyclable;
|
||||||
}
|
}
|
||||||
@ -135,17 +135,17 @@ export class FurnitureItem implements IFurnitureItem
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get _Str_8932(): number
|
public get creationDay(): number
|
||||||
{
|
{
|
||||||
return this._creationDay;
|
return this._creationDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get _Str_9050(): number
|
public get creationMonth(): number
|
||||||
{
|
{
|
||||||
return this._creationMonth;
|
return this._creationMonth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get _Str_9408(): number
|
public get creationYear(): number
|
||||||
{
|
{
|
||||||
return this._creationYear;
|
return this._creationYear;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ export class FurnitureItem implements IFurnitureItem
|
|||||||
return this._slotId;
|
return this._slotId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get _Str_3951(): number
|
public get songId(): number
|
||||||
{
|
{
|
||||||
return this._songId;
|
return this._songId;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ export class FurnitureItem implements IFurnitureItem
|
|||||||
return this._hasRentPeriodStarted;
|
return this._hasRentPeriodStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get _Str_10616(): number
|
public get expirationTimeStamp(): number
|
||||||
{
|
{
|
||||||
return this._expirationTimeStamp;
|
return this._expirationTimeStamp;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ export interface IFurnitureItem
|
|||||||
stuffData: IObjectData;
|
stuffData: IObjectData;
|
||||||
extra: number;
|
extra: number;
|
||||||
category: number;
|
category: number;
|
||||||
_Str_16260: boolean;
|
recyclable: boolean;
|
||||||
isTradable: boolean;
|
isTradable: boolean;
|
||||||
isGroupable: boolean;
|
isGroupable: boolean;
|
||||||
sellable: boolean;
|
sellable: boolean;
|
||||||
|
5
src/api/utils/LocalStorageKeys.ts
Normal file
5
src/api/utils/LocalStorageKeys.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export class LocalStorageKeys
|
||||||
|
{
|
||||||
|
public static CATALOG_PLACE_MULTIPLE_OBJECTS: string = 'catalogPlaceMultipleObjects';
|
||||||
|
public static CATALOG_SKIP_PURCHASE_CONFIRMATION: string = 'catalogSkipPurchaseConfirmation';
|
||||||
|
}
|
@ -5,6 +5,7 @@ export * from './LocalizeBageName';
|
|||||||
export * from './LocalizeFormattedNumber';
|
export * from './LocalizeFormattedNumber';
|
||||||
export * from './LocalizeShortNumber';
|
export * from './LocalizeShortNumber';
|
||||||
export * from './LocalizeText';
|
export * from './LocalizeText';
|
||||||
|
export * from './LocalStorageKeys';
|
||||||
export * from './PlaySound';
|
export * from './PlaySound';
|
||||||
export * from './ProductImageUtility';
|
export * from './ProductImageUtility';
|
||||||
export * from './Randomizer';
|
export * from './Randomizer';
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
import { FrontPageItem, RoomPreviewer } from '@nitrots/nitro-renderer';
|
|
||||||
import { createContext, Dispatch, FC, ProviderProps, SetStateAction, useContext } from 'react';
|
|
||||||
import { ICatalogNode } from './common/ICatalogNode';
|
|
||||||
import { ICatalogOptions } from './common/ICatalogOptions';
|
|
||||||
import { ICatalogPage } from './common/ICatalogPage';
|
|
||||||
import { IPageLocalization } from './common/IPageLocalization';
|
|
||||||
import { IPurchasableOffer } from './common/IPurchasableOffer';
|
|
||||||
import { IPurchaseOptions } from './common/IPurchaseOptions';
|
|
||||||
import { SearchResult } from './common/SearchResult';
|
|
||||||
|
|
||||||
interface ICatalogContext
|
|
||||||
{
|
|
||||||
isVisible: boolean;
|
|
||||||
isBusy: boolean;
|
|
||||||
setIsBusy: Dispatch<SetStateAction<boolean>>;
|
|
||||||
pageId: number;
|
|
||||||
currentType: string;
|
|
||||||
setCurrentType: Dispatch<SetStateAction<string>>;
|
|
||||||
rootNode: ICatalogNode;
|
|
||||||
setRootNode: Dispatch<SetStateAction<ICatalogNode>>;
|
|
||||||
offersToNodes: Map<number, ICatalogNode[]>;
|
|
||||||
setOffersToNodes: Dispatch<SetStateAction<Map<number, ICatalogNode[]>>>;
|
|
||||||
currentPage: ICatalogPage;
|
|
||||||
setCurrentPage: Dispatch<SetStateAction<ICatalogPage>>;
|
|
||||||
currentOffer: IPurchasableOffer;
|
|
||||||
setCurrentOffer: Dispatch<SetStateAction<IPurchasableOffer>>;
|
|
||||||
activeNodes: ICatalogNode[];
|
|
||||||
setActiveNodes: Dispatch<SetStateAction<ICatalogNode[]>>;
|
|
||||||
searchResult: SearchResult;
|
|
||||||
setSearchResult: Dispatch<SetStateAction<SearchResult>>;
|
|
||||||
frontPageItems: FrontPageItem[];
|
|
||||||
setFrontPageItems: Dispatch<SetStateAction<FrontPageItem[]>>;
|
|
||||||
roomPreviewer: RoomPreviewer;
|
|
||||||
purchaseOptions: IPurchaseOptions;
|
|
||||||
setPurchaseOptions: Dispatch<SetStateAction<IPurchaseOptions>>;
|
|
||||||
catalogOptions: ICatalogOptions;
|
|
||||||
setCatalogOptions: Dispatch<SetStateAction<ICatalogOptions>>;
|
|
||||||
resetState: () => void;
|
|
||||||
getNodesByOfferId: (offerId: number, flag?: boolean) => ICatalogNode[];
|
|
||||||
loadCatalogPage: (pageId: number, offerId: number) => void;
|
|
||||||
showCatalogPage: (pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) => void;
|
|
||||||
activateNode: (targetNode: ICatalogNode) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CatalogContext = createContext<ICatalogContext>({
|
|
||||||
isVisible: null,
|
|
||||||
isBusy: null,
|
|
||||||
setIsBusy: null,
|
|
||||||
pageId: null,
|
|
||||||
currentType: null,
|
|
||||||
setCurrentType: null,
|
|
||||||
rootNode: null,
|
|
||||||
setRootNode: null,
|
|
||||||
offersToNodes: null,
|
|
||||||
setOffersToNodes: null,
|
|
||||||
currentPage: null,
|
|
||||||
setCurrentPage: null,
|
|
||||||
currentOffer: null,
|
|
||||||
setCurrentOffer: null,
|
|
||||||
activeNodes: null,
|
|
||||||
setActiveNodes: null,
|
|
||||||
searchResult: null,
|
|
||||||
setSearchResult: null,
|
|
||||||
frontPageItems: null,
|
|
||||||
setFrontPageItems: null,
|
|
||||||
roomPreviewer: null,
|
|
||||||
purchaseOptions: null,
|
|
||||||
setPurchaseOptions: null,
|
|
||||||
catalogOptions: null,
|
|
||||||
setCatalogOptions: null,
|
|
||||||
resetState: null,
|
|
||||||
getNodesByOfferId: null,
|
|
||||||
loadCatalogPage: null,
|
|
||||||
showCatalogPage: null,
|
|
||||||
activateNode: null
|
|
||||||
});
|
|
||||||
|
|
||||||
export const CatalogContextProvider: FC<ProviderProps<ICatalogContext>> = props =>
|
|
||||||
{
|
|
||||||
return <CatalogContext.Provider value={ props.value }>{ props.children }</CatalogContext.Provider>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useCatalogContext = () => useContext(CatalogContext);
|
|
@ -1,291 +0,0 @@
|
|||||||
import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, ClubGiftInfoEvent, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, SellablePetPalettesMessageEvent } from '@nitrots/nitro-renderer';
|
|
||||||
import { GuildMembershipsMessageEvent } from '@nitrots/nitro-renderer/src/nitro/communication/messages/incoming/user/GuildMembershipsMessageEvent';
|
|
||||||
import { FC, useCallback } from 'react';
|
|
||||||
import { GetFurnitureData, GetProductDataForLocalization, LocalizeText, NotificationAlertType, NotificationUtilities, ProductTypeEnum } from '../../api';
|
|
||||||
import { CatalogGiftReceiverNotFoundEvent, CatalogNameResultEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent } from '../../events';
|
|
||||||
import { DispatchUiEvent, UseMessageEventHook } from '../../hooks';
|
|
||||||
import { useCatalogContext } from './CatalogContext';
|
|
||||||
import { CatalogNode } from './common/CatalogNode';
|
|
||||||
import { CatalogPetPalette } from './common/CatalogPetPalette';
|
|
||||||
import { CatalogType } from './common/CatalogType';
|
|
||||||
import { GiftWrappingConfiguration } from './common/GiftWrappingConfiguration';
|
|
||||||
import { ICatalogNode } from './common/ICatalogNode';
|
|
||||||
import { IProduct } from './common/IProduct';
|
|
||||||
import { IPurchasableOffer } from './common/IPurchasableOffer';
|
|
||||||
import { Offer } from './common/Offer';
|
|
||||||
import { PageLocalization } from './common/PageLocalization';
|
|
||||||
import { Product } from './common/Product';
|
|
||||||
|
|
||||||
export const CatalogMessageHandler: FC<{}> = props =>
|
|
||||||
{
|
|
||||||
const { setIsBusy, pageId, currentType, setRootNode, setOffersToNodes, currentPage, setCurrentOffer, setFrontPageItems, resetState, showCatalogPage, setCatalogOptions, setPurchaseOptions } = useCatalogContext();
|
|
||||||
|
|
||||||
const onCatalogPagesListEvent = useCallback((event: CatalogPagesListEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
const offers: Map<number, ICatalogNode[]> = new Map();
|
|
||||||
|
|
||||||
const getCatalogNode = (node: NodeData, depth: number, parent: ICatalogNode) =>
|
|
||||||
{
|
|
||||||
const catalogNode = (new CatalogNode(node, depth, parent) as ICatalogNode);
|
|
||||||
|
|
||||||
for(const offerId of catalogNode.offerIds)
|
|
||||||
{
|
|
||||||
if(offers.has(offerId)) offers.get(offerId).push(catalogNode);
|
|
||||||
else offers.set(offerId, [ catalogNode ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
for(const child of node.children) catalogNode.addChild(getCatalogNode(child, depth, catalogNode));
|
|
||||||
|
|
||||||
return catalogNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
setRootNode(getCatalogNode(parser.root, 0, null));
|
|
||||||
setOffersToNodes(offers);
|
|
||||||
}, [ setRootNode, setOffersToNodes ]);
|
|
||||||
|
|
||||||
const onCatalogPageMessageEvent = useCallback((event: CatalogPageMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
if(parser.catalogType !== currentType) return;
|
|
||||||
|
|
||||||
const purchasableOffers: IPurchasableOffer[] = [];
|
|
||||||
|
|
||||||
for(const offer of parser.offers)
|
|
||||||
{
|
|
||||||
const products: IProduct[] = [];
|
|
||||||
const productData = GetProductDataForLocalization(offer.localizationId);
|
|
||||||
|
|
||||||
for(const product of offer.products)
|
|
||||||
{
|
|
||||||
const furnitureData = GetFurnitureData(product.furniClassId, product.productType);
|
|
||||||
|
|
||||||
products.push(new Product(product.productType, product.furniClassId, product.extraParam, product.productCount, productData, furnitureData, product.uniqueLimitedItem, product.uniqueLimitedSeriesSize, product.uniqueLimitedItemsLeft));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!products.length) continue;
|
|
||||||
|
|
||||||
const purchasableOffer = new Offer(offer.offerId, offer.localizationId, offer.rent, offer.priceCredits, offer.priceActivityPoints, offer.priceActivityPointsType, offer.giftable, offer.clubLevel, products, offer.bundlePurchaseAllowed);
|
|
||||||
|
|
||||||
if((currentType === CatalogType.NORMAL) || ((purchasableOffer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (purchasableOffer.pricingModel !== Offer.PRICING_MODEL_MULTI))) purchasableOffers.push(purchasableOffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(parser.frontPageItems && parser.frontPageItems.length) setFrontPageItems(parser.frontPageItems);
|
|
||||||
|
|
||||||
setIsBusy(false);
|
|
||||||
|
|
||||||
if(pageId === parser.pageId)
|
|
||||||
{
|
|
||||||
showCatalogPage(parser.pageId, parser.layoutCode, new PageLocalization(parser.localization.images.concat(), parser.localization.texts.concat()), purchasableOffers, parser.offerId, parser.acceptSeasonCurrencyAsCredits);
|
|
||||||
}
|
|
||||||
}, [ currentType, pageId, setFrontPageItems, setIsBusy, showCatalogPage ]);
|
|
||||||
|
|
||||||
const onPurchaseOKMessageEvent = useCallback((event: PurchaseOKMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
DispatchUiEvent(new CatalogPurchasedEvent(parser.offer));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onPurchaseErrorMessageEvent = useCallback((event: PurchaseErrorMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
DispatchUiEvent(new CatalogPurchaseFailureEvent(parser.code));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onPurchaseNotAllowedMessageEvent = useCallback((event: PurchaseNotAllowedMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
DispatchUiEvent(new CatalogPurchaseNotAllowedEvent(parser.code));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onLimitedEditionSoldOutEvent = useCallback((event: LimitedEditionSoldOutEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
DispatchUiEvent(new CatalogPurchaseSoldOutEvent());
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onProductOfferEvent = useCallback((event: ProductOfferEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
const offerData = parser.offer;
|
|
||||||
|
|
||||||
if(!offerData || !offerData.products.length) return;
|
|
||||||
|
|
||||||
const offerProductData = offerData.products[0];
|
|
||||||
|
|
||||||
if(offerProductData.uniqueLimitedItem)
|
|
||||||
{
|
|
||||||
// update unique
|
|
||||||
}
|
|
||||||
|
|
||||||
const products: IProduct[] = [];
|
|
||||||
const productData = GetProductDataForLocalization(offerData.localizationId);
|
|
||||||
|
|
||||||
for(const product of offerData.products)
|
|
||||||
{
|
|
||||||
const furnitureData = GetFurnitureData(product.furniClassId, product.productType);
|
|
||||||
|
|
||||||
products.push(new Product(product.productType, product.furniClassId, product.extraParam, product.productCount, productData, furnitureData, product.uniqueLimitedItem, product.uniqueLimitedSeriesSize, product.uniqueLimitedItemsLeft));
|
|
||||||
}
|
|
||||||
|
|
||||||
const offer = new Offer(offerData.offerId, offerData.localizationId, offerData.rent, offerData.priceCredits, offerData.priceActivityPoints, offerData.priceActivityPointsType, offerData.giftable, offerData.clubLevel, products, offerData.bundlePurchaseAllowed);
|
|
||||||
|
|
||||||
if(!((currentType === CatalogType.NORMAL) || ((offer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (offer.pricingModel !== Offer.PRICING_MODEL_MULTI)))) return;
|
|
||||||
|
|
||||||
offer.page = currentPage;
|
|
||||||
|
|
||||||
setCurrentOffer(offer);
|
|
||||||
|
|
||||||
if(offer.product && (offer.product.productType === ProductTypeEnum.WALL))
|
|
||||||
{
|
|
||||||
if(offer.product && (offer.product.productType === ProductTypeEnum.WALL))
|
|
||||||
{
|
|
||||||
setPurchaseOptions(prevValue =>
|
|
||||||
{
|
|
||||||
const newValue = { ...prevValue };
|
|
||||||
|
|
||||||
newValue.extraData =( offer.product.extraParam || null);
|
|
||||||
|
|
||||||
return newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// (this._isObjectMoverRequested) && (this._purchasableOffer)
|
|
||||||
}, [ currentType, currentPage, setCurrentOffer, setPurchaseOptions ]);
|
|
||||||
|
|
||||||
const onSellablePetPalettesMessageEvent = useCallback((event: SellablePetPalettesMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
const petPalette = new CatalogPetPalette(parser.productCode, parser.palettes.slice());
|
|
||||||
|
|
||||||
setCatalogOptions(prevValue =>
|
|
||||||
{
|
|
||||||
const petPalettes = [];
|
|
||||||
|
|
||||||
if(prevValue.petPalettes) petPalettes.push(...prevValue.petPalettes);
|
|
||||||
|
|
||||||
for(let i = 0; i < petPalettes.length; i++)
|
|
||||||
{
|
|
||||||
const palette = petPalettes[i];
|
|
||||||
|
|
||||||
if(palette.breed === petPalette.breed)
|
|
||||||
{
|
|
||||||
petPalettes.splice(i, 1);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
petPalettes.push(petPalette);
|
|
||||||
|
|
||||||
return { ...prevValue, petPalettes };
|
|
||||||
});
|
|
||||||
}, [ setCatalogOptions ]);
|
|
||||||
|
|
||||||
const onApproveNameMessageEvent = useCallback((event: ApproveNameMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
DispatchUiEvent(new CatalogNameResultEvent(parser.result, parser.validationInfo));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onGiftReceiverNotFoundEvent = useCallback(() =>
|
|
||||||
{
|
|
||||||
DispatchUiEvent(new CatalogGiftReceiverNotFoundEvent());
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onHabboClubOffersMessageEvent = useCallback((event: HabboClubOffersMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
setCatalogOptions(prevValue =>
|
|
||||||
{
|
|
||||||
const clubOffers = parser.offers;
|
|
||||||
|
|
||||||
return { ...prevValue, clubOffers };
|
|
||||||
});
|
|
||||||
}, [ setCatalogOptions ]);
|
|
||||||
|
|
||||||
const onGuildMembershipsMessageEvent = useCallback((event: GuildMembershipsMessageEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
setCatalogOptions(prevValue =>
|
|
||||||
{
|
|
||||||
const groups = parser.groups;
|
|
||||||
|
|
||||||
return { ...prevValue, groups };
|
|
||||||
});
|
|
||||||
}, [ setCatalogOptions ]);
|
|
||||||
|
|
||||||
const onGiftWrappingConfigurationEvent = useCallback((event: GiftWrappingConfigurationEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
setCatalogOptions(prevValue =>
|
|
||||||
{
|
|
||||||
const giftConfiguration = new GiftWrappingConfiguration(parser);
|
|
||||||
|
|
||||||
return { ...prevValue, giftConfiguration };
|
|
||||||
});
|
|
||||||
}, [ setCatalogOptions ]);
|
|
||||||
|
|
||||||
const onMarketplaceMakeOfferResult = useCallback((event: MarketplaceMakeOfferResult) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
if(!parser) return;
|
|
||||||
|
|
||||||
let title = '';
|
|
||||||
if(parser.result === 1)
|
|
||||||
{
|
|
||||||
title = LocalizeText('inventory.marketplace.result.title.success');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
title = LocalizeText('inventory.marketplace.result.title.failure');
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = LocalizeText(`inventory.marketplace.result.${ parser.result }`);
|
|
||||||
|
|
||||||
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, title);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onClubGiftInfoEvent = useCallback((event: ClubGiftInfoEvent) =>
|
|
||||||
{
|
|
||||||
const parser = event.getParser();
|
|
||||||
|
|
||||||
setCatalogOptions(prevValue =>
|
|
||||||
{
|
|
||||||
const clubGifts = parser;
|
|
||||||
|
|
||||||
return { ...prevValue, clubGifts };
|
|
||||||
});
|
|
||||||
}, [ setCatalogOptions ]);
|
|
||||||
|
|
||||||
UseMessageEventHook(CatalogPagesListEvent, onCatalogPagesListEvent);
|
|
||||||
UseMessageEventHook(CatalogPageMessageEvent, onCatalogPageMessageEvent);
|
|
||||||
UseMessageEventHook(PurchaseOKMessageEvent, onPurchaseOKMessageEvent);
|
|
||||||
UseMessageEventHook(PurchaseErrorMessageEvent, onPurchaseErrorMessageEvent);
|
|
||||||
UseMessageEventHook(PurchaseNotAllowedMessageEvent, onPurchaseNotAllowedMessageEvent);
|
|
||||||
UseMessageEventHook(LimitedEditionSoldOutEvent, onLimitedEditionSoldOutEvent);
|
|
||||||
UseMessageEventHook(ProductOfferEvent, onProductOfferEvent);
|
|
||||||
UseMessageEventHook(GuildMembershipsMessageEvent, onGuildMembershipsMessageEvent);
|
|
||||||
UseMessageEventHook(SellablePetPalettesMessageEvent, onSellablePetPalettesMessageEvent);
|
|
||||||
UseMessageEventHook(ApproveNameMessageEvent, onApproveNameMessageEvent);
|
|
||||||
UseMessageEventHook(GiftReceiverNotFoundEvent, onGiftReceiverNotFoundEvent);
|
|
||||||
UseMessageEventHook(HabboClubOffersMessageEvent, onHabboClubOffersMessageEvent);
|
|
||||||
UseMessageEventHook(GiftWrappingConfigurationEvent, onGiftWrappingConfigurationEvent);
|
|
||||||
UseMessageEventHook(ClubGiftInfoEvent, onClubGiftInfoEvent);
|
|
||||||
UseMessageEventHook(MarketplaceMakeOfferResult, onMarketplaceMakeOfferResult);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
@ -1,406 +1,75 @@
|
|||||||
import { CatalogPublishedMessageEvent, FrontPageItem, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, ILinkEventTracker, RoomPreviewer } from '@nitrots/nitro-renderer';
|
import { ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { AddEventLinkTracker, GetRoomEngine, LocalizeText, NotificationAlertType, NotificationUtilities, PlaySound, RemoveLinkEventTracker, SendMessageComposer, SoundNames } from '../../api';
|
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../api';
|
||||||
import { Column, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
|
import { Column, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
|
||||||
import { CatalogPurchasedEvent } from '../../events';
|
import { useCatalog } from '../../hooks';
|
||||||
import { UseMessageEventHook, UseUiEvent } from '../../hooks';
|
|
||||||
import { CatalogContextProvider } from './CatalogContext';
|
|
||||||
import { CatalogMessageHandler } from './CatalogMessageHandler';
|
|
||||||
import { CatalogPage } from './common/CatalogPage';
|
|
||||||
import { CatalogType } from './common/CatalogType';
|
|
||||||
import { ICatalogNode } from './common/ICatalogNode';
|
|
||||||
import { ICatalogOptions } from './common/ICatalogOptions';
|
|
||||||
import { ICatalogPage } from './common/ICatalogPage';
|
|
||||||
import { IPageLocalization } from './common/IPageLocalization';
|
|
||||||
import { IPurchasableOffer } from './common/IPurchasableOffer';
|
|
||||||
import { IPurchaseOptions } from './common/IPurchaseOptions';
|
|
||||||
import { RequestedPage } from './common/RequestedPage';
|
|
||||||
import { SearchResult } from './common/SearchResult';
|
|
||||||
import { CatalogGiftView } from './views/gift/CatalogGiftView';
|
import { CatalogGiftView } from './views/gift/CatalogGiftView';
|
||||||
import { CatalogNavigationView } from './views/navigation/CatalogNavigationView';
|
import { CatalogNavigationView } from './views/navigation/CatalogNavigationView';
|
||||||
import { GetCatalogLayout } from './views/page/layout/GetCatalogLayout';
|
import { GetCatalogLayout } from './views/page/layout/GetCatalogLayout';
|
||||||
import { MarketplacePostOfferView } from './views/page/layout/marketplace/MarketplacePostOfferView';
|
import { MarketplacePostOfferView } from './views/page/layout/marketplace/MarketplacePostOfferView';
|
||||||
|
|
||||||
const REQUESTED_PAGE = new RequestedPage();
|
|
||||||
|
|
||||||
export const CatalogView: FC<{}> = props =>
|
export const CatalogView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const { isVisible = false, setIsVisible = null, rootNode = null, currentPage = null, navigationHidden = false, setNavigationHidden = null, activeNodes = [], searchResult = null, setSearchResult = null, getNodeById = null, openPageByName = null, openPageByOfferId = null, activateNode = null } = useCatalog();
|
||||||
const [ isBusy, setIsBusy ] = useState(false);
|
|
||||||
const [ pageId, setPageId ] = useState(-1);
|
|
||||||
const [ previousPageId, setPreviousPageId ] = useState(-1);
|
|
||||||
const [ currentType, setCurrentType ] = useState(CatalogType.NORMAL);
|
|
||||||
const [ rootNode, setRootNode ] = useState<ICatalogNode>(null);
|
|
||||||
const [ offersToNodes, setOffersToNodes ] = useState<Map<number, ICatalogNode[]>>(null);
|
|
||||||
const [ currentPage, setCurrentPage ] = useState<ICatalogPage>(null);
|
|
||||||
const [ currentOffer, setCurrentOffer ] = useState<IPurchasableOffer>(null);
|
|
||||||
const [ activeNodes, setActiveNodes ] = useState<ICatalogNode[]>([]);
|
|
||||||
const [ searchResult, setSearchResult ] = useState<SearchResult>(null);
|
|
||||||
const [ frontPageItems, setFrontPageItems ] = useState<FrontPageItem[]>([]);
|
|
||||||
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
|
||||||
const [ navigationHidden, setNavigationHidden ] = useState(false);
|
|
||||||
const [ purchaseOptions, setPurchaseOptions ] = useState<IPurchaseOptions>({ quantity: 1, extraData: null, extraParamRequired: false, previewStuffData: null });
|
|
||||||
const [ catalogOptions, setCatalogOptions ] = useState<ICatalogOptions>({});
|
|
||||||
|
|
||||||
const resetState = useCallback(() =>
|
|
||||||
{
|
|
||||||
setPageId(-1);
|
|
||||||
setPreviousPageId(-1);
|
|
||||||
setRootNode(null);
|
|
||||||
setOffersToNodes(null);
|
|
||||||
setCurrentPage(null);
|
|
||||||
setCurrentOffer(null);
|
|
||||||
setActiveNodes([]);
|
|
||||||
setSearchResult(null);
|
|
||||||
setFrontPageItems([]);
|
|
||||||
setIsVisible(false);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onCatalogPublishedMessageEvent = useCallback((event: CatalogPublishedMessageEvent) =>
|
|
||||||
{
|
|
||||||
const wasVisible = isVisible;
|
|
||||||
|
|
||||||
resetState();
|
|
||||||
|
|
||||||
if(wasVisible) NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.published.description'), NotificationAlertType.ALERT, null, null, LocalizeText('catalog.alert.published.title'));
|
|
||||||
}, [ isVisible, resetState ]);
|
|
||||||
|
|
||||||
UseMessageEventHook(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent);
|
|
||||||
|
|
||||||
const getNodeById = useCallback((id: number, node: ICatalogNode) =>
|
|
||||||
{
|
|
||||||
if((node.pageId === id) && (node !== rootNode)) return node;
|
|
||||||
|
|
||||||
for(const child of node.children)
|
|
||||||
{
|
|
||||||
const found = (getNodeById(id, child) as ICatalogNode);
|
|
||||||
|
|
||||||
if(found) return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}, [ rootNode ]);
|
|
||||||
|
|
||||||
const getNodeByName = useCallback((name: string, node: ICatalogNode) =>
|
|
||||||
{
|
|
||||||
if((node.pageName === name) && (node !== rootNode)) return node;
|
|
||||||
|
|
||||||
for(const child of node.children)
|
|
||||||
{
|
|
||||||
const found = (getNodeByName(name, child) as ICatalogNode);
|
|
||||||
|
|
||||||
if(found) return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}, [ rootNode ]);
|
|
||||||
|
|
||||||
const getNodesByOfferId = useCallback((offerId: number, flag: boolean = false) =>
|
|
||||||
{
|
|
||||||
if(!offersToNodes || !offersToNodes.size) return null;
|
|
||||||
|
|
||||||
if(flag)
|
|
||||||
{
|
|
||||||
const nodes: ICatalogNode[] = [];
|
|
||||||
const offers = offersToNodes.get(offerId);
|
|
||||||
|
|
||||||
if(offers && offers.length) for(const offer of offers) (offer.isVisible && nodes.push(offer));
|
|
||||||
|
|
||||||
if(nodes.length) return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offersToNodes.get(offerId);
|
|
||||||
}, [ offersToNodes ]);
|
|
||||||
|
|
||||||
const loadCatalogPage = useCallback((pageId: number, offerId: number) =>
|
|
||||||
{
|
|
||||||
if(pageId < 0) return;
|
|
||||||
|
|
||||||
setIsBusy(true);
|
|
||||||
setPageId(pageId);
|
|
||||||
|
|
||||||
if(pageId > -1) SendMessageComposer(new GetCatalogPageComposer(pageId, offerId, currentType));
|
|
||||||
}, [ currentType ]);
|
|
||||||
|
|
||||||
const showCatalogPage = useCallback((pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) =>
|
|
||||||
{
|
|
||||||
const catalogPage = (new CatalogPage(pageId, layoutCode, localization, offers, acceptSeasonCurrencyAsCredits) as ICatalogPage);
|
|
||||||
|
|
||||||
setCurrentPage(catalogPage);
|
|
||||||
setPreviousPageId(prevValue => ((pageId !== -1) ? pageId : prevValue));
|
|
||||||
setNavigationHidden(false);
|
|
||||||
|
|
||||||
if((offerId > -1) && catalogPage.offers.length)
|
|
||||||
{
|
|
||||||
for(const offer of catalogPage.offers)
|
|
||||||
{
|
|
||||||
if(offer.offerId !== offerId) continue;
|
|
||||||
|
|
||||||
setCurrentOffer(offer)
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const activateNode = useCallback((targetNode: ICatalogNode, offerId: number = -1) =>
|
|
||||||
{
|
|
||||||
if(targetNode.parent.pageName === 'root')
|
|
||||||
{
|
|
||||||
if(targetNode.children.length)
|
|
||||||
{
|
|
||||||
for(const child of targetNode.children)
|
|
||||||
{
|
|
||||||
if(!child.isVisible) continue;
|
|
||||||
|
|
||||||
targetNode = child;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const nodes: ICatalogNode[] = [];
|
|
||||||
|
|
||||||
let node = targetNode;
|
|
||||||
|
|
||||||
while(node && (node.pageName !== 'root'))
|
|
||||||
{
|
|
||||||
nodes.push(node);
|
|
||||||
|
|
||||||
node = node.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes.reverse();
|
|
||||||
|
|
||||||
setActiveNodes(prevValue =>
|
|
||||||
{
|
|
||||||
const isActive = (prevValue.indexOf(targetNode) >= 0);
|
|
||||||
const isOpen = targetNode.isOpen;
|
|
||||||
|
|
||||||
for(const existing of prevValue)
|
|
||||||
{
|
|
||||||
existing.deactivate();
|
|
||||||
|
|
||||||
if(nodes.indexOf(existing) === -1) existing.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const n of nodes)
|
|
||||||
{
|
|
||||||
n.activate();
|
|
||||||
|
|
||||||
if(n.parent) n.open();
|
|
||||||
|
|
||||||
if((n === targetNode.parent) && n.children.length) n.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isActive && isOpen) targetNode.close();
|
|
||||||
else targetNode.open();
|
|
||||||
|
|
||||||
return nodes;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(targetNode.pageId > -1) loadCatalogPage(targetNode.pageId, offerId);
|
|
||||||
}, [ setActiveNodes, loadCatalogPage ]);
|
|
||||||
|
|
||||||
const openPageById = useCallback((id: number) =>
|
|
||||||
{
|
|
||||||
setSearchResult(null);
|
|
||||||
|
|
||||||
if(!isVisible)
|
|
||||||
{
|
|
||||||
REQUESTED_PAGE.requestById = id;
|
|
||||||
|
|
||||||
setIsVisible(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const node = getNodeById(id, rootNode);
|
|
||||||
|
|
||||||
if(node) activateNode(node);
|
|
||||||
}
|
|
||||||
}, [ isVisible, rootNode, getNodeById, activateNode ]);
|
|
||||||
|
|
||||||
const openPageByName = useCallback((name: string) =>
|
|
||||||
{
|
|
||||||
setSearchResult(null);
|
|
||||||
|
|
||||||
if(!isVisible)
|
|
||||||
{
|
|
||||||
REQUESTED_PAGE.requestByName = name;
|
|
||||||
|
|
||||||
setIsVisible(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const node = getNodeByName(name, rootNode);
|
|
||||||
|
|
||||||
if(node) activateNode(node);
|
|
||||||
}
|
|
||||||
}, [ isVisible, rootNode, getNodeByName, activateNode ]);
|
|
||||||
|
|
||||||
const openPageByOfferId = useCallback((offerId: number) =>
|
|
||||||
{
|
|
||||||
setSearchResult(null);
|
|
||||||
|
|
||||||
if(!isVisible)
|
|
||||||
{
|
|
||||||
REQUESTED_PAGE.requestedByOfferId = offerId;
|
|
||||||
|
|
||||||
setIsVisible(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const nodes = getNodesByOfferId(offerId);
|
|
||||||
|
|
||||||
if(!nodes || !nodes.length) return;
|
|
||||||
|
|
||||||
activateNode(nodes[0], offerId);
|
|
||||||
}
|
|
||||||
}, [ isVisible, getNodesByOfferId, activateNode ]);
|
|
||||||
|
|
||||||
const onCatalogPurchasedEvent = useCallback((event: CatalogPurchasedEvent) =>
|
|
||||||
{
|
|
||||||
PlaySound(SoundNames.CREDITS);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogPurchasedEvent);
|
|
||||||
|
|
||||||
const linkReceived = useCallback((url: string) =>
|
|
||||||
{
|
|
||||||
const parts = url.split('/');
|
|
||||||
|
|
||||||
if(parts.length < 2) return;
|
|
||||||
|
|
||||||
switch(parts[1])
|
|
||||||
{
|
|
||||||
case 'show':
|
|
||||||
setIsVisible(true);
|
|
||||||
return;
|
|
||||||
case 'hide':
|
|
||||||
setIsVisible(false);
|
|
||||||
return;
|
|
||||||
case 'toggle':
|
|
||||||
setIsVisible(prevValue => !prevValue);
|
|
||||||
return;
|
|
||||||
case 'open':
|
|
||||||
if(parts.length > 2)
|
|
||||||
{
|
|
||||||
if(parts.length === 4)
|
|
||||||
{
|
|
||||||
switch(parts[2])
|
|
||||||
{
|
|
||||||
case 'offerId':
|
|
||||||
openPageByOfferId(parseInt(parts[3]));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
openPageByName(parts[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setIsVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, [ openPageByOfferId, openPageByName ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
const linkTracker: ILinkEventTracker = {
|
const linkTracker: ILinkEventTracker = {
|
||||||
linkReceived,
|
linkReceived: (url: string) =>
|
||||||
|
{
|
||||||
|
const parts = url.split('/');
|
||||||
|
|
||||||
|
if(parts.length < 2) return;
|
||||||
|
|
||||||
|
switch(parts[1])
|
||||||
|
{
|
||||||
|
case 'show':
|
||||||
|
setIsVisible(true);
|
||||||
|
return;
|
||||||
|
case 'hide':
|
||||||
|
setIsVisible(false);
|
||||||
|
return;
|
||||||
|
case 'toggle':
|
||||||
|
setIsVisible(prevValue => !prevValue);
|
||||||
|
return;
|
||||||
|
case 'open':
|
||||||
|
if(parts.length > 2)
|
||||||
|
{
|
||||||
|
if(parts.length === 4)
|
||||||
|
{
|
||||||
|
switch(parts[2])
|
||||||
|
{
|
||||||
|
case 'offerId':
|
||||||
|
openPageByOfferId(parseInt(parts[3]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openPageByName(parts[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setIsVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
eventUrlPrefix: 'catalog/'
|
eventUrlPrefix: 'catalog/'
|
||||||
};
|
};
|
||||||
|
|
||||||
AddEventLinkTracker(linkTracker);
|
AddEventLinkTracker(linkTracker);
|
||||||
|
|
||||||
return () => RemoveLinkEventTracker(linkTracker);
|
return () => RemoveLinkEventTracker(linkTracker);
|
||||||
}, [ linkReceived ]);
|
}, [ setIsVisible, openPageByOfferId, openPageByName ]);
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
setRoomPreviewer(new RoomPreviewer(GetRoomEngine(), ++RoomPreviewer.PREVIEW_COUNTER));
|
|
||||||
|
|
||||||
return () =>
|
|
||||||
{
|
|
||||||
setRoomPreviewer(prevValue =>
|
|
||||||
{
|
|
||||||
prevValue.dispose();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!isVisible || rootNode) return;
|
|
||||||
|
|
||||||
SendMessageComposer(new GetGiftWrappingConfigurationComposer());
|
|
||||||
SendMessageComposer(new GetClubGiftInfo());
|
|
||||||
SendMessageComposer(new GetCatalogIndexComposer(currentType));
|
|
||||||
}, [ isVisible, rootNode, currentType ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!isVisible || !rootNode) return;
|
|
||||||
|
|
||||||
switch(REQUESTED_PAGE.requestType)
|
|
||||||
{
|
|
||||||
case RequestedPage.REQUEST_TYPE_NONE:
|
|
||||||
if(activeNodes && activeNodes.length) return;
|
|
||||||
|
|
||||||
if(rootNode.isBranch)
|
|
||||||
{
|
|
||||||
for(const child of rootNode.children)
|
|
||||||
{
|
|
||||||
if(child && child.isVisible)
|
|
||||||
{
|
|
||||||
activateNode(child);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case RequestedPage.REQUEST_TYPE_ID:
|
|
||||||
openPageById(REQUESTED_PAGE.requestById);
|
|
||||||
REQUESTED_PAGE.resetRequest();
|
|
||||||
return;
|
|
||||||
case RequestedPage.REQUEST_TYPE_OFFER:
|
|
||||||
openPageByOfferId(REQUESTED_PAGE.requestedByOfferId);
|
|
||||||
REQUESTED_PAGE.resetRequest();
|
|
||||||
return;
|
|
||||||
case RequestedPage.REQUEST_TYPE_NAME:
|
|
||||||
openPageByName(REQUESTED_PAGE.requestByName);
|
|
||||||
REQUESTED_PAGE.resetRequest();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, [ isVisible, rootNode, activeNodes, activateNode, openPageById, openPageByOfferId, openPageByName ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
if(!searchResult && currentPage && (currentPage.pageId === -1)) openPageById(previousPageId);
|
|
||||||
}, [ searchResult, currentPage, previousPageId, openPageById ]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
return () => setCurrentOffer(null);
|
|
||||||
}, [ currentPage ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CatalogContextProvider value={ { isVisible, isBusy, setIsBusy, pageId, currentType, setCurrentType, rootNode, setRootNode, offersToNodes, setOffersToNodes, currentPage, setCurrentPage, currentOffer, setCurrentOffer, activeNodes, setActiveNodes, searchResult, setSearchResult, frontPageItems, setFrontPageItems, roomPreviewer, purchaseOptions, setPurchaseOptions, catalogOptions, setCatalogOptions, resetState, getNodesByOfferId, loadCatalogPage, showCatalogPage, activateNode } }>
|
<>
|
||||||
<CatalogMessageHandler />
|
|
||||||
{ isVisible &&
|
{ isVisible &&
|
||||||
<NitroCardView uniqueKey="catalog" className="nitro-catalog">
|
<NitroCardView uniqueKey="catalog" className="nitro-catalog">
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('catalog.title') } onCloseClick={ event =>
|
<NitroCardHeaderView headerText={ LocalizeText('catalog.title') } onCloseClick={ event => setIsVisible(false) } />
|
||||||
{
|
|
||||||
setIsVisible(false);
|
|
||||||
} } />
|
|
||||||
<NitroCardTabsView>
|
<NitroCardTabsView>
|
||||||
{ rootNode && (rootNode.children.length > 0) && rootNode.children.map(child =>
|
{ rootNode && (rootNode.children.length > 0) && rootNode.children.map(child =>
|
||||||
{
|
{
|
||||||
@ -433,6 +102,6 @@ export const CatalogView: FC<{}> = props =>
|
|||||||
</NitroCardView> }
|
</NitroCardView> }
|
||||||
<CatalogGiftView />
|
<CatalogGiftView />
|
||||||
<MarketplacePostOfferView />
|
<MarketplacePostOfferView />
|
||||||
</CatalogContextProvider>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
import { CatalogPageMessageOfferData, RoomObjectCategory, RoomObjectPlacementSource } from '@nitrots/nitro-renderer';
|
|
||||||
import { GetRoomEngine, ProductTypeEnum } from '../../../api';
|
|
||||||
import { IsCatalogOfferDraggable } from './IsCatalogOfferDraggable';
|
|
||||||
|
|
||||||
export const AttemptCatalogPlacement = (offer: CatalogPageMessageOfferData) =>
|
|
||||||
{
|
|
||||||
if(!IsCatalogOfferDraggable(offer)) return;
|
|
||||||
|
|
||||||
const product = offer.products[0];
|
|
||||||
|
|
||||||
let category: number = -1;
|
|
||||||
|
|
||||||
switch(product.productType)
|
|
||||||
{
|
|
||||||
case ProductTypeEnum.FLOOR:
|
|
||||||
category = RoomObjectCategory.FLOOR;
|
|
||||||
break;
|
|
||||||
case ProductTypeEnum.WALL:
|
|
||||||
category = RoomObjectCategory.WALL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(category === -1) return;
|
|
||||||
|
|
||||||
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.CATALOG, -(offer.offerId), category, product.furniClassId, (product.extraParam) ? product.extraParam.toString() : null))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
export class FurniCategory
|
|
||||||
{
|
|
||||||
public static DEFAULT: number = 1;
|
|
||||||
public static WALL_PAPER: number = 2;
|
|
||||||
public static FLOOR: number = 3;
|
|
||||||
public static LANDSCAPE: number = 4;
|
|
||||||
public static POST_IT: number = 5;
|
|
||||||
public static POSTER: number = 6;
|
|
||||||
public static SOUND_SET: number = 7;
|
|
||||||
public static TRAX_SONG: number = 8;
|
|
||||||
public static PRESENT: number = 9;
|
|
||||||
public static ECOTRON_BOX: number = 10;
|
|
||||||
public static TROPHY: number = 11;
|
|
||||||
public static CREDIT_FURNI: number = 12;
|
|
||||||
public static PET_SHAMPOO: number = 13;
|
|
||||||
public static PET_CUSTOM_PART: number = 14;
|
|
||||||
public static PET_CUSTOM_PART_SHAMPOO: number = 15;
|
|
||||||
public static PET_SADDLE: number = 16;
|
|
||||||
public static GUILD_FURNI: number = 17;
|
|
||||||
public static GAME_FURNI: number = 18;
|
|
||||||
public static MONSTERPLANT_SEED: number = 19;
|
|
||||||
public static MONSTERPLANT_REVIVAL: number = 20;
|
|
||||||
public static MONSTERPLANT_REBREED: number = 21;
|
|
||||||
public static MONSTERPLANT_FERTILIZE: number = 22;
|
|
||||||
public static FIGURE_PURCHASABLE_SET: number = 23;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { CatalogPageMessageOfferData, RoomControllerLevel } from '@nitrots/nitro-renderer';
|
|
||||||
import { GetRoomSession, ProductTypeEnum } from '../../../api';
|
|
||||||
|
|
||||||
export const IsCatalogOfferDraggable = (offer: CatalogPageMessageOfferData) =>
|
|
||||||
{
|
|
||||||
return ((GetRoomSession().isRoomOwner || (GetRoomSession().isGuildRoom && (GetRoomSession().controllerLevel >= RoomControllerLevel.GUILD_MEMBER))) && (offer.products.length === 1) && (offer.products[0].productType !== ProductTypeEnum.EFFECT) && (offer.products[0].productType !== ProductTypeEnum.HABBO_CLUB))
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
import { GetNitroInstance } from '../../../api';
|
|
||||||
import { IPurse } from './IPurse';
|
|
||||||
|
|
||||||
export class Purse implements IPurse
|
|
||||||
{
|
|
||||||
private _credits: number = 0;
|
|
||||||
private _activityPoints: Map<number, number>;
|
|
||||||
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 = GetNitroInstance().time;
|
|
||||||
this._credits = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get clubDays(): number
|
|
||||||
{
|
|
||||||
return this._clubDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set clubDays(k: number)
|
|
||||||
{
|
|
||||||
this._lastUpdated = GetNitroInstance().time;
|
|
||||||
this._clubDays = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get clubPeriods(): number
|
|
||||||
{
|
|
||||||
return this._clubPeriods;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set clubPeriods(k: number)
|
|
||||||
{
|
|
||||||
this._lastUpdated = GetNitroInstance().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 = GetNitroInstance().time;
|
|
||||||
this._pastClubDays = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get _Str_4605(): number
|
|
||||||
{
|
|
||||||
return this._pastVipDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set _Str_4605(k: number)
|
|
||||||
{
|
|
||||||
this._lastUpdated = GetNitroInstance().time;
|
|
||||||
this._pastVipDays = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get _Str_18527(): Map<number, number>
|
|
||||||
{
|
|
||||||
return this._activityPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set _Str_18527(k: Map<number, number>)
|
|
||||||
{
|
|
||||||
this._lastUpdated = GetNitroInstance().time;
|
|
||||||
this._activityPoints = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public _Str_5590(k: number): number
|
|
||||||
{
|
|
||||||
return this._activityPoints[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
public set _Str_4458(k: number)
|
|
||||||
{
|
|
||||||
this._lastUpdated = GetNitroInstance().time;
|
|
||||||
|
|
||||||
this._minutesUntilExpiration = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get _Str_4458(): number
|
|
||||||
{
|
|
||||||
const k = ((GetNitroInstance().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 = GetNitroInstance().time;
|
|
||||||
this._minutesSinceLastModified = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get _Str_6312(): number
|
|
||||||
{
|
|
||||||
return this._minutesSinceLastModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get _Str_26225(): number
|
|
||||||
{
|
|
||||||
return this._lastUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
export class SubscriptionInfo
|
|
||||||
{
|
|
||||||
private _lastUpdated: number;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public readonly clubDays: number = 0,
|
|
||||||
public readonly clubPeriods: number = 0,
|
|
||||||
public readonly isVip: boolean = false,
|
|
||||||
public readonly pastDays: number = 0,
|
|
||||||
public readonly pastVipDays: number = 0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public get lastUpdated(): number
|
|
||||||
{
|
|
||||||
return this._lastUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
10
src/components/catalog/views/CatalogPurchaseConfirmView.tsx
Normal file
10
src/components/catalog/views/CatalogPurchaseConfirmView.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
|
||||||
|
export const CatalogPurchaseConfirmView: FC<{}> = props =>
|
||||||
|
{
|
||||||
|
const {} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div></div>
|
||||||
|
);
|
||||||
|
}
|
@ -5,8 +5,7 @@ import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { GetSessionDataManager, LocalizeText, ProductTypeEnum, SendMessageComposer } from '../../../../api';
|
import { GetSessionDataManager, LocalizeText, ProductTypeEnum, SendMessageComposer } from '../../../../api';
|
||||||
import { Base, Button, ButtonGroup, Column, Flex, FormGroup, LayoutCurrencyIcon, LayoutFurniImageView, LayoutGiftTagView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
|
import { Base, Button, ButtonGroup, Column, Flex, FormGroup, LayoutCurrencyIcon, LayoutFurniImageView, LayoutGiftTagView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
|
||||||
import { CatalogEvent, CatalogInitGiftEvent, CatalogPurchasedEvent } from '../../../../events';
|
import { CatalogEvent, CatalogInitGiftEvent, CatalogPurchasedEvent } from '../../../../events';
|
||||||
import { UseUiEvent } from '../../../../hooks';
|
import { useCatalog, UseUiEvent } from '../../../../hooks';
|
||||||
import { useCatalogContext } from '../../CatalogContext';
|
|
||||||
|
|
||||||
export const CatalogGiftView: FC<{}> = props =>
|
export const CatalogGiftView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
@ -24,7 +23,7 @@ export const CatalogGiftView: FC<{}> = props =>
|
|||||||
const [ maxBoxIndex, setMaxBoxIndex ] = useState<number>(0);
|
const [ maxBoxIndex, setMaxBoxIndex ] = useState<number>(0);
|
||||||
const [ maxRibbonIndex, setMaxRibbonIndex ] = useState<number>(0);
|
const [ maxRibbonIndex, setMaxRibbonIndex ] = useState<number>(0);
|
||||||
const [ receiverNotFound, setReceiverNotFound ] = useState<boolean>(false);
|
const [ receiverNotFound, setReceiverNotFound ] = useState<boolean>(false);
|
||||||
const { catalogOptions = null } = useCatalogContext();
|
const { catalogOptions = null } = useCatalog();
|
||||||
const { giftConfiguration = null } = catalogOptions;
|
const { giftConfiguration = null } = catalogOptions;
|
||||||
|
|
||||||
const close = useCallback(() =>
|
const close = useCallback(() =>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { LayoutGridItem } from '../../../../common/layout/LayoutGridItem';
|
import { ICatalogNode } from '../../../../api';
|
||||||
import { Text } from '../../../../common/Text';
|
import { LayoutGridItem, Text } from '../../../../common';
|
||||||
import { useCatalogContext } from '../../CatalogContext';
|
import { useCatalog } from '../../../../hooks';
|
||||||
import { ICatalogNode } from '../../common/ICatalogNode';
|
|
||||||
import { CatalogIconView } from '../catalog-icon/CatalogIconView';
|
import { CatalogIconView } from '../catalog-icon/CatalogIconView';
|
||||||
import { CatalogNavigationSetView } from './CatalogNavigationSetView';
|
import { CatalogNavigationSetView } from './CatalogNavigationSetView';
|
||||||
|
|
||||||
@ -15,7 +14,7 @@ export interface CatalogNavigationItemViewProps
|
|||||||
export const CatalogNavigationItemView: FC<CatalogNavigationItemViewProps> = props =>
|
export const CatalogNavigationItemView: FC<CatalogNavigationItemViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { node = null } = props;
|
const { node = null } = props;
|
||||||
const { activateNode = null } = useCatalogContext();
|
const { activateNode = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { ICatalogNode } from '../../common/ICatalogNode';
|
import { ICatalogNode } from '../../../../api';
|
||||||
import { CatalogNavigationItemView } from './CatalogNavigationItemView';
|
import { CatalogNavigationItemView } from './CatalogNavigationItemView';
|
||||||
|
|
||||||
export interface CatalogNavigationSetViewProps
|
export interface CatalogNavigationSetViewProps
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { AutoGrid } from '../../../../common/AutoGrid';
|
import { ICatalogNode } from '../../../../api';
|
||||||
import { Column } from '../../../../common/Column';
|
import { AutoGrid, Column } from '../../../../common';
|
||||||
import { useCatalogContext } from '../../CatalogContext';
|
import { useCatalog } from '../../../../hooks';
|
||||||
import { ICatalogNode } from '../../common/ICatalogNode';
|
|
||||||
import { CatalogSearchView } from '../page/common/CatalogSearchView';
|
import { CatalogSearchView } from '../page/common/CatalogSearchView';
|
||||||
import { CatalogNavigationItemView } from './CatalogNavigationItemView';
|
import { CatalogNavigationItemView } from './CatalogNavigationItemView';
|
||||||
import { CatalogNavigationSetView } from './CatalogNavigationSetView';
|
import { CatalogNavigationSetView } from './CatalogNavigationSetView';
|
||||||
@ -15,7 +14,7 @@ export interface CatalogNavigationViewProps
|
|||||||
export const CatalogNavigationView: FC<CatalogNavigationViewProps> = props =>
|
export const CatalogNavigationView: FC<CatalogNavigationViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { node = null } = props;
|
const { node = null } = props;
|
||||||
const { searchResult = null } = useCatalogContext();
|
const { searchResult = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
import { FC, useMemo } from 'react';
|
import { MouseEventType } from '@nitrots/nitro-renderer';
|
||||||
import { ProductTypeEnum } from '../../../../../api';
|
import { FC, MouseEvent, useMemo, useState } from 'react';
|
||||||
|
import { IPurchasableOffer, Offer, ProductTypeEnum } from '../../../../../api';
|
||||||
import { LayoutAvatarImageView, LayoutGridItem, LayoutGridItemProps } from '../../../../../common';
|
import { LayoutAvatarImageView, LayoutGridItem, LayoutGridItemProps } from '../../../../../common';
|
||||||
import { IPurchasableOffer } from '../../../common/IPurchasableOffer';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { Offer } from '../../../common/Offer';
|
|
||||||
|
|
||||||
interface CatalogGridOfferViewProps extends LayoutGridItemProps
|
interface CatalogGridOfferViewProps extends LayoutGridItemProps
|
||||||
{
|
{
|
||||||
offer: IPurchasableOffer;
|
offer: IPurchasableOffer;
|
||||||
|
selectOffer: (offer: IPurchasableOffer) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
|
export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { offer = null, ...rest } = props;
|
const { offer = null, selectOffer = null, itemActive = false, ...rest } = props;
|
||||||
|
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||||
|
const { requestOfferToMover = null } = useCatalog();
|
||||||
|
|
||||||
const iconUrl = useMemo(() =>
|
const iconUrl = useMemo(() =>
|
||||||
{
|
{
|
||||||
@ -23,12 +26,31 @@ export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
|
|||||||
return offer.product.getIconUrl(offer);
|
return offer.product.getIconUrl(offer);
|
||||||
}, [ offer ]);
|
}, [ offer ]);
|
||||||
|
|
||||||
|
const onMouseEvent = (event: MouseEvent) =>
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case MouseEventType.MOUSE_DOWN:
|
||||||
|
selectOffer(offer);
|
||||||
|
setMouseDown(true);
|
||||||
|
return;
|
||||||
|
case MouseEventType.MOUSE_UP:
|
||||||
|
setMouseDown(false);
|
||||||
|
return;
|
||||||
|
case MouseEventType.ROLL_OUT:
|
||||||
|
if(!isMouseDown || !itemActive) return;
|
||||||
|
|
||||||
|
requestOfferToMover(offer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const product = offer.product;
|
const product = offer.product;
|
||||||
|
|
||||||
if(!product) return null;
|
if(!product) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutGridItem itemImage={ iconUrl } itemCount={ ((offer.pricingModel === Offer.PRICING_MODEL_MULTI) ? product.productCount : 1) } itemUniqueSoldout={ (product.uniqueLimitedItemSeriesSize && !product.uniqueLimitedItemsLeft) } itemUniqueNumber={ product.uniqueLimitedItemSeriesSize } { ...rest }>
|
<LayoutGridItem itemImage={ iconUrl } itemCount={ ((offer.pricingModel === Offer.PRICING_MODEL_MULTI) ? product.productCount : 1) } itemUniqueSoldout={ (product.uniqueLimitedItemSeriesSize && !product.uniqueLimitedItemsLeft) } itemUniqueNumber={ product.uniqueLimitedItemSeriesSize } itemActive={ itemActive } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } { ...rest }>
|
||||||
{ (offer.product.productType === ProductTypeEnum.ROBOT) &&
|
{ (offer.product.productType === ProductTypeEnum.ROBOT) &&
|
||||||
<LayoutAvatarImageView figure={ offer.product.extraParam } headOnly={ true } direction={ 3 } /> }
|
<LayoutAvatarImageView figure={ offer.product.extraParam } headOnly={ true } direction={ 3 } /> }
|
||||||
</LayoutGridItem>
|
</LayoutGridItem>
|
||||||
|
@ -1,25 +1,15 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { IFurnitureData } from '@nitrots/nitro-renderer';
|
import { IFurnitureData } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { GetSessionDataManager, LocalizeText } from '../../../../../api';
|
import { CatalogPage, CatalogType, FilterCatalogNode, FurnitureOffer, GetOfferNodes, GetSessionDataManager, ICatalogNode, ICatalogPage, IPurchasableOffer, LocalizeText, PageLocalization, SearchResult } from '../../../../../api';
|
||||||
import { Button } from '../../../../../common/Button';
|
import { Button, Flex } from '../../../../../common';
|
||||||
import { Flex } from '../../../../../common/Flex';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
import { CatalogPage } from '../../../common/CatalogPage';
|
|
||||||
import { CatalogType } from '../../../common/CatalogType';
|
|
||||||
import { FilterCatalogNode, GetOfferNodes } from '../../../common/CatalogUtilities';
|
|
||||||
import { FurnitureOffer } from '../../../common/FurnitureOffer';
|
|
||||||
import { ICatalogNode } from '../../../common/ICatalogNode';
|
|
||||||
import { ICatalogPage } from '../../../common/ICatalogPage';
|
|
||||||
import { IPurchasableOffer } from '../../../common/IPurchasableOffer';
|
|
||||||
import { PageLocalization } from '../../../common/PageLocalization';
|
|
||||||
import { SearchResult } from '../../../common/SearchResult';
|
|
||||||
|
|
||||||
export const CatalogSearchView: FC<{}> = props =>
|
export const CatalogSearchView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ searchValue, setSearchValue ] = useState('');
|
const [ searchValue, setSearchValue ] = useState('');
|
||||||
const [ needsProcessing, setNeedsProcessing ] = useState(false);
|
const [ needsProcessing, setNeedsProcessing ] = useState(false);
|
||||||
const { currentType = null, rootNode = null, setActiveNodes = null, offersToNodes = null, searchResult = null, setSearchResult = null, setCurrentPage = null } = useCatalogContext();
|
const { currentType = null, rootNode = null, offersToNodes = null, searchResult = null, setSearchResult = null, setCurrentPage = null } = useCatalog();
|
||||||
|
|
||||||
const updateSearchValue = (value: string) =>
|
const updateSearchValue = (value: string) =>
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ICatalogPage } from '../../../common/ICatalogPage';
|
import { ICatalogPage } from '../../../../../api';
|
||||||
|
|
||||||
export interface CatalogLayoutProps
|
export interface CatalogLayoutProps
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { LocalizeText } from '../../../../../api';
|
import { LocalizeText } from '../../../../../api';
|
||||||
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { CatalogBadgeSelectorWidgetView } from '../widgets/CatalogBadgeSelectorWidgetView';
|
import { CatalogBadgeSelectorWidgetView } from '../widgets/CatalogBadgeSelectorWidgetView';
|
||||||
import { CatalogFirstProductSelectorWidgetView } from '../widgets/CatalogFirstProductSelectorWidgetView';
|
import { CatalogFirstProductSelectorWidgetView } from '../widgets/CatalogFirstProductSelectorWidgetView';
|
||||||
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
||||||
@ -14,7 +14,7 @@ import { CatalogLayoutProps } from './CatalogLayout.types';
|
|||||||
export const CatalogLayoutBadgeDisplayView: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayoutBadgeDisplayView: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const { page = null } = props;
|
const { page = null } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { CatalogAddOnBadgeWidgetView } from '../widgets/CatalogAddOnBadgeWidgetView';
|
import { CatalogAddOnBadgeWidgetView } from '../widgets/CatalogAddOnBadgeWidgetView';
|
||||||
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
||||||
import { CatalogLimitedItemWidgetView } from '../widgets/CatalogLimitedItemWidgetView';
|
import { CatalogLimitedItemWidgetView } from '../widgets/CatalogLimitedItemWidgetView';
|
||||||
@ -13,7 +13,7 @@ import { CatalogLayoutProps } from './CatalogLayout.types';
|
|||||||
export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const { page = null } = props;
|
const { page = null } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid>
|
<Grid>
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Base } from '../../../../../common/Base';
|
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
||||||
import { Column } from '../../../../../common/Column';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { Flex } from '../../../../../common/Flex';
|
|
||||||
import { Grid } from '../../../../../common/Grid';
|
|
||||||
import { Text } from '../../../../../common/Text';
|
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
import { CatalogGuildBadgeWidgetView } from '../widgets/CatalogGuildBadgeWidgetView';
|
import { CatalogGuildBadgeWidgetView } from '../widgets/CatalogGuildBadgeWidgetView';
|
||||||
import { CatalogGuildSelectorWidgetView } from '../widgets/CatalogGuildSelectorWidgetView';
|
import { CatalogGuildSelectorWidgetView } from '../widgets/CatalogGuildSelectorWidgetView';
|
||||||
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
||||||
@ -16,7 +12,7 @@ import { CatalogLayoutProps } from './CatalogLayout.types';
|
|||||||
export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const { page = null } = props;
|
const { page = null } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid>
|
<Grid>
|
||||||
|
@ -2,7 +2,7 @@ import { CatalogGroupsComposer } from '@nitrots/nitro-renderer';
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { SendMessageComposer } from '../../../../../api';
|
import { SendMessageComposer } from '../../../../../api';
|
||||||
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { CatalogFirstProductSelectorWidgetView } from '../widgets/CatalogFirstProductSelectorWidgetView';
|
import { CatalogFirstProductSelectorWidgetView } from '../widgets/CatalogFirstProductSelectorWidgetView';
|
||||||
import { CatalogGuildSelectorWidgetView } from '../widgets/CatalogGuildSelectorWidgetView';
|
import { CatalogGuildSelectorWidgetView } from '../widgets/CatalogGuildSelectorWidgetView';
|
||||||
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
||||||
@ -13,7 +13,7 @@ export const CatalogLayouGuildForumView: FC<CatalogLayoutProps> = props =>
|
|||||||
{
|
{
|
||||||
const { page = null } = props;
|
const { page = null } = props;
|
||||||
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState<number>(0);
|
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState<number>(0);
|
||||||
const { currentOffer = null, setCurrentOffer = null, catalogOptions = null } = useCatalogContext();
|
const { currentOffer = null, setCurrentOffer = null, catalogOptions = null } = useCatalog();
|
||||||
const { groups = null } = catalogOptions;
|
const { groups = null } = catalogOptions;
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import { NitroPoint } from '@nitrots/nitro-renderer';
|
import { NitroPoint } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { Base } from '../../../../../common/Base';
|
import { Base, Column, Flex, Grid, Text } from '../../../../../common';
|
||||||
import { Column } from '../../../../../common/Column';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { Flex } from '../../../../../common/Flex';
|
|
||||||
import { Grid } from '../../../../../common/Grid';
|
|
||||||
import { Text } from '../../../../../common/Text';
|
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
||||||
import { CatalogSpacesWidgetView } from '../widgets/CatalogSpacesWidgetView';
|
import { CatalogSpacesWidgetView } from '../widgets/CatalogSpacesWidgetView';
|
||||||
import { CatalogTotalPriceWidget } from '../widgets/CatalogTotalPriceWidget';
|
import { CatalogTotalPriceWidget } from '../widgets/CatalogTotalPriceWidget';
|
||||||
@ -15,7 +11,7 @@ import { CatalogLayoutProps } from './CatalogLayout.types';
|
|||||||
export const CatalogLayoutSpacesView: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayoutSpacesView: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const { page = null } = props;
|
const { page = null } = props;
|
||||||
const { currentOffer = null, roomPreviewer = null } = useCatalogContext();
|
const { currentOffer = null, roomPreviewer = null } = useCatalog();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { Column } from '../../../../../common/Column';
|
import { Column, Flex, Grid, Text } from '../../../../../common';
|
||||||
import { Flex } from '../../../../../common/Flex';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { Grid } from '../../../../../common/Grid';
|
|
||||||
import { Text } from '../../../../../common/Text';
|
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
||||||
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
||||||
import { CatalogTotalPriceWidget } from '../widgets/CatalogTotalPriceWidget';
|
import { CatalogTotalPriceWidget } from '../widgets/CatalogTotalPriceWidget';
|
||||||
@ -14,7 +11,7 @@ export const CatalogLayoutTrophiesView: FC<CatalogLayoutProps> = props =>
|
|||||||
{
|
{
|
||||||
const { page = null } = props;
|
const { page = null } = props;
|
||||||
const [ trophyText, setTrophyText ] = useState<string>('');
|
const [ trophyText, setTrophyText ] = useState<string>('');
|
||||||
const { currentOffer = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, setPurchaseOptions = null } = useCatalog();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
import { ClubOfferData, GetClubOffersMessageComposer, PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer';
|
import { ClubOfferData, GetClubOffersMessageComposer, PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { LocalizeText, SendMessageComposer } from '../../../../../api';
|
import { CatalogPurchaseState, LocalizeText, SendMessageComposer } from '../../../../../api';
|
||||||
import { AutoGrid, Button, Column, Flex, Grid, LayoutCurrencyIcon, LayoutGridItem, LayoutLoadingSpinnerView, Text } from '../../../../../common';
|
import { AutoGrid, Button, Column, Flex, Grid, LayoutCurrencyIcon, LayoutGridItem, LayoutLoadingSpinnerView, Text } from '../../../../../common';
|
||||||
import { CatalogEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent } from '../../../../../events';
|
import { CatalogEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent } from '../../../../../events';
|
||||||
import { usePurse, UseUiEvent } from '../../../../../hooks';
|
import { useCatalog, usePurse, UseUiEvent } from '../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
|
|
||||||
import { CatalogLayoutProps } from './CatalogLayout.types';
|
import { CatalogLayoutProps } from './CatalogLayout.types';
|
||||||
|
|
||||||
export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const [ pendingOffer, setPendingOffer ] = useState<ClubOfferData>(null);
|
const [ pendingOffer, setPendingOffer ] = useState<ClubOfferData>(null);
|
||||||
const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
|
const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
|
||||||
const { currentPage = null, catalogOptions = null } = useCatalogContext();
|
const { currentPage = null, catalogOptions = null } = useCatalog();
|
||||||
const { purse = null, getCurrencyAmount = null } = usePurse();
|
const { purse = null, getCurrencyAmount = null } = usePurse();
|
||||||
const { clubOffers = null } = catalogOptions;
|
const { clubOffers = null } = catalogOptions;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ICatalogPage } from '../../../common/ICatalogPage';
|
import { ICatalogPage } from '../../../../../api';
|
||||||
import { CatalogLayoutProps } from './CatalogLayout.types';
|
import { CatalogLayoutProps } from './CatalogLayout.types';
|
||||||
import { CatalogLayoutBadgeDisplayView } from './CatalogLayoutBadgeDisplayView';
|
import { CatalogLayoutBadgeDisplayView } from './CatalogLayoutBadgeDisplayView';
|
||||||
import { CatalogLayoutDefaultView } from './CatalogLayoutDefaultView';
|
import { CatalogLayoutDefaultView } from './CatalogLayoutDefaultView';
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { FrontPageItem } from '@nitrots/nitro-renderer';
|
import { FrontPageItem } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect } from 'react';
|
import { FC, useCallback, useEffect } from 'react';
|
||||||
import { CreateLinkEvent } from '../../../../../../api';
|
import { CreateLinkEvent } from '../../../../../../api';
|
||||||
import { Column } from '../../../../../../common/Column';
|
import { Column, Grid } from '../../../../../../common';
|
||||||
import { Grid } from '../../../../../../common/Grid';
|
import { useCatalog } from '../../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../../CatalogContext';
|
|
||||||
import { CatalogRedeemVoucherView } from '../../common/CatalogRedeemVoucherView';
|
import { CatalogRedeemVoucherView } from '../../common/CatalogRedeemVoucherView';
|
||||||
import { CatalogLayoutProps } from '../CatalogLayout.types';
|
import { CatalogLayoutProps } from '../CatalogLayout.types';
|
||||||
import { CatalogLayoutFrontPageItemView } from './CatalogLayoutFrontPageItemView';
|
import { CatalogLayoutFrontPageItemView } from './CatalogLayoutFrontPageItemView';
|
||||||
@ -11,7 +10,7 @@ import { CatalogLayoutFrontPageItemView } from './CatalogLayoutFrontPageItemView
|
|||||||
export const CatalogLayoutFrontpage4View: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayoutFrontpage4View: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const { page = null, hideNavigation = null } = props;
|
const { page = null, hideNavigation = null } = props;
|
||||||
const { frontPageItems = [] } = useCatalogContext();
|
const { frontPageItems = [] } = useCatalog();
|
||||||
|
|
||||||
const selectItem = useCallback((item: FrontPageItem) =>
|
const selectItem = useCallback((item: FrontPageItem) =>
|
||||||
{
|
{
|
||||||
|
@ -3,14 +3,13 @@ import { FC, useCallback, useEffect, useState } from 'react';
|
|||||||
import { FurnitureItem, LocalizeText, NotificationUtilities, ProductTypeEnum, SendMessageComposer } from '../../../../../../api';
|
import { FurnitureItem, LocalizeText, NotificationUtilities, ProductTypeEnum, SendMessageComposer } from '../../../../../../api';
|
||||||
import { Base, Button, Column, Grid, LayoutFurniImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../../common';
|
import { Base, Button, Column, Grid, LayoutFurniImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../../common';
|
||||||
import { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
|
import { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
|
||||||
import { UseMessageEventHook, UseUiEvent } from '../../../../../../hooks';
|
import { useCatalog, UseMessageEventHook, UseUiEvent } from '../../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../../CatalogContext';
|
|
||||||
|
|
||||||
export const MarketplacePostOfferView : FC<{}> = props =>
|
export const MarketplacePostOfferView : FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ item, setItem ] = useState<FurnitureItem>(null);
|
const [ item, setItem ] = useState<FurnitureItem>(null);
|
||||||
const [ askingPrice, setAskingPrice ] = useState(0);
|
const [ askingPrice, setAskingPrice ] = useState(0);
|
||||||
const { catalogOptions = null, setCatalogOptions = null } = useCatalogContext();
|
const { catalogOptions = null, setCatalogOptions = null } = useCatalog();
|
||||||
const { marketplaceConfiguration = null } = catalogOptions;
|
const { marketplaceConfiguration = null } = catalogOptions;
|
||||||
|
|
||||||
const onMarketplaceConfigurationEvent = useCallback((event: MarketplaceConfigurationEvent) =>
|
const onMarketplaceConfigurationEvent = useCallback((event: MarketplaceConfigurationEvent) =>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { ApproveNameMessageComposer } from '@nitrots/nitro-renderer';
|
import { ApproveNameMessageComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { LocalizeText, SendMessageComposer } from '../../../../../../api';
|
import { IPurchasableOffer, LocalizeText, Offer, SendMessageComposer } from '../../../../../../api';
|
||||||
import { Column, Flex, LayoutCurrencyIcon, Text } from '../../../../../../common';
|
import { Column, Flex, LayoutCurrencyIcon, Text } from '../../../../../../common';
|
||||||
import { CatalogPurchasedEvent } from '../../../../../../events';
|
import { CatalogPurchasedEvent } from '../../../../../../events';
|
||||||
import { UseUiEvent } from '../../../../../../hooks';
|
import { UseUiEvent } from '../../../../../../hooks';
|
||||||
import { IPurchasableOffer } from '../../../../common/IPurchasableOffer';
|
|
||||||
import { Offer } from '../../../../common/Offer';
|
|
||||||
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
|
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
|
||||||
import { CatalogPetNameApprovalView } from './CatalogPetNameApprovalView';
|
import { CatalogPetNameApprovalView } from './CatalogPetNameApprovalView';
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { ApproveNameMessageComposer, ColorConverter, GetSellablePetPalettesComposer, PurchaseFromCatalogComposer, SellablePetPaletteData } from '@nitrots/nitro-renderer';
|
import { ApproveNameMessageComposer, ColorConverter, GetSellablePetPalettesComposer, PurchaseFromCatalogComposer, SellablePetPaletteData } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { LocalizeText, SendMessageComposer } from '../../../../../../api';
|
import { GetPetAvailableColors, GetPetIndexFromLocalization, LocalizeText, SendMessageComposer } from '../../../../../../api';
|
||||||
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, LayoutPetImageView, Text } from '../../../../../../common';
|
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, LayoutPetImageView, Text } from '../../../../../../common';
|
||||||
import { CatalogNameResultEvent, CatalogPurchaseFailureEvent, CatalogWidgetEvent } from '../../../../../../events';
|
import { CatalogNameResultEvent, CatalogPurchaseFailureEvent, CatalogWidgetEvent } from '../../../../../../events';
|
||||||
import { DispatchUiEvent, UseUiEvent } from '../../../../../../hooks';
|
import { DispatchUiEvent, useCatalog, UseUiEvent } from '../../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../../CatalogContext';
|
|
||||||
import { GetPetAvailableColors, GetPetIndexFromLocalization } from '../../../../common/CatalogUtilities';
|
|
||||||
import { CatalogAddOnBadgeWidgetView } from '../../widgets/CatalogAddOnBadgeWidgetView';
|
import { CatalogAddOnBadgeWidgetView } from '../../widgets/CatalogAddOnBadgeWidgetView';
|
||||||
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
|
import { CatalogPurchaseWidgetView } from '../../widgets/CatalogPurchaseWidgetView';
|
||||||
import { CatalogTotalPriceWidget } from '../../widgets/CatalogTotalPriceWidget';
|
import { CatalogTotalPriceWidget } from '../../widgets/CatalogTotalPriceWidget';
|
||||||
@ -25,7 +23,7 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
|
|||||||
const [ petName, setPetName ] = useState('');
|
const [ petName, setPetName ] = useState('');
|
||||||
const [ approvalPending, setApprovalPending ] = useState(true);
|
const [ approvalPending, setApprovalPending ] = useState(true);
|
||||||
const [ approvalResult, setApprovalResult ] = useState(-1);
|
const [ approvalResult, setApprovalResult ] = useState(-1);
|
||||||
const { currentOffer = null, setCurrentOffer = null, setPurchaseOptions = null, catalogOptions = null, roomPreviewer = null } = useCatalogContext();
|
const { currentOffer = null, setCurrentOffer = null, setPurchaseOptions = null, catalogOptions = null, roomPreviewer = null } = useCatalog();
|
||||||
const { petPalettes = null } = catalogOptions;
|
const { petPalettes = null } = catalogOptions;
|
||||||
|
|
||||||
const getColor = useMemo(() =>
|
const getColor = useMemo(() =>
|
||||||
|
@ -2,15 +2,14 @@ import { SelectClubGiftComposer } from '@nitrots/nitro-renderer';
|
|||||||
import { FC, useCallback } from 'react';
|
import { FC, useCallback } from 'react';
|
||||||
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../../api';
|
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../../api';
|
||||||
import { AutoGrid, Text } from '../../../../../../common';
|
import { AutoGrid, Text } from '../../../../../../common';
|
||||||
import { usePurse } from '../../../../../../hooks';
|
import { useCatalog, usePurse } from '../../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../../CatalogContext';
|
|
||||||
import { CatalogLayoutProps } from '../CatalogLayout.types';
|
import { CatalogLayoutProps } from '../CatalogLayout.types';
|
||||||
import { VipGiftItem } from './VipGiftItemView';
|
import { VipGiftItem } from './VipGiftItemView';
|
||||||
|
|
||||||
export const CatalogLayoutVipGiftsView: FC<CatalogLayoutProps> = props =>
|
export const CatalogLayoutVipGiftsView: FC<CatalogLayoutProps> = props =>
|
||||||
{
|
{
|
||||||
const { purse = null } = usePurse();
|
const { purse = null } = usePurse();
|
||||||
const { catalogOptions = null, setCatalogOptions = null } = useCatalogContext();
|
const { catalogOptions = null, setCatalogOptions = null } = useCatalog();
|
||||||
const { clubGifts = null } = catalogOptions;
|
const { clubGifts = null } = catalogOptions;
|
||||||
|
|
||||||
const giftsAvailable = useCallback(() =>
|
const giftsAvailable = useCallback(() =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { BaseProps, LayoutBadgeImageView } from '../../../../../common';
|
import { BaseProps, LayoutBadgeImageView } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
|
|
||||||
interface CatalogAddOnBadgeWidgetViewProps extends BaseProps<HTMLDivElement>
|
interface CatalogAddOnBadgeWidgetViewProps extends BaseProps<HTMLDivElement>
|
||||||
{
|
{
|
||||||
@ -10,7 +10,7 @@ interface CatalogAddOnBadgeWidgetViewProps extends BaseProps<HTMLDivElement>
|
|||||||
export const CatalogAddOnBadgeWidgetView: FC<CatalogAddOnBadgeWidgetViewProps> = props =>
|
export const CatalogAddOnBadgeWidgetView: FC<CatalogAddOnBadgeWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { ...rest } = props;
|
const { ...rest } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
if(!currentOffer || !currentOffer.badgeCode || !currentOffer.badgeCode.length) return null;
|
if(!currentOffer || !currentOffer.badgeCode || !currentOffer.badgeCode.length) return null;
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { StringDataType } from '@nitrots/nitro-renderer';
|
import { StringDataType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { AutoGrid, AutoGridProps, LayoutBadgeImageView, LayoutGridItem } from '../../../../../common';
|
import { AutoGrid, AutoGridProps, LayoutBadgeImageView, LayoutGridItem } from '../../../../../common';
|
||||||
import { useInventoryBadges } from '../../../../../hooks';
|
import { useCatalog, useInventoryBadges } from '../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
|
|
||||||
const EXCLUDED_BADGE_CODES: string[] = [];
|
const EXCLUDED_BADGE_CODES: string[] = [];
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
|
|||||||
const { columnCount = 5, ...rest } = props;
|
const { columnCount = 5, ...rest } = props;
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const [ currentBadgeCode, setCurrentBadgeCode ] = useState<string>(null);
|
const [ currentBadgeCode, setCurrentBadgeCode ] = useState<string>(null);
|
||||||
const { currentOffer = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, setPurchaseOptions = null } = useCatalog();
|
||||||
const { badgeCodes = [], activate = null, deactivate = null } = useInventoryBadges();
|
const { badgeCodes = [], activate = null, deactivate = null } = useInventoryBadges();
|
||||||
|
|
||||||
const previewStuffData = useMemo(() =>
|
const previewStuffData = useMemo(() =>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { AutoGrid, AutoGridProps } from '../../../../../common/AutoGrid';
|
import { AutoGrid, AutoGridProps, LayoutGridItem } from '../../../../../common';
|
||||||
import { LayoutGridItem } from '../../../../../common/layout/LayoutGridItem';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
|
|
||||||
interface CatalogBundleGridWidgetViewProps extends AutoGridProps
|
interface CatalogBundleGridWidgetViewProps extends AutoGridProps
|
||||||
{
|
{
|
||||||
@ -11,7 +10,7 @@ interface CatalogBundleGridWidgetViewProps extends AutoGridProps
|
|||||||
export const CatalogBundleGridWidgetView: FC<CatalogBundleGridWidgetViewProps> = props =>
|
export const CatalogBundleGridWidgetView: FC<CatalogBundleGridWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { columnCount = 5, children = null, ...rest } = props;
|
const { columnCount = 5, children = null, ...rest } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
if(!currentOffer) return null;
|
if(!currentOffer) return null;
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
|
|
||||||
export const CatalogFirstProductSelectorWidgetView: FC<{}> = props =>
|
export const CatalogFirstProductSelectorWidgetView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { currentPage = null, setCurrentOffer = null } = useCatalogContext();
|
const { currentPage = null, setCurrentOffer = null } = useCatalog();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { StringDataType } from '@nitrots/nitro-renderer';
|
import { StringDataType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useMemo } from 'react';
|
import { FC, useMemo } from 'react';
|
||||||
import { BaseProps, LayoutBadgeImageView } from '../../../../../common';
|
import { BaseProps, LayoutBadgeImageView } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
|
|
||||||
interface CatalogGuildBadgeWidgetViewProps extends BaseProps<HTMLDivElement>
|
interface CatalogGuildBadgeWidgetViewProps extends BaseProps<HTMLDivElement>
|
||||||
{
|
{
|
||||||
@ -11,7 +11,7 @@ interface CatalogGuildBadgeWidgetViewProps extends BaseProps<HTMLDivElement>
|
|||||||
export const CatalogGuildBadgeWidgetView: FC<CatalogGuildBadgeWidgetViewProps> = props =>
|
export const CatalogGuildBadgeWidgetView: FC<CatalogGuildBadgeWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { ...rest } = props;
|
const { ...rest } = props;
|
||||||
const { currentOffer = null, purchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, purchaseOptions = null } = useCatalog();
|
||||||
const { previewStuffData = null } = purchaseOptions;
|
const { previewStuffData = null } = purchaseOptions;
|
||||||
|
|
||||||
const badgeCode = useMemo(() =>
|
const badgeCode = useMemo(() =>
|
||||||
|
@ -2,12 +2,12 @@ import { CatalogGroupsComposer, StringDataType } from '@nitrots/nitro-renderer';
|
|||||||
import { FC, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { LocalizeText, SendMessageComposer } from '../../../../../api';
|
import { LocalizeText, SendMessageComposer } from '../../../../../api';
|
||||||
import { Base, Button, Flex } from '../../../../../common';
|
import { Base, Button, Flex } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
|
|
||||||
export const CatalogGuildSelectorWidgetView: FC<{}> = props =>
|
export const CatalogGuildSelectorWidgetView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState<number>(0);
|
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState<number>(0);
|
||||||
const { currentOffer = null, catalogOptions = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, catalogOptions = null, setPurchaseOptions = null } = useCatalog();
|
||||||
const { groups = null } = catalogOptions;
|
const { groups = null } = catalogOptions;
|
||||||
|
|
||||||
const previewStuffData = useMemo(() =>
|
const previewStuffData = useMemo(() =>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { ProductTypeEnum } from '../../../../../api';
|
import { IPurchasableOffer, ProductTypeEnum } from '../../../../../api';
|
||||||
import { AutoGrid, AutoGridProps } from '../../../../../common';
|
import { AutoGrid, AutoGridProps } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { IPurchasableOffer } from '../../../common/IPurchasableOffer';
|
|
||||||
import { CatalogGridOfferView } from '../common/CatalogGridOfferView';
|
import { CatalogGridOfferView } from '../common/CatalogGridOfferView';
|
||||||
|
|
||||||
interface CatalogItemGridWidgetViewProps extends AutoGridProps
|
interface CatalogItemGridWidgetViewProps extends AutoGridProps
|
||||||
@ -13,7 +12,7 @@ interface CatalogItemGridWidgetViewProps extends AutoGridProps
|
|||||||
export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = props =>
|
export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { columnCount = 5, children = null, ...rest } = props;
|
const { columnCount = 5, children = null, ...rest } = props;
|
||||||
const { currentOffer = null, setCurrentOffer = null, currentPage = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, setCurrentOffer = null, currentPage = null, setPurchaseOptions = null } = useCatalog();
|
||||||
|
|
||||||
if(!currentPage) return null;
|
if(!currentPage) return null;
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = pro
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoGrid columnCount={ columnCount } { ...rest }>
|
<AutoGrid columnCount={ columnCount } { ...rest }>
|
||||||
{ currentPage.offers && (currentPage.offers.length > 0) && currentPage.offers.map((offer, index) => <CatalogGridOfferView key={ index } itemActive={ (currentOffer && (currentOffer.offerId === offer.offerId)) } offer={ offer } onClick={ event => selectOffer(offer) } />) }
|
{ currentPage.offers && (currentPage.offers.length > 0) && currentPage.offers.map((offer, index) => <CatalogGridOfferView key={ index } itemActive={ (currentOffer && (currentOffer.offerId === offer.offerId)) } offer={ offer } selectOffer={ selectOffer } />) }
|
||||||
{ children }
|
{ children }
|
||||||
</AutoGrid>
|
</AutoGrid>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { Offer } from '../../../../../api';
|
||||||
import { Base, BaseProps, LayoutLimitedEditionCompletePlateView } from '../../../../../common';
|
import { Base, BaseProps, LayoutLimitedEditionCompletePlateView } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { Offer } from '../../../common/Offer';
|
|
||||||
|
|
||||||
export const CatalogLimitedItemWidgetView: FC<BaseProps<HTMLDivElement>> = props =>
|
export const CatalogLimitedItemWidgetView: FC<BaseProps<HTMLDivElement>> = props =>
|
||||||
{
|
{
|
||||||
const { children = null, ...rest } = props;
|
const { children = null, ...rest } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
if(!currentOffer || (currentOffer.pricingModel !== Offer.PRICING_MODEL_SINGLE) || !currentOffer.product.isUniqueLimitedItem) return null;
|
if(!currentOffer || (currentOffer.pricingModel !== Offer.PRICING_MODEL_SINGLE) || !currentOffer.product.isUniqueLimitedItem) return null;
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { IPurchasableOffer } from '../../../../../api';
|
||||||
import { Flex, LayoutCurrencyIcon, Text } from '../../../../../common';
|
import { Flex, LayoutCurrencyIcon, Text } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { IPurchasableOffer } from '../../../common/IPurchasableOffer';
|
|
||||||
|
|
||||||
interface CatalogPriceDisplayWidgetViewProps
|
interface CatalogPriceDisplayWidgetViewProps
|
||||||
{
|
{
|
||||||
@ -13,7 +13,7 @@ interface CatalogPriceDisplayWidgetViewProps
|
|||||||
export const CatalogPriceDisplayWidgetView: FC<CatalogPriceDisplayWidgetViewProps> = props =>
|
export const CatalogPriceDisplayWidgetView: FC<CatalogPriceDisplayWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { offer = null, separator = false } = props;
|
const { offer = null, separator = false } = props;
|
||||||
const { purchaseOptions = null } = useCatalogContext();
|
const { purchaseOptions = null } = useCatalog();
|
||||||
const { quantity = 1 } = purchaseOptions;
|
const { quantity = 1 } = purchaseOptions;
|
||||||
|
|
||||||
if(!offer) return null;
|
if(!offer) return null;
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer';
|
import { PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { CreateLinkEvent, GetClubMemberLevel, LocalizeText, SendMessageComposer } from '../../../../../api';
|
import { CatalogPurchaseState, CreateLinkEvent, GetClubMemberLevel, LocalizeText, LocalStorageKeys, Offer, SendMessageComposer } from '../../../../../api';
|
||||||
import { Button, LayoutLoadingSpinnerView } from '../../../../../common';
|
import { Button, LayoutLoadingSpinnerView } from '../../../../../common';
|
||||||
import { CatalogEvent, CatalogInitGiftEvent, CatalogInitPurchaseEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent, CatalogWidgetEvent } from '../../../../../events';
|
import { CatalogEvent, CatalogInitGiftEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent } from '../../../../../events';
|
||||||
import { DispatchUiEvent, usePurse, UseUiEvent } from '../../../../../hooks';
|
import { DispatchUiEvent, useCatalog, useLocalStorage, usePurse, UseUiEvent } from '../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
|
|
||||||
import { Offer } from '../../../common/Offer';
|
|
||||||
|
|
||||||
interface CatalogPurchaseWidgetViewProps
|
interface CatalogPurchaseWidgetViewProps
|
||||||
{
|
{
|
||||||
@ -19,19 +16,10 @@ export const CatalogPurchaseWidgetView: FC<CatalogPurchaseWidgetViewProps> = pro
|
|||||||
const { noGiftOption = false, purchaseCallback = null } = props;
|
const { noGiftOption = false, purchaseCallback = null } = props;
|
||||||
const [ purchaseWillBeGift, setPurchaseWillBeGift ] = useState(false);
|
const [ purchaseWillBeGift, setPurchaseWillBeGift ] = useState(false);
|
||||||
const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
|
const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
|
||||||
const { currentOffer = null, currentPage = null, purchaseOptions = null, setPurchaseOptions = null } = useCatalogContext();
|
const [ catalogSkipPurchaseConfirmation, setCatalogSkipPurchaseConfirmation ] = useLocalStorage(LocalStorageKeys.CATALOG_SKIP_PURCHASE_CONFIRMATION, false);
|
||||||
|
const { currentOffer = null, currentPage = null, purchaseOptions = null, setPurchaseOptions = null } = useCatalog();
|
||||||
const { getCurrencyAmount = null } = usePurse();
|
const { getCurrencyAmount = null } = usePurse();
|
||||||
|
|
||||||
const onCatalogInitPurchaseEvent = useCallback((event: CatalogInitPurchaseEvent) =>
|
|
||||||
{
|
|
||||||
if(!currentOffer) return;
|
|
||||||
|
|
||||||
// show purchase confirmation
|
|
||||||
// offer, page.pageId, extraData, quantity, previewStuffData, null, true, null
|
|
||||||
}, [ currentOffer ]);
|
|
||||||
|
|
||||||
UseUiEvent(CatalogWidgetEvent.INIT_PURCHASE, onCatalogInitPurchaseEvent);
|
|
||||||
|
|
||||||
const onCatalogEvent = useCallback((event: CatalogEvent) =>
|
const onCatalogEvent = useCallback((event: CatalogEvent) =>
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Flex, FlexProps } from '../../../../../common/Flex';
|
import { Flex, FlexProps } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { CatalogPriceDisplayWidgetView } from './CatalogPriceDisplayWidgetView';
|
import { CatalogPriceDisplayWidgetView } from './CatalogPriceDisplayWidgetView';
|
||||||
|
|
||||||
interface CatalogSimplePriceWidgetViewProps extends FlexProps
|
interface CatalogSimplePriceWidgetViewProps extends FlexProps
|
||||||
@ -11,7 +11,7 @@ interface CatalogSimplePriceWidgetViewProps extends FlexProps
|
|||||||
export const CatalogSimplePriceWidgetView: FC<CatalogSimplePriceWidgetViewProps> = props =>
|
export const CatalogSimplePriceWidgetView: FC<CatalogSimplePriceWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { gap = 1, ...rest } = props;
|
const { gap = 1, ...rest } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex gap={ gap } alignItems="center" classNames={ [ 'bg-muted', 'p-1', 'rounded' ] } { ...rest }>
|
<Flex gap={ gap } alignItems="center" classNames={ [ 'bg-muted', 'p-1', 'rounded' ] } { ...rest }>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { LocalizeText, ProductTypeEnum } from '../../../../../api';
|
import { IPurchasableOffer, LocalizeText, Offer, ProductTypeEnum } from '../../../../../api';
|
||||||
import { AutoGrid, AutoGridProps, Button, ButtonGroup } from '../../../../../common';
|
import { AutoGrid, AutoGridProps, Button, ButtonGroup } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { IPurchasableOffer } from '../../../common/IPurchasableOffer';
|
|
||||||
import { Offer } from '../../../common/Offer';
|
|
||||||
import { CatalogGridOfferView } from '../common/CatalogGridOfferView';
|
import { CatalogGridOfferView } from '../common/CatalogGridOfferView';
|
||||||
|
|
||||||
interface CatalogSpacesWidgetViewProps extends AutoGridProps
|
interface CatalogSpacesWidgetViewProps extends AutoGridProps
|
||||||
@ -19,7 +17,21 @@ export const CatalogSpacesWidgetView: FC<CatalogSpacesWidgetViewProps> = props =
|
|||||||
const [ groupedOffers, setGroupedOffers ] = useState<IPurchasableOffer[][]>(null);
|
const [ groupedOffers, setGroupedOffers ] = useState<IPurchasableOffer[][]>(null);
|
||||||
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState(-1);
|
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState(-1);
|
||||||
const [ selectedOfferForGroup, setSelectedOfferForGroup ] = useState<IPurchasableOffer[]>(null);
|
const [ selectedOfferForGroup, setSelectedOfferForGroup ] = useState<IPurchasableOffer[]>(null);
|
||||||
const { currentPage = null, currentOffer = null, setCurrentOffer = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentPage = null, currentOffer = null, setCurrentOffer = null, setPurchaseOptions = null } = useCatalog();
|
||||||
|
|
||||||
|
const setSelectedOffer = (offer: IPurchasableOffer) =>
|
||||||
|
{
|
||||||
|
if(!offer) return;
|
||||||
|
|
||||||
|
setSelectedOfferForGroup(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = [ ...prevValue ];
|
||||||
|
|
||||||
|
newValue[selectedGroupIndex] = offer;
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -89,22 +101,7 @@ export const CatalogSpacesWidgetView: FC<CatalogSpacesWidgetViewProps> = props =
|
|||||||
{ SPACES_GROUP_NAMES.map((name, index) => <Button key={ index } active={ (selectedGroupIndex === index) } onClick={ event => setSelectedGroupIndex(index) }>{ LocalizeText(`catalog.spaces.tab.${ name }`) }</Button>) }
|
{ SPACES_GROUP_NAMES.map((name, index) => <Button key={ index } active={ (selectedGroupIndex === index) } onClick={ event => setSelectedGroupIndex(index) }>{ LocalizeText(`catalog.spaces.tab.${ name }`) }</Button>) }
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<AutoGrid columnCount={ columnCount } { ...rest }>
|
<AutoGrid columnCount={ columnCount } { ...rest }>
|
||||||
{ offers && (offers.length > 0) && offers.map((offer, index) =>
|
{ offers && (offers.length > 0) && offers.map((offer, index) => <CatalogGridOfferView key={ index } itemActive={ (currentOffer && (currentOffer === offer)) } offer={ offer } selectOffer={ offer => setSelectedOffer(offer) } />) }
|
||||||
{
|
|
||||||
const setSelectedOffer = () =>
|
|
||||||
{
|
|
||||||
setSelectedOfferForGroup(prevValue =>
|
|
||||||
{
|
|
||||||
const newValue = [ ...prevValue ];
|
|
||||||
|
|
||||||
newValue[selectedGroupIndex] = offer;
|
|
||||||
|
|
||||||
return newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return <CatalogGridOfferView key={ index } itemActive={ (currentOffer && (currentOffer === offer)) } offer={ offer } onClick={ setSelectedOffer } />;
|
|
||||||
}) }
|
|
||||||
{ children }
|
{ children }
|
||||||
</AutoGrid>
|
</AutoGrid>
|
||||||
</>
|
</>
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { LocalizeText } from '../../../../../api';
|
import { LocalizeText } from '../../../../../api';
|
||||||
import { Flex } from '../../../../../common/Flex';
|
import { Flex, Text } from '../../../../../common';
|
||||||
import { Text } from '../../../../../common/Text';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
|
||||||
|
|
||||||
const MIN_VALUE: number = 1;
|
const MIN_VALUE: number = 1;
|
||||||
const MAX_VALUE: number = 100;
|
const MAX_VALUE: number = 100;
|
||||||
|
|
||||||
export const CatalogSpinnerWidgetView: FC<{}> = props =>
|
export const CatalogSpinnerWidgetView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { currentOffer = null, purchaseOptions = null, setPurchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, purchaseOptions = null, setPurchaseOptions = null } = useCatalog();
|
||||||
const { quantity = 1 } = purchaseOptions;
|
const { quantity = 1 } = purchaseOptions;
|
||||||
|
|
||||||
const updateQuantity = (value: number) =>
|
const updateQuantity = (value: number) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Column, ColumnProps } from '../../../../../common/Column';
|
import { Column, ColumnProps } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { CatalogPriceDisplayWidgetView } from './CatalogPriceDisplayWidgetView';
|
import { CatalogPriceDisplayWidgetView } from './CatalogPriceDisplayWidgetView';
|
||||||
|
|
||||||
interface CatalogSimplePriceWidgetViewProps extends ColumnProps
|
interface CatalogSimplePriceWidgetViewProps extends ColumnProps
|
||||||
@ -10,7 +10,7 @@ interface CatalogSimplePriceWidgetViewProps extends ColumnProps
|
|||||||
export const CatalogTotalPriceWidget: FC<CatalogSimplePriceWidgetViewProps> = props =>
|
export const CatalogTotalPriceWidget: FC<CatalogSimplePriceWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { gap = 1, ...rest } = props;
|
const { gap = 1, ...rest } = props;
|
||||||
const { currentOffer = null } = useCatalogContext();
|
const { currentOffer = null } = useCatalog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column gap={ gap } { ...rest }>
|
<Column gap={ gap } { ...rest }>
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import { Vector3d } from '@nitrots/nitro-renderer';
|
import { Vector3d } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { GetAvatarRenderManager, GetSessionDataManager, ProductTypeEnum } from '../../../../../api';
|
import { FurniCategory, GetAvatarRenderManager, GetSessionDataManager, Offer, ProductTypeEnum } from '../../../../../api';
|
||||||
import { AutoGrid, Column, LayoutGridItem, LayoutRoomPreviewerView } from '../../../../../common';
|
import { AutoGrid, Column, LayoutGridItem, LayoutRoomPreviewerView } from '../../../../../common';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalog } from '../../../../../hooks';
|
||||||
import { FurniCategory } from '../../../common/FurniCategory';
|
|
||||||
import { Offer } from '../../../common/Offer';
|
|
||||||
|
|
||||||
export const CatalogViewProductWidgetView: FC<{}> = props =>
|
export const CatalogViewProductWidgetView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { currentOffer = null, roomPreviewer = null, purchaseOptions = null } = useCatalogContext();
|
const { currentOffer = null, roomPreviewer = null, purchaseOptions = null } = useCatalog();
|
||||||
const { previewStuffData = null } = purchaseOptions;
|
const { previewStuffData = null } = purchaseOptions;
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { GroupInformationParser, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
import { GroupInformationParser, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback } from 'react';
|
import { FC, useCallback } from 'react';
|
||||||
import { CreateLinkEvent, GetGroupManager, GetGroupMembers, GetSessionDataManager, LocalizeText, NotificationUtilities, SendMessageComposer, TryJoinGroup, TryVisitRoom } from '../../../api';
|
import { CatalogPageName, CreateLinkEvent, GetGroupManager, GetGroupMembers, GetSessionDataManager, LocalizeText, NotificationUtilities, SendMessageComposer, TryJoinGroup, TryVisitRoom } from '../../../api';
|
||||||
import { Button, Column, Flex, Grid, GridProps, LayoutBadgeImageView, Text } from '../../../common';
|
import { Button, Column, Flex, Grid, GridProps, LayoutBadgeImageView, Text } from '../../../common';
|
||||||
import { CatalogPageName } from '../../catalog/common/CatalogPageName';
|
|
||||||
import { GroupMembershipType } from '../common/GroupMembershipType';
|
import { GroupMembershipType } from '../common/GroupMembershipType';
|
||||||
import { GroupType } from '../common/GroupType';
|
import { GroupType } from '../common/GroupType';
|
||||||
|
|
||||||
|
@ -3,12 +3,14 @@ import { ILinkEventTracker, NitroSettingsEvent, UserSettingsCameraFollowComposer
|
|||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api';
|
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api';
|
||||||
import { Column, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common';
|
import { Column, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common';
|
||||||
import { DispatchMainEvent, DispatchUiEvent, UseMessageEventHook } from '../../hooks';
|
import { DispatchMainEvent, DispatchUiEvent, useCatalogPlaceMultipleItems, useCatalogSkipPurchaseConfirmation, UseMessageEventHook } from '../../hooks';
|
||||||
|
|
||||||
export const UserSettingsView: FC<{}> = props =>
|
export const UserSettingsView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const [ userSettings, setUserSettings ] = useState<NitroSettingsEvent>(null);
|
const [ userSettings, setUserSettings ] = useState<NitroSettingsEvent>(null);
|
||||||
|
const [ catalogPlaceMultipleObjects, setCatalogPlaceMultipleObjects ] = useCatalogPlaceMultipleItems();
|
||||||
|
const [ catalogSkipPurchaseConfirmation, setCatalogSkipPurchaseConfirmation ] = useCatalogSkipPurchaseConfirmation();
|
||||||
|
|
||||||
const onUserSettingsEvent = useCallback((event: UserSettingsEvent) =>
|
const onUserSettingsEvent = useCallback((event: UserSettingsEvent) =>
|
||||||
{
|
{
|
||||||
@ -141,6 +143,14 @@ export const UserSettingsView: FC<{}> = props =>
|
|||||||
<input className="form-check-input" type="checkbox" checked={ userSettings.cameraFollow } onChange={ event => processAction('camera_follow', event.target.checked) } />
|
<input className="form-check-input" type="checkbox" checked={ userSettings.cameraFollow } onChange={ event => processAction('camera_follow', event.target.checked) } />
|
||||||
<Text>{ LocalizeText('memenu.settings.other.disable.room.camera.follow') }</Text>
|
<Text>{ LocalizeText('memenu.settings.other.disable.room.camera.follow') }</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Flex alignItems="center" gap={ 1 }>
|
||||||
|
<input className="form-check-input" type="checkbox" checked={ catalogPlaceMultipleObjects } onChange={ event => setCatalogPlaceMultipleObjects(event.target.checked) } />
|
||||||
|
<Text>{ LocalizeText('memenu.settings.other.place.multiple.objects') }</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex alignItems="center" gap={ 1 }>
|
||||||
|
<input className="form-check-input" type="checkbox" checked={ catalogSkipPurchaseConfirmation } onChange={ event => setCatalogSkipPurchaseConfirmation(event.target.checked) } />
|
||||||
|
<Text>{ LocalizeText('memenu.settings.other.skip.purchase.confirmation') }</Text>
|
||||||
|
</Flex>
|
||||||
</Column>
|
</Column>
|
||||||
<Column>
|
<Column>
|
||||||
<Text bold>{ LocalizeText('widget.memenu.settings.volume') }</Text>
|
<Text bold>{ LocalizeText('widget.memenu.settings.volume') }</Text>
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
|
||||||
import { CatalogWidgetEvent } from './CatalogWidgetEvent';
|
|
||||||
|
|
||||||
export class CatalogInitPurchaseEvent extends NitroEvent
|
|
||||||
{
|
|
||||||
private _enableBuyAsGift: boolean = true;
|
|
||||||
private _userName: string;
|
|
||||||
|
|
||||||
constructor(enableBuyAsGift: boolean = true, userName: string = null)
|
|
||||||
{
|
|
||||||
super(CatalogWidgetEvent.INIT_PURCHASE);
|
|
||||||
|
|
||||||
this._enableBuyAsGift = enableBuyAsGift;
|
|
||||||
this._userName = userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get enableBuyAsGift(): boolean
|
|
||||||
{
|
|
||||||
return this._enableBuyAsGift;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get userName(): string
|
|
||||||
{
|
|
||||||
return this._userName;
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,6 @@ export class CatalogWidgetEvent extends NitroEvent
|
|||||||
public static APPROVE_RESULT: string = 'CWE_CWE_APPROVE_RESULT';
|
public static APPROVE_RESULT: string = 'CWE_CWE_APPROVE_RESULT';
|
||||||
public static PURCHASE_OVERRIDE: string = 'CWE_PURCHASE_OVERRIDE';
|
public static PURCHASE_OVERRIDE: string = 'CWE_PURCHASE_OVERRIDE';
|
||||||
public static SELLABLE_PET_PALETTES: string = 'CWE_SELLABLE_PET_PALETTES';
|
public static SELLABLE_PET_PALETTES: string = 'CWE_SELLABLE_PET_PALETTES';
|
||||||
public static INIT_PURCHASE: string = 'CWE_INIT_PURCHASE';
|
|
||||||
public static UPDATE_ROOM_PREVIEW: string = 'CWE_UPDATE_ROOM_PREVIEW';
|
public static UPDATE_ROOM_PREVIEW: string = 'CWE_UPDATE_ROOM_PREVIEW';
|
||||||
public static GUILD_SELECTED: string = 'CWE_GUILD_SELECTED';
|
public static GUILD_SELECTED: string = 'CWE_GUILD_SELECTED';
|
||||||
public static TOTAL_PRICE_WIDGET_INITIALIZED: string = 'CWE_TOTAL_PRICE_WIDGET_INITIALIZED';
|
public static TOTAL_PRICE_WIDGET_INITIALIZED: string = 'CWE_TOTAL_PRICE_WIDGET_INITIALIZED';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { IObjectData, NitroEvent } from '@nitrots/nitro-renderer';
|
import { IObjectData, NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
import { IPurchasableOffer } from '../../components/catalog/common/IPurchasableOffer';
|
import { IPurchasableOffer } from '../../api';
|
||||||
|
|
||||||
export class SetRoomPreviewerStuffDataEvent extends NitroEvent
|
export class SetRoomPreviewerStuffDataEvent extends NitroEvent
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
export * from './CatalogEvent';
|
export * from './CatalogEvent';
|
||||||
export * from './CatalogGiftReceiverNotFoundEvent';
|
export * from './CatalogGiftReceiverNotFoundEvent';
|
||||||
export * from './CatalogInitGiftEvent';
|
export * from './CatalogInitGiftEvent';
|
||||||
export * from './CatalogInitPurchaseEvent';
|
|
||||||
export * from './CatalogNameResultEvent';
|
export * from './CatalogNameResultEvent';
|
||||||
export * from './CatalogPostMarketplaceOfferEvent';
|
export * from './CatalogPostMarketplaceOfferEvent';
|
||||||
export * from './CatalogPurchasedEvent';
|
export * from './CatalogPurchasedEvent';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export * from './catalog';
|
export * from './catalog';
|
||||||
export * from './guide-tool';
|
export * from './guide-tool';
|
||||||
export * from './help';
|
export * from './help';
|
||||||
|
export * from './inventory';
|
||||||
export * from './mod-tools';
|
export * from './mod-tools';
|
||||||
export * from './notification-center';
|
export * from './notification-center';
|
||||||
export * from './room-widgets';
|
export * from './room-widgets';
|
||||||
|
14
src/events/inventory/InventoryFurniAddedEvent.ts
Normal file
14
src/events/inventory/InventoryFurniAddedEvent.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export class InventoryFurniAddedEvent extends NitroEvent
|
||||||
|
{
|
||||||
|
public static FURNI_ADDED: string = 'IFAE_FURNI_ADDED';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly id: number,
|
||||||
|
public readonly spriteId: number,
|
||||||
|
public readonly category: number)
|
||||||
|
{
|
||||||
|
super(InventoryFurniAddedEvent.FURNI_ADDED);
|
||||||
|
}
|
||||||
|
}
|
1
src/events/inventory/index.ts
Normal file
1
src/events/inventory/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './InventoryFurniAddedEvent';
|
5
src/hooks/catalog/index.ts
Normal file
5
src/hooks/catalog/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export * from './useCatalog';
|
||||||
|
export * from './useCatalogBuildersClub';
|
||||||
|
export * from './useCatalogItemMover';
|
||||||
|
export * from './useCatalogPlaceMultipleItems';
|
||||||
|
export * from './useCatalogSkipPurchaseConfirmation';
|
611
src/hooks/catalog/useCatalog.ts
Normal file
611
src/hooks/catalog/useCatalog.ts
Normal file
@ -0,0 +1,611 @@
|
|||||||
|
import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, FrontPageItem, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomPreviewer, SellablePetPalettesMessageEvent } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, GetFurnitureData, GetProductDataForLocalization, GetRoomEngine, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, NotificationUtilities, Offer, PageLocalization, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api';
|
||||||
|
import { CatalogGiftReceiverNotFoundEvent, CatalogNameResultEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent } from '../../events';
|
||||||
|
import { DispatchUiEvent, UseUiEvent } from '../events';
|
||||||
|
import { UseMessageEventHook } from '../messages';
|
||||||
|
import { useCatalogBuildersClub } from './useCatalogBuildersClub';
|
||||||
|
import { useCatalogItemMover } from './useCatalogItemMover';
|
||||||
|
|
||||||
|
const useCatalogState = () =>
|
||||||
|
{
|
||||||
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ isBusy, setIsBusy ] = useState(false);
|
||||||
|
const [ pageId, setPageId ] = useState(-1);
|
||||||
|
const [ previousPageId, setPreviousPageId ] = useState(-1);
|
||||||
|
const [ currentType, setCurrentType ] = useState(CatalogType.NORMAL);
|
||||||
|
const [ rootNode, setRootNode ] = useState<ICatalogNode>(null);
|
||||||
|
const [ offersToNodes, setOffersToNodes ] = useState<Map<number, ICatalogNode[]>>(null);
|
||||||
|
const [ currentPage, setCurrentPage ] = useState<ICatalogPage>(null);
|
||||||
|
const [ currentOffer, setCurrentOffer ] = useState<IPurchasableOffer>(null);
|
||||||
|
const [ activeNodes, setActiveNodes ] = useState<ICatalogNode[]>([]);
|
||||||
|
const [ searchResult, setSearchResult ] = useState<SearchResult>(null);
|
||||||
|
const [ frontPageItems, setFrontPageItems ] = useState<FrontPageItem[]>([]);
|
||||||
|
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
|
||||||
|
const [ navigationHidden, setNavigationHidden ] = useState(false);
|
||||||
|
const [ purchaseOptions, setPurchaseOptions ] = useState<IPurchaseOptions>({ quantity: 1, extraData: null, extraParamRequired: false, previewStuffData: null });
|
||||||
|
const [ catalogOptions, setCatalogOptions ] = useState<ICatalogOptions>({});
|
||||||
|
const { furniCount = 0, furniLimit = 0, secondsLeft = 0 } = useCatalogBuildersClub();
|
||||||
|
const { requestOfferToMover = null, cancelObjectMover = null } = useCatalogItemMover({ currentType, pageId, currentOffer, purchaseOptions }, { furniCount, furniLimit, secondsLeft });
|
||||||
|
const requestedPage = useRef(new RequestedPage());
|
||||||
|
|
||||||
|
const resetState = useCallback(() =>
|
||||||
|
{
|
||||||
|
setPageId(-1);
|
||||||
|
setPreviousPageId(-1);
|
||||||
|
setRootNode(null);
|
||||||
|
setOffersToNodes(null);
|
||||||
|
setCurrentPage(null);
|
||||||
|
setCurrentOffer(null);
|
||||||
|
setActiveNodes([]);
|
||||||
|
setSearchResult(null);
|
||||||
|
setFrontPageItems([]);
|
||||||
|
setIsVisible(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getNodeById = useCallback((id: number, node: ICatalogNode) =>
|
||||||
|
{
|
||||||
|
if((node.pageId === id) && (node !== rootNode)) return node;
|
||||||
|
|
||||||
|
for(const child of node.children)
|
||||||
|
{
|
||||||
|
const found = (getNodeById(id, child) as ICatalogNode);
|
||||||
|
|
||||||
|
if(found) return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}, [ rootNode ]);
|
||||||
|
|
||||||
|
const getNodeByName = useCallback((name: string, node: ICatalogNode) =>
|
||||||
|
{
|
||||||
|
if((node.pageName === name) && (node !== rootNode)) return node;
|
||||||
|
|
||||||
|
for(const child of node.children)
|
||||||
|
{
|
||||||
|
const found = (getNodeByName(name, child) as ICatalogNode);
|
||||||
|
|
||||||
|
if(found) return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}, [ rootNode ]);
|
||||||
|
|
||||||
|
const getNodesByOfferId = useCallback((offerId: number, flag: boolean = false) =>
|
||||||
|
{
|
||||||
|
if(!offersToNodes || !offersToNodes.size) return null;
|
||||||
|
|
||||||
|
if(flag)
|
||||||
|
{
|
||||||
|
const nodes: ICatalogNode[] = [];
|
||||||
|
const offers = offersToNodes.get(offerId);
|
||||||
|
|
||||||
|
if(offers && offers.length) for(const offer of offers) (offer.isVisible && nodes.push(offer));
|
||||||
|
|
||||||
|
if(nodes.length) return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offersToNodes.get(offerId);
|
||||||
|
}, [ offersToNodes ]);
|
||||||
|
|
||||||
|
const loadCatalogPage = useCallback((pageId: number, offerId: number) =>
|
||||||
|
{
|
||||||
|
if(pageId < 0) return;
|
||||||
|
|
||||||
|
setIsBusy(true);
|
||||||
|
setPageId(pageId);
|
||||||
|
|
||||||
|
if(pageId > -1) SendMessageComposer(new GetCatalogPageComposer(pageId, offerId, currentType));
|
||||||
|
}, [ currentType ]);
|
||||||
|
|
||||||
|
const showCatalogPage = useCallback((pageId: number, layoutCode: string, localization: IPageLocalization, offers: IPurchasableOffer[], offerId: number, acceptSeasonCurrencyAsCredits: boolean) =>
|
||||||
|
{
|
||||||
|
const catalogPage = (new CatalogPage(pageId, layoutCode, localization, offers, acceptSeasonCurrencyAsCredits) as ICatalogPage);
|
||||||
|
|
||||||
|
setCurrentPage(catalogPage);
|
||||||
|
setPreviousPageId(prevValue => ((pageId !== -1) ? pageId : prevValue));
|
||||||
|
setNavigationHidden(false);
|
||||||
|
|
||||||
|
if((offerId > -1) && catalogPage.offers.length)
|
||||||
|
{
|
||||||
|
for(const offer of catalogPage.offers)
|
||||||
|
{
|
||||||
|
if(offer.offerId !== offerId) continue;
|
||||||
|
|
||||||
|
setCurrentOffer(offer)
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const activateNode = useCallback((targetNode: ICatalogNode, offerId: number = -1) =>
|
||||||
|
{
|
||||||
|
cancelObjectMover();
|
||||||
|
|
||||||
|
if(targetNode.parent.pageName === 'root')
|
||||||
|
{
|
||||||
|
if(targetNode.children.length)
|
||||||
|
{
|
||||||
|
for(const child of targetNode.children)
|
||||||
|
{
|
||||||
|
if(!child.isVisible) continue;
|
||||||
|
|
||||||
|
targetNode = child;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes: ICatalogNode[] = [];
|
||||||
|
|
||||||
|
let node = targetNode;
|
||||||
|
|
||||||
|
while(node && (node.pageName !== 'root'))
|
||||||
|
{
|
||||||
|
nodes.push(node);
|
||||||
|
|
||||||
|
node = node.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.reverse();
|
||||||
|
|
||||||
|
setActiveNodes(prevValue =>
|
||||||
|
{
|
||||||
|
const isActive = (prevValue.indexOf(targetNode) >= 0);
|
||||||
|
const isOpen = targetNode.isOpen;
|
||||||
|
|
||||||
|
for(const existing of prevValue)
|
||||||
|
{
|
||||||
|
existing.deactivate();
|
||||||
|
|
||||||
|
if(nodes.indexOf(existing) === -1) existing.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const n of nodes)
|
||||||
|
{
|
||||||
|
n.activate();
|
||||||
|
|
||||||
|
if(n.parent) n.open();
|
||||||
|
|
||||||
|
if((n === targetNode.parent) && n.children.length) n.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isActive && isOpen) targetNode.close();
|
||||||
|
else targetNode.open();
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(targetNode.pageId > -1) loadCatalogPage(targetNode.pageId, offerId);
|
||||||
|
}, [ setActiveNodes, loadCatalogPage, cancelObjectMover ]);
|
||||||
|
|
||||||
|
const openPageById = useCallback((id: number) =>
|
||||||
|
{
|
||||||
|
setSearchResult(null);
|
||||||
|
|
||||||
|
if(!isVisible)
|
||||||
|
{
|
||||||
|
requestedPage.current.requestById = id;
|
||||||
|
|
||||||
|
setIsVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const node = getNodeById(id, rootNode);
|
||||||
|
|
||||||
|
if(node) activateNode(node);
|
||||||
|
}
|
||||||
|
}, [ isVisible, rootNode, getNodeById, activateNode ]);
|
||||||
|
|
||||||
|
const openPageByName = useCallback((name: string) =>
|
||||||
|
{
|
||||||
|
setSearchResult(null);
|
||||||
|
|
||||||
|
if(!isVisible)
|
||||||
|
{
|
||||||
|
requestedPage.current.requestByName = name;
|
||||||
|
|
||||||
|
setIsVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const node = getNodeByName(name, rootNode);
|
||||||
|
|
||||||
|
if(node) activateNode(node);
|
||||||
|
}
|
||||||
|
}, [ isVisible, rootNode, getNodeByName, activateNode ]);
|
||||||
|
|
||||||
|
const openPageByOfferId = useCallback((offerId: number) =>
|
||||||
|
{
|
||||||
|
setSearchResult(null);
|
||||||
|
|
||||||
|
if(!isVisible)
|
||||||
|
{
|
||||||
|
requestedPage.current.requestedByOfferId = offerId;
|
||||||
|
|
||||||
|
setIsVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const nodes = getNodesByOfferId(offerId);
|
||||||
|
|
||||||
|
if(!nodes || !nodes.length) return;
|
||||||
|
|
||||||
|
activateNode(nodes[0], offerId);
|
||||||
|
}
|
||||||
|
}, [ isVisible, getNodesByOfferId, activateNode ]);
|
||||||
|
|
||||||
|
const onCatalogPagesListEvent = useCallback((event: CatalogPagesListEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
const offers: Map<number, ICatalogNode[]> = new Map();
|
||||||
|
|
||||||
|
const getCatalogNode = (node: NodeData, depth: number, parent: ICatalogNode) =>
|
||||||
|
{
|
||||||
|
const catalogNode = (new CatalogNode(node, depth, parent) as ICatalogNode);
|
||||||
|
|
||||||
|
for(const offerId of catalogNode.offerIds)
|
||||||
|
{
|
||||||
|
if(offers.has(offerId)) offers.get(offerId).push(catalogNode);
|
||||||
|
else offers.set(offerId, [ catalogNode ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
depth++;
|
||||||
|
|
||||||
|
for(const child of node.children) catalogNode.addChild(getCatalogNode(child, depth, catalogNode));
|
||||||
|
|
||||||
|
return catalogNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRootNode(getCatalogNode(parser.root, 0, null));
|
||||||
|
setOffersToNodes(offers);
|
||||||
|
}, [ setRootNode, setOffersToNodes ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(CatalogPagesListEvent, onCatalogPagesListEvent);
|
||||||
|
|
||||||
|
const onCatalogPageMessageEvent = useCallback((event: CatalogPageMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(parser.catalogType !== currentType) return;
|
||||||
|
|
||||||
|
const purchasableOffers: IPurchasableOffer[] = [];
|
||||||
|
|
||||||
|
for(const offer of parser.offers)
|
||||||
|
{
|
||||||
|
const products: IProduct[] = [];
|
||||||
|
const productData = GetProductDataForLocalization(offer.localizationId);
|
||||||
|
|
||||||
|
for(const product of offer.products)
|
||||||
|
{
|
||||||
|
const furnitureData = GetFurnitureData(product.furniClassId, product.productType);
|
||||||
|
|
||||||
|
products.push(new Product(product.productType, product.furniClassId, product.extraParam, product.productCount, productData, furnitureData, product.uniqueLimitedItem, product.uniqueLimitedSeriesSize, product.uniqueLimitedItemsLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!products.length) continue;
|
||||||
|
|
||||||
|
const purchasableOffer = new Offer(offer.offerId, offer.localizationId, offer.rent, offer.priceCredits, offer.priceActivityPoints, offer.priceActivityPointsType, offer.giftable, offer.clubLevel, products, offer.bundlePurchaseAllowed);
|
||||||
|
|
||||||
|
if((currentType === CatalogType.NORMAL) || ((purchasableOffer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (purchasableOffer.pricingModel !== Offer.PRICING_MODEL_MULTI))) purchasableOffers.push(purchasableOffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(parser.frontPageItems && parser.frontPageItems.length) setFrontPageItems(parser.frontPageItems);
|
||||||
|
|
||||||
|
setIsBusy(false);
|
||||||
|
|
||||||
|
if(pageId === parser.pageId)
|
||||||
|
{
|
||||||
|
showCatalogPage(parser.pageId, parser.layoutCode, new PageLocalization(parser.localization.images.concat(), parser.localization.texts.concat()), purchasableOffers, parser.offerId, parser.acceptSeasonCurrencyAsCredits);
|
||||||
|
}
|
||||||
|
}, [ currentType, pageId, setFrontPageItems, setIsBusy, showCatalogPage ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(CatalogPageMessageEvent, onCatalogPageMessageEvent);
|
||||||
|
|
||||||
|
const onPurchaseOKMessageEvent = useCallback((event: PurchaseOKMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
DispatchUiEvent(new CatalogPurchasedEvent(parser.offer));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(PurchaseOKMessageEvent, onPurchaseOKMessageEvent);
|
||||||
|
|
||||||
|
const onPurchaseErrorMessageEvent = useCallback((event: PurchaseErrorMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
DispatchUiEvent(new CatalogPurchaseFailureEvent(parser.code));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(PurchaseErrorMessageEvent, onPurchaseErrorMessageEvent);
|
||||||
|
|
||||||
|
const onPurchaseNotAllowedMessageEvent = useCallback((event: PurchaseNotAllowedMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
DispatchUiEvent(new CatalogPurchaseNotAllowedEvent(parser.code));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(PurchaseNotAllowedMessageEvent, onPurchaseNotAllowedMessageEvent);
|
||||||
|
|
||||||
|
const onLimitedEditionSoldOutEvent = useCallback((event: LimitedEditionSoldOutEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
DispatchUiEvent(new CatalogPurchaseSoldOutEvent());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(LimitedEditionSoldOutEvent, onLimitedEditionSoldOutEvent);
|
||||||
|
|
||||||
|
const onProductOfferEvent = useCallback((event: ProductOfferEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
const offerData = parser.offer;
|
||||||
|
|
||||||
|
if(!offerData || !offerData.products.length) return;
|
||||||
|
|
||||||
|
const offerProductData = offerData.products[0];
|
||||||
|
|
||||||
|
if(offerProductData.uniqueLimitedItem)
|
||||||
|
{
|
||||||
|
// update unique
|
||||||
|
}
|
||||||
|
|
||||||
|
const products: IProduct[] = [];
|
||||||
|
const productData = GetProductDataForLocalization(offerData.localizationId);
|
||||||
|
|
||||||
|
for(const product of offerData.products)
|
||||||
|
{
|
||||||
|
const furnitureData = GetFurnitureData(product.furniClassId, product.productType);
|
||||||
|
|
||||||
|
products.push(new Product(product.productType, product.furniClassId, product.extraParam, product.productCount, productData, furnitureData, product.uniqueLimitedItem, product.uniqueLimitedSeriesSize, product.uniqueLimitedItemsLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
const offer = new Offer(offerData.offerId, offerData.localizationId, offerData.rent, offerData.priceCredits, offerData.priceActivityPoints, offerData.priceActivityPointsType, offerData.giftable, offerData.clubLevel, products, offerData.bundlePurchaseAllowed);
|
||||||
|
|
||||||
|
if(!((currentType === CatalogType.NORMAL) || ((offer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (offer.pricingModel !== Offer.PRICING_MODEL_MULTI)))) return;
|
||||||
|
|
||||||
|
offer.page = currentPage;
|
||||||
|
|
||||||
|
setCurrentOffer(offer);
|
||||||
|
|
||||||
|
if(offer.product && (offer.product.productType === ProductTypeEnum.WALL))
|
||||||
|
{
|
||||||
|
setPurchaseOptions(prevValue =>
|
||||||
|
{
|
||||||
|
const newValue = { ...prevValue };
|
||||||
|
|
||||||
|
newValue.extraData =( offer.product.extraParam || null);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// (this._isObjectMoverRequested) && (this._purchasableOffer)
|
||||||
|
}, [ currentType, currentPage, setCurrentOffer, setPurchaseOptions ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(ProductOfferEvent, onProductOfferEvent);
|
||||||
|
|
||||||
|
const onSellablePetPalettesMessageEvent = useCallback((event: SellablePetPalettesMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
const petPalette = new CatalogPetPalette(parser.productCode, parser.palettes.slice());
|
||||||
|
|
||||||
|
setCatalogOptions(prevValue =>
|
||||||
|
{
|
||||||
|
const petPalettes = [];
|
||||||
|
|
||||||
|
if(prevValue.petPalettes) petPalettes.push(...prevValue.petPalettes);
|
||||||
|
|
||||||
|
for(let i = 0; i < petPalettes.length; i++)
|
||||||
|
{
|
||||||
|
const palette = petPalettes[i];
|
||||||
|
|
||||||
|
if(palette.breed === petPalette.breed)
|
||||||
|
{
|
||||||
|
petPalettes.splice(i, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
petPalettes.push(petPalette);
|
||||||
|
|
||||||
|
return { ...prevValue, petPalettes };
|
||||||
|
});
|
||||||
|
}, [ setCatalogOptions ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(SellablePetPalettesMessageEvent, onSellablePetPalettesMessageEvent);
|
||||||
|
|
||||||
|
const onApproveNameMessageEvent = useCallback((event: ApproveNameMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
DispatchUiEvent(new CatalogNameResultEvent(parser.result, parser.validationInfo));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(ApproveNameMessageEvent, onApproveNameMessageEvent);
|
||||||
|
|
||||||
|
const onGiftReceiverNotFoundEvent = useCallback(() =>
|
||||||
|
{
|
||||||
|
DispatchUiEvent(new CatalogGiftReceiverNotFoundEvent());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(GiftReceiverNotFoundEvent, onGiftReceiverNotFoundEvent);
|
||||||
|
|
||||||
|
const onHabboClubOffersMessageEvent = useCallback((event: HabboClubOffersMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setCatalogOptions(prevValue =>
|
||||||
|
{
|
||||||
|
const clubOffers = parser.offers;
|
||||||
|
|
||||||
|
return { ...prevValue, clubOffers };
|
||||||
|
});
|
||||||
|
}, [ setCatalogOptions ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(HabboClubOffersMessageEvent, onHabboClubOffersMessageEvent);
|
||||||
|
|
||||||
|
const onGuildMembershipsMessageEvent = useCallback((event: GuildMembershipsMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setCatalogOptions(prevValue =>
|
||||||
|
{
|
||||||
|
const groups = parser.groups;
|
||||||
|
|
||||||
|
return { ...prevValue, groups };
|
||||||
|
});
|
||||||
|
}, [ setCatalogOptions ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(GuildMembershipsMessageEvent, onGuildMembershipsMessageEvent);
|
||||||
|
|
||||||
|
const onGiftWrappingConfigurationEvent = useCallback((event: GiftWrappingConfigurationEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setCatalogOptions(prevValue =>
|
||||||
|
{
|
||||||
|
const giftConfiguration = new GiftWrappingConfiguration(parser);
|
||||||
|
|
||||||
|
return { ...prevValue, giftConfiguration };
|
||||||
|
});
|
||||||
|
}, [ setCatalogOptions ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(GiftWrappingConfigurationEvent, onGiftWrappingConfigurationEvent);
|
||||||
|
|
||||||
|
const onMarketplaceMakeOfferResult = useCallback((event: MarketplaceMakeOfferResult) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
if(!parser) return;
|
||||||
|
|
||||||
|
let title = '';
|
||||||
|
if(parser.result === 1)
|
||||||
|
{
|
||||||
|
title = LocalizeText('inventory.marketplace.result.title.success');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
title = LocalizeText('inventory.marketplace.result.title.failure');
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = LocalizeText(`inventory.marketplace.result.${ parser.result }`);
|
||||||
|
|
||||||
|
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, title);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseMessageEventHook(MarketplaceMakeOfferResult, onMarketplaceMakeOfferResult);
|
||||||
|
|
||||||
|
const onClubGiftInfoEvent = useCallback((event: ClubGiftInfoEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setCatalogOptions(prevValue =>
|
||||||
|
{
|
||||||
|
const clubGifts = parser;
|
||||||
|
|
||||||
|
return { ...prevValue, clubGifts };
|
||||||
|
});
|
||||||
|
}, [ setCatalogOptions ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(ClubGiftInfoEvent, onClubGiftInfoEvent);
|
||||||
|
|
||||||
|
const onCatalogPublishedMessageEvent = useCallback((event: CatalogPublishedMessageEvent) =>
|
||||||
|
{
|
||||||
|
const wasVisible = isVisible;
|
||||||
|
|
||||||
|
resetState();
|
||||||
|
|
||||||
|
if(wasVisible) NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.published.description'), NotificationAlertType.ALERT, null, null, LocalizeText('catalog.alert.published.title'));
|
||||||
|
}, [ isVisible, resetState ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent);
|
||||||
|
|
||||||
|
const onCatalogPurchasedEvent = useCallback((event: CatalogPurchasedEvent) =>
|
||||||
|
{
|
||||||
|
PlaySound(SoundNames.CREDITS);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
UseUiEvent(CatalogPurchasedEvent.PURCHASE_SUCCESS, onCatalogPurchasedEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
return () => setCurrentOffer(null);
|
||||||
|
}, [ currentPage ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible || !rootNode || !requestedPage.current) return;
|
||||||
|
|
||||||
|
switch(requestedPage.current.requestType)
|
||||||
|
{
|
||||||
|
case RequestedPage.REQUEST_TYPE_NONE:
|
||||||
|
if(activeNodes && activeNodes.length) return;
|
||||||
|
|
||||||
|
if(rootNode.isBranch)
|
||||||
|
{
|
||||||
|
for(const child of rootNode.children)
|
||||||
|
{
|
||||||
|
if(child && child.isVisible)
|
||||||
|
{
|
||||||
|
activateNode(child);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case RequestedPage.REQUEST_TYPE_ID:
|
||||||
|
openPageById(requestedPage.current.requestById);
|
||||||
|
requestedPage.current.resetRequest();
|
||||||
|
return;
|
||||||
|
case RequestedPage.REQUEST_TYPE_OFFER:
|
||||||
|
openPageByOfferId(requestedPage.current.requestedByOfferId);
|
||||||
|
requestedPage.current.resetRequest();
|
||||||
|
return;
|
||||||
|
case RequestedPage.REQUEST_TYPE_NAME:
|
||||||
|
openPageByName(requestedPage.current.requestByName);
|
||||||
|
requestedPage.current.resetRequest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [ isVisible, rootNode, activeNodes, activateNode, openPageById, openPageByOfferId, openPageByName ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!searchResult && currentPage && (currentPage.pageId === -1)) openPageById(previousPageId);
|
||||||
|
}, [ searchResult, currentPage, previousPageId, openPageById ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible || rootNode) return;
|
||||||
|
|
||||||
|
SendMessageComposer(new GetGiftWrappingConfigurationComposer());
|
||||||
|
SendMessageComposer(new GetClubGiftInfo());
|
||||||
|
SendMessageComposer(new GetCatalogIndexComposer(currentType));
|
||||||
|
}, [ isVisible, rootNode, currentType ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setRoomPreviewer(new RoomPreviewer(GetRoomEngine(), ++RoomPreviewer.PREVIEW_COUNTER));
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
setRoomPreviewer(prevValue =>
|
||||||
|
{
|
||||||
|
prevValue.dispose();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { isVisible, setIsVisible, isBusy, pageId, previousPageId, currentType, rootNode, offersToNodes, currentPage, setCurrentPage, currentOffer, setCurrentOffer, activeNodes, searchResult, setSearchResult, frontPageItems, roomPreviewer, navigationHidden, setNavigationHidden, purchaseOptions, setPurchaseOptions, catalogOptions, setCatalogOptions, getNodeById, getNodeByName, activateNode, openPageById, openPageByName, openPageByOfferId, requestOfferToMover };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useCatalog = () => useBetween(useCatalogState);
|
54
src/hooks/catalog/useCatalogBuildersClub.ts
Normal file
54
src/hooks/catalog/useCatalogBuildersClub.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { BuildersClubFurniCountMessageEvent, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { GetNitroInstance, SendMessageComposer } from '../../api';
|
||||||
|
import { UseMessageEventHook } from '../messages';
|
||||||
|
|
||||||
|
const useCatalogBuildersClubState = () =>
|
||||||
|
{
|
||||||
|
const [ furniCount, setFurniCount ] = useState(0);
|
||||||
|
const [ furniLimit, setFurniLimit ] = useState(0);
|
||||||
|
const [ maxFurniLimit, setMaxFurniLimit ] = useState(0);
|
||||||
|
const [ secondsLeft, setSecondsLeft ] = useState(0);
|
||||||
|
const [ updateTime, setUpdateTime ] = useState(0);
|
||||||
|
const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0);
|
||||||
|
|
||||||
|
const refreshBuilderStatus = useCallback(() =>
|
||||||
|
{
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onBuildersClubFurniCountMessageEvent = useCallback((event: BuildersClubFurniCountMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setFurniCount(parser.furniCount);
|
||||||
|
|
||||||
|
refreshBuilderStatus();
|
||||||
|
}, [ refreshBuilderStatus ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(BuildersClubFurniCountMessageEvent, onBuildersClubFurniCountMessageEvent);
|
||||||
|
|
||||||
|
const onBuildersClubSubscriptionStatusMessageEvent = useCallback((event: BuildersClubSubscriptionStatusMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setFurniLimit(parser._Str_15864);
|
||||||
|
setMaxFurniLimit(parser._Str_24094);
|
||||||
|
setSecondsLeft(parser._Str_3709);
|
||||||
|
setUpdateTime(GetNitroInstance().time);
|
||||||
|
setSecondsLeftWithGrace(parser._Str_24379);
|
||||||
|
|
||||||
|
refreshBuilderStatus();
|
||||||
|
}, [ refreshBuilderStatus ]);
|
||||||
|
|
||||||
|
UseMessageEventHook(BuildersClubSubscriptionStatusMessageEvent, onBuildersClubSubscriptionStatusMessageEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
SendMessageComposer(new BuildersClubQueryFurniCountMessageComposer());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { furniCount, furniLimit, maxFurniLimit, secondsLeft, updateTime, secondsLeftWithGrace };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useCatalogBuildersClub = useCatalogBuildersClubState;
|
321
src/hooks/catalog/useCatalogItemMover.ts
Normal file
321
src/hooks/catalog/useCatalogItemMover.ts
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
import { BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, FurniturePlaceComposer, FurniturePlacePaintComposer, LegacyDataType, PurchaseFromCatalogComposer, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, Vector3d } from '@nitrots/nitro-renderer';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { BuilderFurniPlaceableStatus, CatalogType, CreateLinkEvent, FurniCategory, GetRoomEngine, GetRoomSession, IPurchasableOffer, IPurchaseOptions, Offer, PlacedObjectPurchaseData, ProductTypeEnum, SendMessageComposer } from '../../api';
|
||||||
|
import { InventoryFurniAddedEvent } from '../../events';
|
||||||
|
import { UseRoomEngineEvent, UseUiEvent } from '../events';
|
||||||
|
import { useCatalogPlaceMultipleItems } from './useCatalogPlaceMultipleItems';
|
||||||
|
import { useCatalogSkipPurchaseConfirmation } from './useCatalogSkipPurchaseConfirmation';
|
||||||
|
|
||||||
|
const DUMMY_PAGE_ID_FOR_OFFER_SEARCH = -12345678;
|
||||||
|
const DRAG_AND_DROP_ENABLED = true;
|
||||||
|
|
||||||
|
const useCatalogItemMoverState = (catalog: { currentType: string, pageId: number, currentOffer: IPurchasableOffer, purchaseOptions: IPurchaseOptions }, buildersClub: { furniCount: number, furniLimit: number, secondsLeft: number }) =>
|
||||||
|
{
|
||||||
|
const [ objectMoverRequested, setObjectMoverRequested ] = useState(false);
|
||||||
|
const [ catalogPlaceMultipleObjects, setCatalogPlaceMultipleObjects ] = useCatalogPlaceMultipleItems();
|
||||||
|
const [ catalogSkipPurchaseConfirmation, setCatalogSkipPurchaseConfirmation ] = useCatalogSkipPurchaseConfirmation();
|
||||||
|
const [ purchasableOffer, setPurchaseableOffer ] = useState<IPurchasableOffer>(null);
|
||||||
|
const [ placedObjectPurchaseData, setPlacedObjectPurchaseData ] = useState<PlacedObjectPurchaseData>(null);
|
||||||
|
|
||||||
|
const getBuilderFurniPlaceableStatus = useCallback((offer: IPurchasableOffer) =>
|
||||||
|
{
|
||||||
|
if(!offer) return BuilderFurniPlaceableStatus.MISSING_OFFER;
|
||||||
|
|
||||||
|
if((buildersClub.furniCount < 0) || (buildersClub.furniCount >= buildersClub.furniLimit)) return BuilderFurniPlaceableStatus.FURNI_LIMIT_REACHED;
|
||||||
|
|
||||||
|
const roomSession = GetRoomSession();
|
||||||
|
|
||||||
|
if(!roomSession) return BuilderFurniPlaceableStatus.NOT_IN_ROOM;
|
||||||
|
|
||||||
|
if(!roomSession.isRoomOwner) return BuilderFurniPlaceableStatus.NOT_ROOM_OWNER;
|
||||||
|
|
||||||
|
if(buildersClub.secondsLeft <= 0)
|
||||||
|
{
|
||||||
|
const roomEngine = GetRoomEngine();
|
||||||
|
|
||||||
|
let objectCount = roomEngine.getRoomObjectCount(roomSession.roomId, RoomObjectCategory.UNIT);
|
||||||
|
|
||||||
|
while(objectCount > 0)
|
||||||
|
{
|
||||||
|
const roomObject = roomEngine.getRoomObjectByIndex(roomSession.roomId, objectCount, RoomObjectCategory.UNIT);
|
||||||
|
const userData = roomSession.userDataManager.getUserDataByIndex(roomObject.id);
|
||||||
|
|
||||||
|
if(userData && (userData.type === RoomObjectType.USER) && (userData.roomIndex !== roomSession.ownRoomIndex) && !userData.isModerator) return BuilderFurniPlaceableStatus.VISITORS_IN_ROOM;
|
||||||
|
|
||||||
|
objectCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BuilderFurniPlaceableStatus.OKAY;
|
||||||
|
}, [ buildersClub.furniCount, buildersClub.furniLimit, buildersClub.secondsLeft ]);
|
||||||
|
|
||||||
|
const isDraggable = useCallback((offer: IPurchasableOffer) =>
|
||||||
|
{
|
||||||
|
const roomSession = GetRoomSession();
|
||||||
|
|
||||||
|
if(((DRAG_AND_DROP_ENABLED && roomSession && offer.page && (offer.page.layoutCode !== 'sold_ltd_items') && (catalog.currentType === CatalogType.NORMAL) && (roomSession.isRoomOwner || (roomSession.isGuildRoom && (roomSession.controllerLevel >= RoomControllerLevel.GUILD_MEMBER)))) || ((catalog.currentType === CatalogType.BUILDER) && (getBuilderFurniPlaceableStatus(offer) === BuilderFurniPlaceableStatus.OKAY))) && (offer.pricingModel !== Offer.PRICING_MODEL_BUNDLE) && (offer.product.productType !== ProductTypeEnum.EFFECT) && (offer.product.productType !== ProductTypeEnum.HABBO_CLUB)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}, [ catalog.currentType, getBuilderFurniPlaceableStatus ]);
|
||||||
|
|
||||||
|
const requestOfferToMover = useCallback((offer: IPurchasableOffer) =>
|
||||||
|
{
|
||||||
|
if(!isDraggable(offer)) return;
|
||||||
|
|
||||||
|
const product = offer.product;
|
||||||
|
|
||||||
|
if(!product) return;
|
||||||
|
|
||||||
|
let category = 0;
|
||||||
|
|
||||||
|
switch(product.productType)
|
||||||
|
{
|
||||||
|
case ProductTypeEnum.FLOOR:
|
||||||
|
category = RoomObjectCategory.FLOOR;
|
||||||
|
break;
|
||||||
|
case ProductTypeEnum.WALL:
|
||||||
|
category = RoomObjectCategory.WALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.CATALOG, -(offer.offerId), category, product.productClassId, product.extraParam))
|
||||||
|
{
|
||||||
|
setPurchaseableOffer(offer);
|
||||||
|
setObjectMoverRequested(true);
|
||||||
|
|
||||||
|
CreateLinkEvent('catalog/hide');
|
||||||
|
}
|
||||||
|
}, [ isDraggable ]);
|
||||||
|
|
||||||
|
const resetRoomPaint = useCallback((planeType: string, type: string) =>
|
||||||
|
{
|
||||||
|
const roomEngine = GetRoomEngine();
|
||||||
|
|
||||||
|
let wallType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE);
|
||||||
|
let floorType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE);
|
||||||
|
let landscapeType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_LANDSCAPE_TYPE);
|
||||||
|
|
||||||
|
wallType = (wallType && wallType.length) ? wallType : '101';
|
||||||
|
floorType = (floorType && floorType.length) ? floorType : '101';
|
||||||
|
landscapeType = (landscapeType && landscapeType.length) ? landscapeType : '1.1';
|
||||||
|
|
||||||
|
switch(planeType)
|
||||||
|
{
|
||||||
|
case 'floor':
|
||||||
|
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, type, wallType, landscapeType, true);
|
||||||
|
return;
|
||||||
|
case 'wallpaper':
|
||||||
|
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, type, landscapeType, true);
|
||||||
|
return;
|
||||||
|
case 'landscape':
|
||||||
|
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, wallType, type, true);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
roomEngine.updateRoomInstancePlaneType(roomEngine.activeRoomId, floorType, wallType, landscapeType, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const cancelObjectMover = useCallback(() =>
|
||||||
|
{
|
||||||
|
if(!purchasableOffer) return;
|
||||||
|
|
||||||
|
GetRoomEngine().cancelRoomObjectInsert();
|
||||||
|
|
||||||
|
setObjectMoverRequested(false);
|
||||||
|
setPurchaseableOffer(null);
|
||||||
|
}, [ purchasableOffer ]);
|
||||||
|
|
||||||
|
const resetObjectMover = useCallback((flag: boolean = true) =>
|
||||||
|
{
|
||||||
|
setObjectMoverRequested(prevValue =>
|
||||||
|
{
|
||||||
|
if(prevValue && flag)
|
||||||
|
{
|
||||||
|
CreateLinkEvent('catalog/open');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const resetPlacedOfferData = useCallback((flag: boolean = false) =>
|
||||||
|
{
|
||||||
|
if(!flag) resetObjectMover();
|
||||||
|
|
||||||
|
setPlacedObjectPurchaseData(prevValue =>
|
||||||
|
{
|
||||||
|
if(prevValue)
|
||||||
|
{
|
||||||
|
switch(prevValue.category)
|
||||||
|
{
|
||||||
|
case RoomObjectCategory.FLOOR:
|
||||||
|
GetRoomEngine().removeRoomObjectFloor(prevValue.roomId, prevValue.objectId);
|
||||||
|
break;
|
||||||
|
case RoomObjectCategory.WALL: {
|
||||||
|
|
||||||
|
switch(prevValue.furniData.className)
|
||||||
|
{
|
||||||
|
case 'floor':
|
||||||
|
case 'wallpaper':
|
||||||
|
case 'landscape':
|
||||||
|
resetRoomPaint('reset', '');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GetRoomEngine().removeRoomObjectWall(prevValue.roomId, prevValue.objectId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
GetRoomEngine().deleteRoomObject(prevValue.objectId, prevValue.category);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}, [ resetObjectMover, resetRoomPaint ]);
|
||||||
|
|
||||||
|
const onRoomEngineObjectPlacedEvent = useCallback((event: RoomEngineObjectPlacedEvent) =>
|
||||||
|
{
|
||||||
|
if(!objectMoverRequested || (event.type !== RoomEngineObjectPlacedEvent.PLACED)) return;
|
||||||
|
|
||||||
|
resetPlacedOfferData(true);
|
||||||
|
|
||||||
|
if(!purchasableOffer)
|
||||||
|
{
|
||||||
|
resetObjectMover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let placed = false;
|
||||||
|
|
||||||
|
const product = purchasableOffer.product;
|
||||||
|
|
||||||
|
if(event.category === RoomObjectCategory.WALL)
|
||||||
|
{
|
||||||
|
switch(product.furnitureData.className)
|
||||||
|
{
|
||||||
|
case 'floor':
|
||||||
|
case 'wallpaper':
|
||||||
|
case 'landscape':
|
||||||
|
placed = (event.placedOnFloor || event.placedOnWall);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
placed = event.placedInRoom;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
placed = event.placedInRoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!placed)
|
||||||
|
{
|
||||||
|
resetObjectMover();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlacedObjectPurchaseData(new PlacedObjectPurchaseData(event.roomId, event.objectId, event.category, event.wallLocation, event.x, event.y, event.direction, purchasableOffer));
|
||||||
|
|
||||||
|
switch(catalog.currentType)
|
||||||
|
{
|
||||||
|
case CatalogType.NORMAL: {
|
||||||
|
switch(event.category)
|
||||||
|
{
|
||||||
|
case RoomObjectCategory.FLOOR:
|
||||||
|
GetRoomEngine().addFurnitureFloor(event.roomId, event.objectId, product.productClassId, new Vector3d(event.x, event.y, event.z), new Vector3d(event.direction), 0, new LegacyDataType());
|
||||||
|
break;
|
||||||
|
case RoomObjectCategory.WALL: {
|
||||||
|
switch(product.furnitureData.className)
|
||||||
|
{
|
||||||
|
case 'floor':
|
||||||
|
case 'wallpaper':
|
||||||
|
case 'landscape':
|
||||||
|
resetRoomPaint(product.furnitureData.className, product.extraParam);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GetRoomEngine().addFurnitureWall(event.roomId, event.objectId, product.productClassId, new Vector3d(event.x, event.y, event.z), new Vector3d(event.direction * 45), 0, event.instanceData, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const roomObject = GetRoomEngine().getRoomObject(event.roomId, event.objectId, event.category);
|
||||||
|
|
||||||
|
if(roomObject) roomObject.model.setValue(RoomObjectVariable.FURNITURE_ALPHA_MULTIPLIER, 0.5);
|
||||||
|
|
||||||
|
SendMessageComposer(new PurchaseFromCatalogComposer(catalog.pageId, purchasableOffer.offerId, product.extraParam, 1));
|
||||||
|
|
||||||
|
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CatalogType.BUILDER: {
|
||||||
|
let pageId = purchasableOffer.page.pageId;
|
||||||
|
|
||||||
|
if(pageId === DUMMY_PAGE_ID_FOR_OFFER_SEARCH)
|
||||||
|
{
|
||||||
|
pageId = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(event.category)
|
||||||
|
{
|
||||||
|
case RoomObjectCategory.FLOOR:
|
||||||
|
SendMessageComposer(new BuildersClubPlaceRoomItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.x, event.y, event.direction));
|
||||||
|
break;
|
||||||
|
case RoomObjectCategory.WALL:
|
||||||
|
SendMessageComposer(new BuildersClubPlaceWallItemMessageComposer(pageId, purchasableOffer.offerId, product.extraParam, event.wallLocation));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(catalogPlaceMultipleObjects) requestOfferToMover(purchasableOffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [ objectMoverRequested, purchasableOffer, catalogPlaceMultipleObjects, catalog, resetPlacedOfferData, resetObjectMover, resetRoomPaint, requestOfferToMover ]);
|
||||||
|
|
||||||
|
UseRoomEngineEvent(RoomEngineObjectPlacedEvent.PLACED, onRoomEngineObjectPlacedEvent);
|
||||||
|
|
||||||
|
const onInventoryFurniAddedEvent = useCallback((event: InventoryFurniAddedEvent) =>
|
||||||
|
{
|
||||||
|
const roomEngine = GetRoomEngine();
|
||||||
|
|
||||||
|
if(!placedObjectPurchaseData || (placedObjectPurchaseData.productClassId !== event.spriteId) || (placedObjectPurchaseData.roomId !== roomEngine.activeRoomId)) return;
|
||||||
|
|
||||||
|
switch(event.category)
|
||||||
|
{
|
||||||
|
case FurniCategory.FLOOR: {
|
||||||
|
const floorType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE);
|
||||||
|
|
||||||
|
if(placedObjectPurchaseData.extraParam !== floorType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FurniCategory.WALL_PAPER: {
|
||||||
|
const wallType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE);
|
||||||
|
|
||||||
|
if(placedObjectPurchaseData.extraParam !== wallType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FurniCategory.LANDSCAPE: {
|
||||||
|
const landscapeType = roomEngine.getRoomInstanceVariable(roomEngine.activeRoomId, RoomObjectVariable.ROOM_LANDSCAPE_TYPE);
|
||||||
|
|
||||||
|
if(placedObjectPurchaseData.extraParam !== landscapeType) SendMessageComposer(new FurniturePlacePaintComposer(event.id));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
SendMessageComposer(new FurniturePlaceComposer(event.id, placedObjectPurchaseData.category, placedObjectPurchaseData.wallLocation, placedObjectPurchaseData.x, placedObjectPurchaseData.y, placedObjectPurchaseData.direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!catalogPlaceMultipleObjects) resetPlacedOfferData();
|
||||||
|
}, [ placedObjectPurchaseData, catalogPlaceMultipleObjects, resetPlacedOfferData ]);
|
||||||
|
|
||||||
|
UseUiEvent(InventoryFurniAddedEvent.FURNI_ADDED, onInventoryFurniAddedEvent);
|
||||||
|
|
||||||
|
return { requestOfferToMover, cancelObjectMover };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useCatalogItemMover = useCatalogItemMoverState;
|
7
src/hooks/catalog/useCatalogPlaceMultipleItems.ts
Normal file
7
src/hooks/catalog/useCatalogPlaceMultipleItems.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { LocalStorageKeys } from '../../api';
|
||||||
|
import { useLocalStorage } from '../useLocalStorage';
|
||||||
|
|
||||||
|
const useCatalogPlaceMultipleItemsState = () => useLocalStorage(LocalStorageKeys.CATALOG_PLACE_MULTIPLE_OBJECTS, false);
|
||||||
|
|
||||||
|
export const useCatalogPlaceMultipleItems = () => useBetween(useCatalogPlaceMultipleItemsState);
|
7
src/hooks/catalog/useCatalogSkipPurchaseConfirmation.ts
Normal file
7
src/hooks/catalog/useCatalogSkipPurchaseConfirmation.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { useBetween } from 'use-between';
|
||||||
|
import { LocalStorageKeys } from '../../api';
|
||||||
|
import { useLocalStorage } from '../useLocalStorage';
|
||||||
|
|
||||||
|
const useCatalogSkipPurchaseConfirmationState = () => useLocalStorage(LocalStorageKeys.CATALOG_SKIP_PURCHASE_CONFIRMATION, false);
|
||||||
|
|
||||||
|
export const useCatalogSkipPurchaseConfirmation = () => useBetween(useCatalogSkipPurchaseConfirmationState);
|
@ -1,4 +1,5 @@
|
|||||||
export * from './achievements';
|
export * from './achievements';
|
||||||
|
export * from './catalog';
|
||||||
export * from './events';
|
export * from './events';
|
||||||
export * from './events/core';
|
export * from './events/core';
|
||||||
export * from './events/nitro';
|
export * from './events/nitro';
|
||||||
@ -10,5 +11,6 @@ export * from './navigator';
|
|||||||
export * from './purse';
|
export * from './purse';
|
||||||
export * from './rooms';
|
export * from './rooms';
|
||||||
export * from './session';
|
export * from './session';
|
||||||
|
export * from './useLocalStorage';
|
||||||
export * from './UseMountEffect';
|
export * from './UseMountEffect';
|
||||||
export * from './useSharedVisibility';
|
export * from './useSharedVisibility';
|
||||||
|
@ -4,6 +4,8 @@ import { useBetween } from 'use-between';
|
|||||||
import { useInventoryUnseenTracker } from '.';
|
import { useInventoryUnseenTracker } from '.';
|
||||||
import { UseMessageEventHook } from '..';
|
import { UseMessageEventHook } from '..';
|
||||||
import { addFurnitureItem, attemptItemPlacement, cancelRoomObjectPlacement, CloneObject, CreateLinkEvent, FurnitureItem, getAllItemIds, getPlacingItemId, GroupItem, mergeFurniFragments, SendMessageComposer, UnseenItemCategory } from '../../api';
|
import { addFurnitureItem, attemptItemPlacement, cancelRoomObjectPlacement, CloneObject, CreateLinkEvent, FurnitureItem, getAllItemIds, getPlacingItemId, GroupItem, mergeFurniFragments, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||||
|
import { InventoryFurniAddedEvent } from '../../events';
|
||||||
|
import { DispatchUiEvent } from '../events';
|
||||||
import { useSharedVisibility } from '../useSharedVisibility';
|
import { useSharedVisibility } from '../useSharedVisibility';
|
||||||
|
|
||||||
let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
|
let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
|
||||||
@ -73,6 +75,8 @@ const useInventoryFurniState = () =>
|
|||||||
const furniture = new FurnitureItem(item);
|
const furniture = new FurnitureItem(item);
|
||||||
|
|
||||||
addFurnitureItem(newValue, furniture, isUnseen(UnseenItemCategory.FURNI, item.itemId));
|
addFurnitureItem(newValue, furniture, isUnseen(UnseenItemCategory.FURNI, item.itemId));
|
||||||
|
|
||||||
|
DispatchUiEvent(new InventoryFurniAddedEvent(furniture.id, furniture.type, furniture.category));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +152,8 @@ const useInventoryFurniState = () =>
|
|||||||
|
|
||||||
addFurnitureItem(newValue, item, isUnseen(UnseenItemCategory.FURNI, itemId));
|
addFurnitureItem(newValue, item, isUnseen(UnseenItemCategory.FURNI, itemId));
|
||||||
|
|
||||||
|
DispatchUiEvent(new InventoryFurniAddedEvent(item.id, item.type, item.category));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
|
43
src/hooks/useLocalStorage.ts
Normal file
43
src/hooks/useLocalStorage.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { NitroLogger } from '@nitrots/nitro-renderer';
|
||||||
|
import { Dispatch, SetStateAction, useState } from 'react';
|
||||||
|
|
||||||
|
const useLocalStorageState = <T>(key: string, initialValue: T): [ T, Dispatch<SetStateAction<T>>] =>
|
||||||
|
{
|
||||||
|
const [ storedValue, setStoredValuie ] = useState<T>(() =>
|
||||||
|
{
|
||||||
|
if(typeof window === 'undefined') return initialValue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const item = window.localStorage.getItem(key);
|
||||||
|
|
||||||
|
return item ? JSON.parse(item) : initialValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(error)
|
||||||
|
{
|
||||||
|
return initialValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const setValue = (value: T) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
||||||
|
|
||||||
|
setStoredValuie(valueToStore);
|
||||||
|
|
||||||
|
if(typeof window !== 'undefined') window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(error)
|
||||||
|
{
|
||||||
|
NitroLogger.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [ storedValue, setValue ];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useLocalStorage = useLocalStorageState;
|
Loading…
Reference in New Issue
Block a user