diff --git a/public/renderer-config.json b/public/renderer-config.json
index bf3a12a3..bd228c88 100644
--- a/public/renderer-config.json
+++ b/public/renderer-config.json
@@ -33,6 +33,7 @@
"system.packet.log": false,
"system.pong.manually": true,
"system.pong.interval.ms": 20000,
+ "room.color.skip.transition": true,
"avatar.mandatory.libraries": [
"bd:1",
"li:0"
diff --git a/public/ui-config.json b/public/ui-config.json
index 0551121f..1cf49b7a 100644
--- a/public/ui-config.json
+++ b/public/ui-config.json
@@ -5,24 +5,7 @@
"thumbnails.url": "https://nitro.nitrots.co/camera/thumbnail/%thumbnail%.png",
"url.prefix": "http://localhost:3000",
"chat.viewer.height.percentage": 0.40,
- "navigator.slider.enabled": true,
- "navigator.slider.content": [
- {
- "title": "Games Hub",
- "image": "https://i.imgur.com/TFoivxi.png",
- "roomId": 2240
- },
- {
- "title": "Help Desk",
- "image": "https://i.imgur.com/GO981GC.png",
- "roomId": 2351
- },
- {
- "title": "The Lido",
- "image": "https://i.imgur.com/NVH38bV.png",
- "roomId": 2346
- }
- ],
+ "widget.dimmer.colorwheel": false,
"hotelview": {
"widgets": {
"slot.1.widget": "promoarticle",
diff --git a/src/App.tsx b/src/App.tsx
index 6b759d0e..ae6999e5 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,6 +5,7 @@ import { useConfigurationEvent } from './hooks/events/core/configuration/configu
import { useLocalizationEvent } from './hooks/events/nitro/localization/localization-event';
import { dispatchMainEvent, useMainEvent } from './hooks/events/nitro/main-event';
import { useRoomEngineEvent } from './hooks/events/nitro/room/room-engine-event';
+import { TransitionAnimation, TransitionAnimationTypes } from './layout';
import { LoadingView } from './views/loading/LoadingView';
import { MainView } from './views/main/MainView';
@@ -126,7 +127,9 @@ export const App: FC<{}> = props =>
return (
{ (!isReady || isError) && }
- { (isReady && !isError) && }
+
+
+
);
}
diff --git a/src/api/nitro/room/widgets/events/RoomDimmerPreset.ts b/src/api/nitro/room/widgets/events/RoomDimmerPreset.ts
new file mode 100644
index 00000000..86600d58
--- /dev/null
+++ b/src/api/nitro/room/widgets/events/RoomDimmerPreset.ts
@@ -0,0 +1,35 @@
+export class RoomDimmerPreset
+{
+ private _id: number;
+ private _type: number;
+ private _color: number;
+ private _brightness: number;
+
+ constructor(id: number, type: number, color: number, brightness: number)
+ {
+ this._id = id;
+ this._type = type;
+ this._color = color;
+ this._brightness = brightness;
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get type(): number
+ {
+ return this._type;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public get brightness(): number
+ {
+ return this._brightness;
+ }
+}
diff --git a/src/api/nitro/room/widgets/events/RoomWidgetUpdateCreditFurniEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetUpdateCreditFurniEvent.ts
new file mode 100644
index 00000000..be70172a
--- /dev/null
+++ b/src/api/nitro/room/widgets/events/RoomWidgetUpdateCreditFurniEvent.ts
@@ -0,0 +1,34 @@
+import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
+
+export class RoomWidgetUpdateCreditFurniEvent extends RoomWidgetUpdateEvent
+{
+ public static CREDIT_FURNI_UPDATE: string = 'RWUCFE_CREDIT_FURNI_UPDATE';
+
+ private _objectId: number;
+ private _value: number;
+ private _furniType: string;
+
+ constructor(type: string, objectId: number, value: number, furniType: string)
+ {
+ super(type);
+
+ this._objectId = objectId;
+ this._value = value;
+ this._furniType = furniType;
+ }
+
+ public get objectId(): number
+ {
+ return this._objectId;
+ }
+
+ public get value(): number
+ {
+ return this._value;
+ }
+
+ public get furniType(): string
+ {
+ return this._furniType;
+ }
+}
diff --git a/src/api/nitro/room/widgets/events/RoomWidgetUpdateDimmerEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetUpdateDimmerEvent.ts
new file mode 100644
index 00000000..82cdb0c6
--- /dev/null
+++ b/src/api/nitro/room/widgets/events/RoomWidgetUpdateDimmerEvent.ts
@@ -0,0 +1,50 @@
+import { RoomDimmerPreset } from './RoomDimmerPreset';
+import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
+
+export class RoomWidgetUpdateDimmerEvent extends RoomWidgetUpdateEvent
+{
+ public static PRESETS: string = 'RWUDE_PRESETS';
+ public static HIDE: string = 'RWUDE_HIDE';
+
+ private _selectedPresetId: number = 0;
+ private _presets: RoomDimmerPreset[];
+
+ constructor(type: string)
+ {
+ super(type);
+
+ this._presets = [];
+ }
+
+ public get presetCount(): number
+ {
+ return this._presets.length;
+ }
+
+ public get presets(): RoomDimmerPreset[]
+ {
+ return this._presets;
+ }
+
+ public get selectedPresetId(): number
+ {
+ return this._selectedPresetId;
+ }
+
+ public set selectedPresetId(k: number)
+ {
+ this._selectedPresetId = k;
+ }
+
+ public setPresetValues(id: number, type: number, color: number, brightness: number):void
+ {
+ const preset = new RoomDimmerPreset(id, type, color, brightness);
+
+ this._presets[(id - 1)] = preset;
+ }
+
+ public getPresetNumber(id: number): RoomDimmerPreset
+ {
+ return this._presets[id];
+ }
+}
diff --git a/src/api/nitro/room/widgets/events/RoomWidgetUpdateDimmerStateEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetUpdateDimmerStateEvent.ts
new file mode 100644
index 00000000..27e9fd13
--- /dev/null
+++ b/src/api/nitro/room/widgets/events/RoomWidgetUpdateDimmerStateEvent.ts
@@ -0,0 +1,48 @@
+import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
+
+export class RoomWidgetUpdateDimmerStateEvent extends RoomWidgetUpdateEvent
+{
+ public static DIMMER_STATE: string = 'RWUDSE_DIMMER_STATE';
+
+ private _state: number;
+ private _presetId: number;
+ private _effectId: number;
+ private _color: number;
+ private _brightness: number;
+
+ constructor(state: number, presetId: number, effectId: number, color: number, brightness: number)
+ {
+ super(RoomWidgetUpdateDimmerStateEvent.DIMMER_STATE);
+
+ this._state = state;
+ this._presetId = presetId;
+ this._effectId = effectId;
+ this._color = color;
+ this._brightness = brightness;
+ }
+
+ public get state(): number
+ {
+ return this._state;
+ }
+
+ public get presetId(): number
+ {
+ return this._presetId;
+ }
+
+ public get effectId(): number
+ {
+ return this._effectId;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public get brightness(): number
+ {
+ return this._brightness;
+ }
+}
diff --git a/src/api/nitro/room/widgets/events/RoomWidgetUpdatePresentDataEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetUpdatePresentDataEvent.ts
new file mode 100644
index 00000000..4a4567b3
--- /dev/null
+++ b/src/api/nitro/room/widgets/events/RoomWidgetUpdatePresentDataEvent.ts
@@ -0,0 +1,116 @@
+import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
+
+export class RoomWidgetUpdatePresentDataEvent extends RoomWidgetUpdateEvent
+{
+ public static PACKAGEINFO: string = 'RWUPDE_PACKAGEINFO';
+ public static CONTENTS: string = 'RWUPDE_CONTENTS';
+ public static CONTENTS_CLUB: string = 'RWUPDE_CONTENTS_CLUB';
+ public static CONTENTS_FLOOR: string = 'RWUPDE_CONTENTS_FLOOR';
+ public static CONTENTS_LANDSCAPE: string = 'RWUPDE_CONTENTS_LANDSCAPE';
+ public static CONTENTS_WALLPAPER: string = 'RWUPDE_CONTENTS_WALLPAPER';
+ public static CONTENTS_IMAGE: string = 'RWUPDE_CONTENTS_IMAGE';
+
+ private _objectId: number = -1;
+ private _classId: number = 0;
+ private _itemType: string = '';
+ private _giftMessage: string = '';
+ private _imageUrl: string = null;
+ private _isController: boolean;
+ private _purchaserName: string;
+ private _purchaserFigure: string;
+ private _placedItemId: number = -1;
+ private _placedItemType: string = '';
+ private _placedInRoom: boolean;
+
+ constructor(type: string, objectId: number, giftMessage: string, isOwnerOfFurniture: boolean = false, imageUrl: string = null, purchaserName: string = null, purchaserFigure: string = null)
+ {
+ super(type);
+
+ this._objectId = objectId;
+ this._giftMessage = giftMessage;
+ this._imageUrl = imageUrl;
+ this._isController = isOwnerOfFurniture;
+ this._purchaserName = purchaserName;
+ this._purchaserFigure = purchaserFigure;
+ }
+
+ public get objectId(): number
+ {
+ return this._objectId;
+ }
+
+ public get classId(): number
+ {
+ return this._classId;
+ }
+
+ public set classId(classId: number)
+ {
+ this._classId = classId;
+ }
+
+ public get itemType(): string
+ {
+ return this._itemType;
+ }
+
+ public set itemType(type: string)
+ {
+ this._itemType = type;
+ }
+
+ public get giftMessage(): string
+ {
+ return this._giftMessage;
+ }
+
+ public get imageUrl(): string
+ {
+ return this._imageUrl;
+ }
+
+ public get isController(): boolean
+ {
+ return this._isController;
+ }
+
+ public get purchaserName(): string
+ {
+ return this._purchaserName;
+ }
+
+ public get purchaserFigure(): string
+ {
+ return this._purchaserFigure;
+ }
+
+ public get placedItemId(): number
+ {
+ return this._placedItemId;
+ }
+
+ public set placedItemId(itemId: number)
+ {
+ this._placedItemId = itemId;
+ }
+
+ public get placedInRoom(): boolean
+ {
+ return this._placedInRoom;
+ }
+
+ public set placedInRoom(flag: boolean)
+ {
+ this._placedInRoom = flag;
+ }
+
+ public get placedItemType(): string
+ {
+ return this._placedItemType;
+ }
+
+ public set placedItemType(type: string)
+ {
+ this._placedItemType = type;
+ }
+}
diff --git a/src/api/nitro/room/widgets/events/index.ts b/src/api/nitro/room/widgets/events/index.ts
index cdb95870..f612d85b 100644
--- a/src/api/nitro/room/widgets/events/index.ts
+++ b/src/api/nitro/room/widgets/events/index.ts
@@ -1,4 +1,5 @@
export * from './IPhotoData';
+export * from './RoomDimmerPreset';
export * from './RoomObjectItem';
export * from './RoomWidgetAvatarInfoEvent';
export * from './RoomWidgetChooserContentEvent';
@@ -10,8 +11,11 @@ export * from './RoomWidgetRoomObjectUpdateEvent';
export * from './RoomWidgetUpdateBackgroundColorPreviewEvent';
export * from './RoomWidgetUpdateChatEvent';
export * from './RoomWidgetUpdateChatInputContentEvent';
+export * from './RoomWidgetUpdateCreditFurniEvent';
export * from './RoomWidgetUpdateCustomStackHeightEvent';
export * from './RoomWidgetUpdateDanceStatusEvent';
+export * from './RoomWidgetUpdateDimmerEvent';
+export * from './RoomWidgetUpdateDimmerStateEvent';
export * from './RoomWidgetUpdateEvent';
export * from './RoomWidgetUpdateExternalImageEvent';
export * from './RoomWidgetUpdateInfostandEvent';
@@ -19,6 +23,7 @@ export * from './RoomWidgetUpdateInfostandFurniEvent';
export * from './RoomWidgetUpdateInfostandPetEvent';
export * from './RoomWidgetUpdateInfostandRentableBotEvent';
export * from './RoomWidgetUpdateInfostandUserEvent';
+export * from './RoomWidgetUpdatePresentDataEvent';
export * from './RoomWidgetUpdateRentableBotChatEvent';
export * from './RoomWidgetUpdateRoomViewEvent';
export * from './RoomWidgetUpdateSongEvent';
diff --git a/src/api/nitro/room/widgets/handlers/FurnitureCreditWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/FurnitureCreditWidgetHandler.ts
new file mode 100644
index 00000000..7ab62fbb
--- /dev/null
+++ b/src/api/nitro/room/widgets/handlers/FurnitureCreditWidgetHandler.ts
@@ -0,0 +1,59 @@
+import { FurnitureExchangeComposer, NitroEvent, RoomObjectVariable, RoomWidgetEnum } from '@nitrots/nitro-renderer';
+import { RoomWidgetCreditFurniRedeemMessage, RoomWidgetUpdateCreditFurniEvent, RoomWidgetUpdateEvent } from '..';
+import { GetRoomEngine } from '../..';
+import { IsOwnerOfFurniture } from '../../..';
+import { RoomWidgetFurniToWidgetMessage, RoomWidgetMessage } from '../messages';
+import { RoomWidgetHandler } from './RoomWidgetHandler';
+
+export class FurnitureCreditWidgetHandler extends RoomWidgetHandler
+{
+ public processEvent(event: NitroEvent): void
+ {
+ return;
+ }
+
+ public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
+ {
+ switch(message.type)
+ {
+ case RoomWidgetFurniToWidgetMessage.REQUEST_CREDITFURNI: {
+ const creditMessage = (message as RoomWidgetFurniToWidgetMessage);
+
+ const roomObject = GetRoomEngine().getRoomObject(creditMessage.roomId, creditMessage.objectId, creditMessage.category);
+
+ if(!roomObject || !IsOwnerOfFurniture(roomObject)) return;
+
+ this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateCreditFurniEvent(RoomWidgetUpdateCreditFurniEvent.CREDIT_FURNI_UPDATE, creditMessage.objectId, roomObject.model.getValue(RoomObjectVariable.FURNITURE_CREDIT_VALUE), (roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID) + '_' + creditMessage.type + '_' + creditMessage.objectId)));
+
+ break;
+ }
+ case RoomWidgetCreditFurniRedeemMessage.REDEEM: {
+ const redeemMessage = (message as RoomWidgetCreditFurniRedeemMessage);
+
+ this.container.roomSession.connection.send(new FurnitureExchangeComposer(redeemMessage.objectId));
+
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ public get type(): string
+ {
+ return RoomWidgetEnum.FURNI_CREDIT_WIDGET;
+ }
+
+ public get eventTypes(): string[]
+ {
+ return [];
+ }
+
+ public get messageTypes(): string[]
+ {
+ return [
+ RoomWidgetFurniToWidgetMessage.REQUEST_CREDITFURNI,
+ RoomWidgetCreditFurniRedeemMessage.REDEEM
+ ];
+ }
+}
diff --git a/src/api/nitro/room/widgets/handlers/FurnitureDimmerWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/FurnitureDimmerWidgetHandler.ts
new file mode 100644
index 00000000..71e35268
--- /dev/null
+++ b/src/api/nitro/room/widgets/handlers/FurnitureDimmerWidgetHandler.ts
@@ -0,0 +1,114 @@
+import { NitroEvent, RoomControllerLevel, RoomEngineDimmerStateEvent, RoomEngineTriggerWidgetEvent, RoomSessionDimmerPresetsEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer';
+import { GetRoomEngine } from '../..';
+import { GetSessionDataManager } from '../../..';
+import { RoomWidgetUpdateDimmerEvent, RoomWidgetUpdateEvent } from '../events';
+import { RoomWidgetUpdateDimmerStateEvent } from '../events/RoomWidgetUpdateDimmerStateEvent';
+import { RoomWidgetDimmerChangeStateMessage, RoomWidgetDimmerPreviewMessage, RoomWidgetFurniToWidgetMessage, RoomWidgetMessage } from '../messages';
+import { RoomWidgetDimmerSavePresetMessage } from '../messages/RoomWidgetDimmerSavePresetMessage';
+import { RoomWidgetHandler } from './RoomWidgetHandler';
+
+export class FurnitureDimmerWidgetHandler extends RoomWidgetHandler
+{
+ public processEvent(event: NitroEvent): void
+ {
+ switch(event.type)
+ {
+ case RoomSessionDimmerPresetsEvent.ROOM_DIMMER_PRESETS: {
+ const presetsEvent = (event as RoomSessionDimmerPresetsEvent);
+ const updateEvent = new RoomWidgetUpdateDimmerEvent(RoomWidgetUpdateDimmerEvent.PRESETS);
+
+ updateEvent.selectedPresetId = presetsEvent.selectedPresetId;
+
+ let i = 0;
+
+ while(i < presetsEvent.presetCount)
+ {
+ const preset = presetsEvent.getPreset(i);
+
+ if(preset) updateEvent.setPresetValues(preset.id, preset.type, preset.color, preset.brightness);
+
+ i++;
+ }
+
+ this.container.eventDispatcher.dispatchEvent(updateEvent);
+ return;
+ }
+ case RoomEngineDimmerStateEvent.ROOM_COLOR: {
+ const stateEvent = (event as RoomEngineDimmerStateEvent);
+
+ this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateDimmerStateEvent(stateEvent.state, stateEvent.presetId, stateEvent.effectId, stateEvent.color, stateEvent.brightness));
+ return;
+ }
+ case RoomEngineTriggerWidgetEvent.REMOVE_DIMMER: {
+ this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateDimmerEvent(RoomWidgetUpdateDimmerEvent.HIDE));
+ return;
+ }
+ }
+ }
+
+ public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
+ {
+ switch(message.type)
+ {
+ case RoomWidgetFurniToWidgetMessage.REQUEST_DIMMER: {
+ if(this.canOpenWidget()) this.container.roomSession.requestMoodlightSettings();
+
+ break;
+ }
+ case RoomWidgetDimmerSavePresetMessage.SAVE_PRESET: {
+ if(this.canOpenWidget())
+ {
+ const savePresetMessage = (message as RoomWidgetDimmerSavePresetMessage);
+
+ this.container.roomSession.updateMoodlightData(savePresetMessage.presetNumber, savePresetMessage.effectTypeId, savePresetMessage.color, savePresetMessage.brightness, savePresetMessage.apply);
+ }
+
+ break;
+ }
+ case RoomWidgetDimmerChangeStateMessage.CHANGE_STATE: {
+ if(this.canOpenWidget()) this.container.roomSession.toggleMoodlightState();
+
+ break;
+ }
+ case RoomWidgetDimmerPreviewMessage.PREVIEW_DIMMER_PRESET: {
+ const roomId = this.container.roomSession.roomId;
+ const previewMessage = (message as RoomWidgetDimmerPreviewMessage);
+
+ GetRoomEngine().updateObjectRoomColor(roomId, previewMessage.color, previewMessage.brightness, previewMessage.bgOnly);
+
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ private canOpenWidget(): boolean
+ {
+ return (this.container.roomSession.isRoomOwner || (this.container.roomSession.controllerLevel >= RoomControllerLevel.GUEST) || GetSessionDataManager().isModerator);
+ }
+
+ public get type(): string
+ {
+ return RoomWidgetEnum.ROOM_DIMMER;
+ }
+
+ public get eventTypes(): string[]
+ {
+ return [
+ RoomSessionDimmerPresetsEvent.ROOM_DIMMER_PRESETS,
+ RoomEngineDimmerStateEvent.ROOM_COLOR,
+ RoomEngineTriggerWidgetEvent.REMOVE_DIMMER
+ ];
+ }
+
+ public get messageTypes(): string[]
+ {
+ return [
+ RoomWidgetFurniToWidgetMessage.REQUEST_DIMMER,
+ RoomWidgetDimmerSavePresetMessage.SAVE_PRESET,
+ RoomWidgetDimmerChangeStateMessage.CHANGE_STATE,
+ RoomWidgetDimmerPreviewMessage.PREVIEW_DIMMER_PRESET
+ ];
+ }
+}
diff --git a/src/api/nitro/room/widgets/handlers/FurniturePresentWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/FurniturePresentWidgetHandler.ts
new file mode 100644
index 00000000..745ed868
--- /dev/null
+++ b/src/api/nitro/room/widgets/handlers/FurniturePresentWidgetHandler.ts
@@ -0,0 +1,223 @@
+import { IFurnitureData, IGetImageListener, NitroEvent, NitroRenderTexture, PetFigureData, RoomObjectCategory, RoomObjectVariable, RoomSessionPresentEvent, RoomWidgetEnum, TextureUtils, Vector3d } from '@nitrots/nitro-renderer';
+import { GetSessionDataManager, IsOwnerOfFurniture } from '../../..';
+import { GetRoomEngine, LocalizeText } from '../../../..';
+import { ProductTypeEnum } from '../../../../../views/catalog/common/ProductTypeEnum';
+import { RoomWidgetUpdateEvent, RoomWidgetUpdatePresentDataEvent } from '../events';
+import { RoomWidgetFurniToWidgetMessage, RoomWidgetPresentOpenMessage } from '../messages';
+import { RoomWidgetMessage } from '../messages/RoomWidgetMessage';
+import { RoomWidgetHandler } from './RoomWidgetHandler';
+
+export class FurniturePresentWidgetHandler extends RoomWidgetHandler implements IGetImageListener
+{
+ private static FLOOR: string = 'floor';
+ private static WALLPAPER: string = 'wallpaper';
+ private static LANDSCAPE: string = 'landscape';
+ private static POSTER: string = 'poster';
+
+ private _lastFurniId: number = -1;
+ private _name: string = null;
+
+ public processEvent(event: NitroEvent): void
+ {
+ switch(event.type)
+ {
+ case RoomSessionPresentEvent.RSPE_PRESENT_OPENED: {
+ const presentEvent = (event as RoomSessionPresentEvent);
+
+ let furniData: IFurnitureData = null;
+
+ if(presentEvent.itemType === ProductTypeEnum.FLOOR)
+ {
+ furniData = GetSessionDataManager().getFloorItemData(presentEvent.classId);
+ }
+ else if(presentEvent.itemType === ProductTypeEnum.WALL)
+ {
+ furniData = GetSessionDataManager().getWallItemData(presentEvent.classId);
+ }
+
+ let isOwnerOfFurni = false;
+
+ if(presentEvent.placedInRoom)
+ {
+ const roomObject = GetRoomEngine().getRoomObject(this.container.roomSession.roomId, presentEvent.placedItemId, RoomObjectCategory.FLOOR);
+
+ if(roomObject) isOwnerOfFurni = IsOwnerOfFurniture(roomObject);
+ }
+
+ let giftImage: string = null;
+ let dataUpdateEvent: RoomWidgetUpdatePresentDataEvent = null;
+
+ switch(presentEvent.itemType)
+ {
+ case ProductTypeEnum.WALL: {
+ if(furniData)
+ {
+ switch(furniData.className)
+ {
+ case FurniturePresentWidgetHandler.FLOOR:
+ dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS_FLOOR, 0, LocalizeText('inventory.furni.item.floor.name'), isOwnerOfFurni);
+ break;
+ case FurniturePresentWidgetHandler.LANDSCAPE:
+ dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS_LANDSCAPE, 0, LocalizeText('inventory.furni.item.landscape.name'), isOwnerOfFurni);
+ break;
+ case FurniturePresentWidgetHandler.WALLPAPER:
+ dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS_WALLPAPER, 0, LocalizeText('inventory.furni.item.wallpaper.name'), isOwnerOfFurni);
+ break;
+ case FurniturePresentWidgetHandler.POSTER: {
+ const productCode = presentEvent.productCode;
+
+ let extras: string = null;
+
+ if(productCode.indexOf('poster') === 0) extras = productCode.replace('poster', '');
+
+ giftImage = GetRoomEngine().getFurnitureWallIconUrl(presentEvent.classId, extras);
+
+ const productData = GetSessionDataManager().getProductData(productCode);
+
+ if(productData) this._name = productData.name;
+ else if(furniData) this._name = furniData.name;
+
+ dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS, 0, this._name, isOwnerOfFurni, giftImage);
+
+ break;
+ }
+ default: {
+ giftImage = GetRoomEngine().getFurnitureWallIconUrl(presentEvent.classId);
+
+ if(furniData) this._name = furniData.name;
+
+ dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS, 0, this._name, isOwnerOfFurni, giftImage);
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case ProductTypeEnum.HABBO_CLUB:
+ dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS_CLUB, 0, LocalizeText('widget.furni.present.hc'), false);
+ break;
+ default: {
+ if(presentEvent.placedItemType === ProductTypeEnum.PET)
+ {
+ const petfigureString = presentEvent.petFigureString;
+
+ if(petfigureString && petfigureString.length)
+ {
+ const petFigureData = new PetFigureData(petfigureString);
+
+ const petImage = GetRoomEngine().getRoomObjectPetImage(petFigureData.typeId, petFigureData.paletteId, petFigureData.color, new Vector3d(90), 64, this, true, 0, petFigureData.customParts);
+
+ if(petImage) giftImage = petImage.getImage().src;
+ }
+ }
+
+ if(!giftImage)
+ {
+ const furniImage = GetRoomEngine().getFurnitureFloorImage(presentEvent.classId, new Vector3d(90), 64, this);
+
+ if(furniImage) giftImage = furniImage.getImage().src;
+ }
+
+ const productData = GetSessionDataManager().getProductData(presentEvent.productCode);
+
+ if(productData) this._name = productData.name;
+ else this._name = furniData.name;
+
+ if(giftImage) dataUpdateEvent = new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS, 0, this._name, isOwnerOfFurni, giftImage);
+
+ break;
+ }
+ }
+
+ if(dataUpdateEvent)
+ {
+ dataUpdateEvent.classId = presentEvent.classId;
+ dataUpdateEvent.itemType = presentEvent.itemType;
+ dataUpdateEvent.placedItemId = presentEvent.placedItemId;
+ dataUpdateEvent.placedInRoom = presentEvent.placedInRoom;
+ dataUpdateEvent.placedItemType = presentEvent.placedItemType;
+
+ this.container.eventDispatcher.dispatchEvent(dataUpdateEvent);
+ }
+
+ return;
+ }
+ }
+ }
+
+ public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
+ {
+ switch(message.type)
+ {
+ case RoomWidgetFurniToWidgetMessage.REQUEST_PRESENT: {
+ const widgetMessage = (message as RoomWidgetFurniToWidgetMessage);
+
+ const roomObject = GetRoomEngine().getRoomObject(widgetMessage.roomId, widgetMessage.objectId, widgetMessage.category);
+
+ if(!roomObject) return null;
+
+ this._lastFurniId = widgetMessage.objectId;
+
+ const giftMessage = (roomObject.model.getValue(RoomObjectVariable.FURNITURE_DATA) || '');
+ const purchaserName = roomObject.model.getValue(RoomObjectVariable.FURNITURE_PURCHASER_NAME);
+ const purchaserFigure = roomObject.model.getValue(RoomObjectVariable.FURNITURE_PURCHASER_FIGURE);
+ const typeId = roomObject.model.getValue(RoomObjectVariable.FURNITURE_TYPE_ID);
+ const extras = roomObject.model.getValue(RoomObjectVariable.FURNITURE_EXTRAS);
+ const giftImage = GetRoomEngine().getFurnitureFloorImage(typeId, new Vector3d(180), 64, null, 0, extras);
+
+ this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.PACKAGEINFO, widgetMessage.objectId, giftMessage, IsOwnerOfFurniture(roomObject), giftImage.getImage().src, purchaserName, purchaserFigure));
+
+ break;
+ }
+ case RoomWidgetPresentOpenMessage.OPEN_PRESENT: {
+ const openMessage = (message as RoomWidgetPresentOpenMessage);
+
+ if(openMessage.objectId !== this._lastFurniId) return null;
+
+ this.container.roomSession.openGift(openMessage.objectId);
+
+ GetRoomEngine().changeObjectModelData(GetRoomEngine().activeRoomId, openMessage.objectId, RoomObjectCategory.FLOOR, RoomObjectVariable.FURNITURE_DISABLE_PICKING_ANIMATION, 1);
+
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ public imageReady(id: number, texture: NitroRenderTexture, image: HTMLImageElement = null): void
+ {
+ let imageUrl: string = null;
+
+ if(image) imageUrl = image.src;
+ else if(texture) imageUrl = TextureUtils.generateImageUrl(texture);
+
+ this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdatePresentDataEvent(RoomWidgetUpdatePresentDataEvent.CONTENTS_IMAGE, 0, this._name, false, imageUrl));
+ }
+
+ public imageFailed(id: number): void
+ {
+
+ }
+
+ public get type(): string
+ {
+ return RoomWidgetEnum.FURNI_PRESENT_WIDGET;
+ }
+
+ public get eventTypes(): string[]
+ {
+ return [
+ RoomSessionPresentEvent.RSPE_PRESENT_OPENED
+ ];
+ }
+
+ public get messageTypes(): string[]
+ {
+ return [
+ RoomWidgetFurniToWidgetMessage.REQUEST_PRESENT,
+ RoomWidgetPresentOpenMessage.OPEN_PRESENT
+ ];
+ }
+}
diff --git a/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts b/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts
index 8daf7bc0..81f5411d 100644
--- a/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts
+++ b/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts
@@ -1,4 +1,5 @@
import { AvatarExpressionEnum, HabboClubLevelEnum, NitroEvent, RoomControllerLevel, RoomSessionChatEvent, RoomSettingsComposer, RoomWidgetEnum, RoomZoomEvent, TextureUtils } from '@nitrots/nitro-renderer';
+import { GetConfiguration, GetNitroInstance } from '../../..';
import { GetRoomEngine, GetSessionDataManager } from '../../../..';
import { SendMessageHook } from '../../../../../hooks/messages';
import { RoomWidgetFloodControlEvent, RoomWidgetUpdateEvent } from '../events';
@@ -146,6 +147,12 @@ export class RoomWidgetChatInputHandler extends RoomWidgetHandler
}
return null;
+ case ':togglefps': {
+ if(GetNitroInstance().ticker.maxFPS > 0) GetNitroInstance().ticker.maxFPS = 0;
+ else GetNitroInstance().ticker.maxFPS = GetConfiguration('system.animation.fps');
+
+ return null;
+ }
case ':client':
case ':nitro':
case ':billsonnn':
diff --git a/src/api/nitro/room/widgets/handlers/index.ts b/src/api/nitro/room/widgets/handlers/index.ts
index d787e68c..f2a12569 100644
--- a/src/api/nitro/room/widgets/handlers/index.ts
+++ b/src/api/nitro/room/widgets/handlers/index.ts
@@ -1,8 +1,11 @@
export * from './DoorbellWidgetHandler';
export * from './FurniChooserWidgetHandler';
export * from './FurnitureContextMenuWidgetHandler';
+export * from './FurnitureCreditWidgetHandler';
export * from './FurnitureCustomStackHeightWidgetHandler';
+export * from './FurnitureDimmerWidgetHandler';
export * from './FurnitureExternalImageWidgetHandler';
+export * from './FurniturePresentWidgetHandler';
export * from './IRoomWidgetHandler';
export * from './IRoomWidgetHandlerManager';
export * from './RoomWidgetAvatarInfoHandler';
diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetCreditFurniRedeemMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetCreditFurniRedeemMessage.ts
new file mode 100644
index 00000000..7b77fdaa
--- /dev/null
+++ b/src/api/nitro/room/widgets/messages/RoomWidgetCreditFurniRedeemMessage.ts
@@ -0,0 +1,20 @@
+import { RoomWidgetMessage } from './RoomWidgetMessage';
+
+export class RoomWidgetCreditFurniRedeemMessage extends RoomWidgetMessage
+{
+ public static REDEEM: string = 'RWCFRM_REDEEM';
+
+ private _objectId: number;
+
+ constructor(type: string, objectId: number)
+ {
+ super(type);
+
+ this._objectId = objectId;
+ }
+
+ public get objectId(): number
+ {
+ return this._objectId;
+ }
+}
diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetDimmerChangeStateMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetDimmerChangeStateMessage.ts
new file mode 100644
index 00000000..de83f498
--- /dev/null
+++ b/src/api/nitro/room/widgets/messages/RoomWidgetDimmerChangeStateMessage.ts
@@ -0,0 +1,11 @@
+import { RoomWidgetMessage } from './RoomWidgetMessage';
+
+export class RoomWidgetDimmerChangeStateMessage extends RoomWidgetMessage
+{
+ public static CHANGE_STATE: string = 'RWCDSM_CHANGE_STATE';
+
+ constructor()
+ {
+ super(RoomWidgetDimmerChangeStateMessage.CHANGE_STATE);
+ }
+}
diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetDimmerPreviewMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetDimmerPreviewMessage.ts
new file mode 100644
index 00000000..39708872
--- /dev/null
+++ b/src/api/nitro/room/widgets/messages/RoomWidgetDimmerPreviewMessage.ts
@@ -0,0 +1,34 @@
+import { RoomWidgetMessage } from './RoomWidgetMessage';
+
+export class RoomWidgetDimmerPreviewMessage extends RoomWidgetMessage
+{
+ public static PREVIEW_DIMMER_PRESET: string = 'RWDPM_PREVIEW_DIMMER_PRESET';
+
+ private _color: number;
+ private _brightness: number;
+ private _bgOnly: boolean;
+
+ constructor(color: number, brightness: number, bgOnly: boolean)
+ {
+ super(RoomWidgetDimmerPreviewMessage.PREVIEW_DIMMER_PRESET);
+
+ this._color = color;
+ this._brightness = brightness;
+ this._bgOnly = bgOnly;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public get brightness(): number
+ {
+ return this._brightness;
+ }
+
+ public get bgOnly(): boolean
+ {
+ return this._bgOnly;
+ }
+}
diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetDimmerSavePresetMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetDimmerSavePresetMessage.ts
new file mode 100644
index 00000000..8e7bd831
--- /dev/null
+++ b/src/api/nitro/room/widgets/messages/RoomWidgetDimmerSavePresetMessage.ts
@@ -0,0 +1,48 @@
+import { RoomWidgetMessage } from './RoomWidgetMessage';
+
+export class RoomWidgetDimmerSavePresetMessage extends RoomWidgetMessage
+{
+ public static SAVE_PRESET: string = 'RWSDPM_SAVE_PRESET';
+
+ private _presetNumber: number;
+ private _effectTypeId: number;
+ private _color: number;
+ private _brightness: number;
+ private _apply: boolean;
+
+ constructor(presetNumber: number, effectTypeId: number, color: number, brightness: number, apply: boolean)
+ {
+ super(RoomWidgetDimmerSavePresetMessage.SAVE_PRESET);
+
+ this._presetNumber = presetNumber;
+ this._effectTypeId = effectTypeId;
+ this._color = color;
+ this._brightness = brightness;
+ this._apply = apply;
+ }
+
+ public get presetNumber(): number
+ {
+ return this._presetNumber;
+ }
+
+ public get effectTypeId(): number
+ {
+ return this._effectTypeId;
+ }
+
+ public get color(): number
+ {
+ return this._color;
+ }
+
+ public get brightness(): number
+ {
+ return this._brightness;
+ }
+
+ public get apply(): boolean
+ {
+ return this._apply;
+ }
+}
diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetPresentOpenMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetPresentOpenMessage.ts
new file mode 100644
index 00000000..20f34f49
--- /dev/null
+++ b/src/api/nitro/room/widgets/messages/RoomWidgetPresentOpenMessage.ts
@@ -0,0 +1,20 @@
+import { RoomWidgetMessage } from './RoomWidgetMessage';
+
+export class RoomWidgetPresentOpenMessage extends RoomWidgetMessage
+{
+ public static OPEN_PRESENT: string = 'RWPOM_OPEN_PRESENT';
+
+ private _objectId: number;
+
+ constructor(type: string, objectId: number)
+ {
+ super(type);
+
+ this._objectId = objectId;
+ }
+
+ public get objectId(): number
+ {
+ return this._objectId;
+ }
+}
diff --git a/src/api/nitro/room/widgets/messages/index.ts b/src/api/nitro/room/widgets/messages/index.ts
index 732e5665..287a3aa6 100644
--- a/src/api/nitro/room/widgets/messages/index.ts
+++ b/src/api/nitro/room/widgets/messages/index.ts
@@ -4,11 +4,16 @@ export * from './RoomWidgetChangePostureMessage';
export * from './RoomWidgetChatMessage';
export * from './RoomWidgetChatSelectAvatarMessage';
export * from './RoomWidgetChatTypingMessage';
+export * from './RoomWidgetCreditFurniRedeemMessage';
export * from './RoomWidgetDanceMessage';
+export * from './RoomWidgetDimmerChangeStateMessage';
+export * from './RoomWidgetDimmerPreviewMessage';
+export * from './RoomWidgetDimmerSavePresetMessage';
export * from './RoomWidgetFurniActionMessage';
export * from './RoomWidgetFurniToWidgetMessage';
export * from './RoomWidgetLetUserInMessage';
export * from './RoomWidgetMessage';
+export * from './RoomWidgetPresentOpenMessage';
export * from './RoomWidgetRequestWidgetMessage';
export * from './RoomWidgetRoomObjectMessage';
export * from './RoomWidgetUseProductMessage';
diff --git a/src/api/utils/ColorUtils.ts b/src/api/utils/ColorUtils.ts
index fade642f..ccb6e27a 100644
--- a/src/api/utils/ColorUtils.ts
+++ b/src/api/utils/ColorUtils.ts
@@ -4,4 +4,14 @@ export class ColorUtils
{
return ('#' + color);
}
+
+ public static makeColorNumberHex(color: number): string
+ {
+ return ( '#' + color.toString(16));
+ }
+
+ public static convertFromHex(color: string): number
+ {
+ return parseInt(color.replace('#', ''), 16);
+ }
}
diff --git a/src/assets/images/catalog/hc_banner_big.png b/src/assets/images/catalog/hc_banner_big.png
new file mode 100644
index 00000000..4b2c4ec3
Binary files /dev/null and b/src/assets/images/catalog/hc_banner_big.png differ
diff --git a/src/assets/images/gift/gift_tag.png b/src/assets/images/gift/gift_tag.png
new file mode 100644
index 00000000..3c24813e
Binary files /dev/null and b/src/assets/images/gift/gift_tag.png differ
diff --git a/src/assets/images/catalog/incognito.png b/src/assets/images/gift/incognito.png
similarity index 100%
rename from src/assets/images/catalog/incognito.png
rename to src/assets/images/gift/incognito.png
diff --git a/src/assets/images/room-widgets/dimmer-widget/dimmer_banner.png b/src/assets/images/room-widgets/dimmer-widget/dimmer_banner.png
new file mode 100644
index 00000000..fdc6e9fa
Binary files /dev/null and b/src/assets/images/room-widgets/dimmer-widget/dimmer_banner.png differ
diff --git a/src/events/catalog/CatalogEvent.ts b/src/events/catalog/CatalogEvent.ts
index f6d6bf72..f4f0f1d1 100644
--- a/src/events/catalog/CatalogEvent.ts
+++ b/src/events/catalog/CatalogEvent.ts
@@ -9,6 +9,8 @@ export class CatalogEvent extends NitroEvent
public static PURCHASE_FAILED: string = 'CE_PURCHASE_FAILED';
public static SOLD_OUT: string = 'CE_SOLD_OUT';
public static APPROVE_NAME_RESULT: string = 'CE_APPROVE_NAME_RESULT';
+ public static GIFT_RECEIVER_NOT_FOUND: string = 'CE_GIFT_RECEIVER_NOT_FOUND';
public static PURCHASE_APPROVED: string = 'CE_PURCHASE_APPROVED';
+ public static INIT_GIFT: string = 'CE_INIT_GIFT';
public static CATALOG_RESET: string = 'CE_RESET';
}
diff --git a/src/events/catalog/CatalogGiftReceiverNotFoundEvent.ts b/src/events/catalog/CatalogGiftReceiverNotFoundEvent.ts
new file mode 100644
index 00000000..611eaff7
--- /dev/null
+++ b/src/events/catalog/CatalogGiftReceiverNotFoundEvent.ts
@@ -0,0 +1,9 @@
+import { CatalogEvent } from './CatalogEvent';
+
+export class CatalogGiftReceiverNotFoundEvent extends CatalogEvent
+{
+ constructor()
+ {
+ super(CatalogEvent.GIFT_RECEIVER_NOT_FOUND);
+ }
+}
diff --git a/src/events/catalog/CatalogInitGiftEvent.ts b/src/events/catalog/CatalogInitGiftEvent.ts
new file mode 100644
index 00000000..fd9c9264
--- /dev/null
+++ b/src/events/catalog/CatalogInitGiftEvent.ts
@@ -0,0 +1,32 @@
+import { CatalogEvent } from './CatalogEvent';
+
+export class CatalogInitGiftEvent extends CatalogEvent
+{
+ private _pageId: number;
+ private _offerId: number;
+ private _extraData: string;
+
+ constructor(pageId: number, offerId: number, extraData: string)
+ {
+ super(CatalogEvent.INIT_GIFT);
+
+ this._pageId = pageId;
+ this._offerId = offerId;
+ this._extraData = extraData;
+ }
+
+ public get pageId(): number
+ {
+ return this._pageId;
+ }
+
+ public get offerId(): number
+ {
+ return this._offerId;
+ }
+
+ public get extraData(): string
+ {
+ return this._extraData;
+ }
+}
diff --git a/src/events/friend-list/FriendListContentEvent.ts b/src/events/friend-list/FriendListContentEvent.ts
index 4527d67c..a7623cbc 100644
--- a/src/events/friend-list/FriendListContentEvent.ts
+++ b/src/events/friend-list/FriendListContentEvent.ts
@@ -1,4 +1,4 @@
-import { MessengerFriend } from '../../views/friend-list/common/MessengerFriend';
+import { MessengerFriend } from '../../views/friends/common/MessengerFriend';
import { FriendListEvent } from './FriendListEvent';
export class FriendListContentEvent extends FriendListEvent
diff --git a/src/hooks/BatchUpdates.ts b/src/hooks/BatchUpdates.ts
new file mode 100644
index 00000000..d5f2501a
--- /dev/null
+++ b/src/hooks/BatchUpdates.ts
@@ -0,0 +1,6 @@
+import { unstable_batchedUpdates } from 'react-dom';
+
+export const BatchUpdates = (callback: () => any) =>
+{
+ return unstable_batchedUpdates(callback);
+}
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 0068322f..4a1a3914 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -1,3 +1,4 @@
+export * from './BatchUpdates';
export * from './events';
export * from './events/core';
export * from './events/nitro';
diff --git a/src/layout/Layout.scss b/src/layout/Layout.scss
index b8e28186..3b613a5f 100644
--- a/src/layout/Layout.scss
+++ b/src/layout/Layout.scss
@@ -29,3 +29,4 @@
@import './mini-camera/NitroLayoutMiniCameraView';
@import './notification-bubble/NotificationBubbleView';
@import './trophy/NitroLayoutTrophyView';
+@import './gift-card/NitroLayoutGiftCardView';
diff --git a/src/layout/card/accordion/item/NitroCardAccordionItemView.tsx b/src/layout/card/accordion/item/NitroCardAccordionItemView.tsx
index acdd4e2f..e1cb135d 100644
--- a/src/layout/card/accordion/item/NitroCardAccordionItemView.tsx
+++ b/src/layout/card/accordion/item/NitroCardAccordionItemView.tsx
@@ -1,12 +1,17 @@
-import { FC, useState } from 'react';
+import { FC, useEffect, useState } from 'react';
import { NitroCardAccordionItemViewProps } from './NitroCardAccordionItemView.types';
export const NitroCardAccordionItemView: FC = props =>
{
- const { className = '', headerClassName = '', contentClassName = '', headerText = '' } = props;
+ const { className = '', headerClassName = '', contentClassName = '', headerText = '', defaultState = false } = props;
const [ isExpanded, setIsExpanded ] = useState(false);
+ useEffect(() =>
+ {
+ setIsExpanded(defaultState);
+ }, [ defaultState ]);
+
return (
setIsExpanded((value) => !value) }>
diff --git a/src/layout/card/accordion/item/NitroCardAccordionItemView.types.ts b/src/layout/card/accordion/item/NitroCardAccordionItemView.types.ts
index c3290126..771ef503 100644
--- a/src/layout/card/accordion/item/NitroCardAccordionItemView.types.ts
+++ b/src/layout/card/accordion/item/NitroCardAccordionItemView.types.ts
@@ -4,4 +4,5 @@ export interface NitroCardAccordionItemViewProps
headerClassName?: string;
contentClassName?: string;
headerText: string;
+ defaultState?: boolean;
}
diff --git a/src/layout/gift-card/NitroLayoutGiftCardView.scss b/src/layout/gift-card/NitroLayoutGiftCardView.scss
new file mode 100644
index 00000000..a2da0c9a
--- /dev/null
+++ b/src/layout/gift-card/NitroLayoutGiftCardView.scss
@@ -0,0 +1,41 @@
+.nitro-gift-card {
+ width: 306px;
+ height: 159px;
+ background: url(../../assets/images/gift/gift_tag.png) center no-repeat;
+
+ .gift-face {
+ width: 65px;
+
+ .gift-incognito {
+ width: 37px;
+ height: 48px;
+ background: url(../../assets/images/gift/incognito.png) center no-repeat;
+ }
+
+ .gift-avatar {
+ position: relative;
+ overflow: hidden;
+ width: 40px;
+ height: 50px;
+
+ .avatar-image {
+ position: absolute;
+ left: -25px;
+ top: -20px;
+ }
+ }
+ }
+
+ .gift-message {
+ width: 100%;
+ min-width: 100%;
+ max-width: 100%;
+ height: 90px;
+ min-height: 90px;
+ max-height: 90px;
+ border: none;
+ resize: none;
+ outline: none;
+ line-height: 17px;
+ }
+}
diff --git a/src/layout/gift-card/NitroLayoutGiftCardView.tsx b/src/layout/gift-card/NitroLayoutGiftCardView.tsx
new file mode 100644
index 00000000..30a575b6
--- /dev/null
+++ b/src/layout/gift-card/NitroLayoutGiftCardView.tsx
@@ -0,0 +1,25 @@
+import { FC } from 'react';
+import { LocalizeText } from '../../api';
+import { AvatarImageView } from '../../views/shared/avatar-image/AvatarImageView';
+import { NitroLayoutGiftCardViewProps } from './NitroLayoutGiftCardView.types';
+
+export const NitroLayoutGiftCardView: FC
= props =>
+{
+ const { figure = null, userName = null, message = null, editable = false, onChange = null } = props;
+
+ return (
+
+
+ { !userName &&
}
+ { figure &&
}
+
+
+ { !editable &&
{ message }
}
+ { editable && onChange &&
}
+ { userName &&
{ LocalizeText('catalog.gift_wrapping_new.message_from', ['name'], [userName]) }
}
+
+
+ );
+};
diff --git a/src/layout/gift-card/NitroLayoutGiftCardView.types.ts b/src/layout/gift-card/NitroLayoutGiftCardView.types.ts
new file mode 100644
index 00000000..c530d65c
--- /dev/null
+++ b/src/layout/gift-card/NitroLayoutGiftCardView.types.ts
@@ -0,0 +1,8 @@
+export interface NitroLayoutGiftCardViewProps
+{
+ figure?:string;
+ userName?: string;
+ message?: string;
+ editable?: boolean;
+ onChange?: (value: string) => void;
+}
diff --git a/src/layout/gift-card/index.ts b/src/layout/gift-card/index.ts
new file mode 100644
index 00000000..73f7d035
--- /dev/null
+++ b/src/layout/gift-card/index.ts
@@ -0,0 +1,2 @@
+export * from './NitroLayoutGiftCardView';
+export * from './NitroLayoutGiftCardView.types';
diff --git a/src/layout/index.ts b/src/layout/index.ts
index 0d843596..f02a74e0 100644
--- a/src/layout/index.ts
+++ b/src/layout/index.ts
@@ -1,5 +1,6 @@
export * from './card';
export * from './draggable-window';
+export * from './gift-card';
export * from './loading-spinner';
export * from './mini-camera';
export * from './notification-bubble';
diff --git a/src/views/Styles.scss b/src/views/Styles.scss
index eecc2119..4f31d9e5 100644
--- a/src/views/Styles.scss
+++ b/src/views/Styles.scss
@@ -2,7 +2,7 @@
@import './avatar-editor/AvatarEditorView';
@import './camera/CameraWidgetView';
@import './catalog/CatalogView';
-@import './friend-list/FriendListView';
+@import './friends/FriendsView';
@import './groups/GroupView';
@import './hotel-view/HotelView';
@import './inventory/InventoryView';
diff --git a/src/views/catalog/CatalogMessageHandler.tsx b/src/views/catalog/CatalogMessageHandler.tsx
index e875ddfe..89c1e6fc 100644
--- a/src/views/catalog/CatalogMessageHandler.tsx
+++ b/src/views/catalog/CatalogMessageHandler.tsx
@@ -1,7 +1,8 @@
-import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, GiftWrappingConfigurationEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, SellablePetPalettesMessageEvent, UserSubscriptionEvent } from '@nitrots/nitro-renderer';
+import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, SellablePetPalettesMessageEvent, UserSubscriptionEvent } from '@nitrots/nitro-renderer';
import { GuildMembershipsMessageEvent } from '@nitrots/nitro-renderer/src/nitro/communication/messages/incoming/user/GuildMembershipsMessageEvent';
import { FC, useCallback } from 'react';
import { CatalogNameResultEvent, CatalogPurchaseFailureEvent } from '../../events';
+import { CatalogGiftReceiverNotFoundEvent } from '../../events/catalog/CatalogGiftReceiverNotFoundEvent';
import { CatalogPurchasedEvent } from '../../events/catalog/CatalogPurchasedEvent';
import { CatalogPurchaseSoldOutEvent } from '../../events/catalog/CatalogPurchaseSoldOutEvent';
import { dispatchUiEvent } from '../../hooks/events/ui/ui-event';
@@ -96,6 +97,11 @@ export const CatalogMessageHandler: FC = props =>
dispatchUiEvent(new CatalogNameResultEvent(parser.result, parser.validationInfo));
}, []);
+ const onGiftReceiverNotFoundEvent = useCallback(() =>
+ {
+ dispatchUiEvent(new CatalogGiftReceiverNotFoundEvent());
+ }, []);
+
const onHabboClubOffersMessageEvent = useCallback((event: HabboClubOffersMessageEvent) =>
{
const parser = event.getParser();
@@ -168,6 +174,7 @@ export const CatalogMessageHandler: FC = props =>
CreateMessageHook(GuildMembershipsMessageEvent, onGuildMembershipsMessageEvent);
CreateMessageHook(SellablePetPalettesMessageEvent, onSellablePetPalettesMessageEvent);
CreateMessageHook(ApproveNameMessageEvent, onApproveNameMessageEvent);
+ CreateMessageHook(GiftReceiverNotFoundEvent, onGiftReceiverNotFoundEvent);
CreateMessageHook(HabboClubOffersMessageEvent, onHabboClubOffersMessageEvent);
CreateMessageHook(UserSubscriptionEvent, onUserSubscriptionEvent);
CreateMessageHook(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent);
diff --git a/src/views/catalog/CatalogView.tsx b/src/views/catalog/CatalogView.tsx
index 95a2f1d9..d49b167e 100644
--- a/src/views/catalog/CatalogView.tsx
+++ b/src/views/catalog/CatalogView.tsx
@@ -10,6 +10,7 @@ import { CatalogMode, CatalogViewProps } from './CatalogView.types';
import { BuildCatalogPageTree } from './common/CatalogUtilities';
import { CatalogContextProvider } from './context/CatalogContext';
import { CatalogReducer, initialCatalog } from './reducers/CatalogReducer';
+import { CatalogPageGiftView } from './views/gift/CatalogPageGiftView';
import { ACTIVE_PAGES, CatalogNavigationView } from './views/navigation/CatalogNavigationView';
import { CatalogPageView } from './views/page/CatalogPageView';
@@ -213,6 +214,7 @@ export const CatalogView: FC = props =>
}
+
);
}
diff --git a/src/views/catalog/views/CatalogViews.scss b/src/views/catalog/views/CatalogViews.scss
index c8a97e7c..d5d8464b 100644
--- a/src/views/catalog/views/CatalogViews.scss
+++ b/src/views/catalog/views/CatalogViews.scss
@@ -2,3 +2,4 @@
@import './navigation/CatalogNavigationView';
@import './page/CatalogPageView';
@import './search/CatalogSearchView';
+@import './gift/CatalogPageGiftView';
diff --git a/src/views/catalog/views/gift/CatalogPageGiftView.scss b/src/views/catalog/views/gift/CatalogPageGiftView.scss
new file mode 100644
index 00000000..9f43a086
--- /dev/null
+++ b/src/views/catalog/views/gift/CatalogPageGiftView.scss
@@ -0,0 +1,14 @@
+.nitro-catalog-gift {
+
+ .gift-preview {
+ width: 80px;
+ height: 80px;
+ overflow: hidden;
+ }
+
+ .gift-color {
+ width: 15px;
+ height: 15px;
+ border-radius: $border-radius;
+ }
+}
diff --git a/src/views/catalog/views/gift/CatalogPageGiftView.tsx b/src/views/catalog/views/gift/CatalogPageGiftView.tsx
new file mode 100644
index 00000000..1d7a1bf1
--- /dev/null
+++ b/src/views/catalog/views/gift/CatalogPageGiftView.tsx
@@ -0,0 +1,235 @@
+import { PurchaseFromCatalogAsGiftComposer } from '@nitrots/nitro-renderer';
+import classNames from 'classnames';
+import { FC, useCallback, useEffect, useMemo, useState } from 'react';
+import { GetSessionDataManager, LocalizeText } from '../../../../api';
+import { CatalogEvent } from '../../../../events';
+import { CatalogInitGiftEvent } from '../../../../events/catalog/CatalogInitGiftEvent';
+import { SendMessageHook, useUiEvent } from '../../../../hooks';
+import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutGiftCardView } from '../../../../layout';
+import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
+import { FurniImageView } from '../../../shared/furni-image/FurniImageView';
+import { useCatalogContext } from '../../context/CatalogContext';
+
+export const CatalogPageGiftView: FC<{}> = props =>
+{
+ const { catalogState = null } = useCatalogContext();
+ const { giftConfiguration = null } = catalogState;
+
+ const [ isVisible, setIsVisible ] = useState
(false);
+ const [ pageId, setPageId ] = useState(0);
+ const [ offerId, setOfferId ] = useState(0);
+
+ const [ receiverName, setReceiverName ] = useState('');
+ const [ showMyFace, setShowMyFace ] = useState(true);
+ const [ message, setMessage ] = useState('');
+ const [ colors, setColors ] = useState<{ id: number, color: string }[]>([]);
+ const [ selectedBoxIndex, setSelectedBoxIndex ] = useState(0);
+ const [ selectedRibbonIndex, setSelectedRibbonIndex ] = useState(0);
+ const [ selectedColorId, setSelectedColorId ] = useState(0);
+ const [ maxBoxIndex, setMaxBoxIndex ] = useState(0);
+ const [ maxRibbonIndex, setMaxRibbonIndex ] = useState(0);
+
+ const [ receiverNotFound, setReceiverNotFound ] = useState(false);
+
+ useEffect(() =>
+ {
+ setReceiverNotFound(false);
+ }, [ receiverName ]);
+
+ useEffect(() =>
+ {
+ if(!giftConfiguration) return;
+
+ setMaxBoxIndex(giftConfiguration.boxTypes.length - 1);
+ setMaxRibbonIndex(giftConfiguration.ribbonTypes.length - 1);
+
+ const newColors: { id: number, color: string }[] = [];
+
+ for(const colorId of giftConfiguration.stuffTypes)
+ {
+ const giftData = GetSessionDataManager().getFloorItemData(colorId);
+
+ if(!giftData) continue;
+
+ if(giftData.colors && giftData.colors.length > 0) newColors.push({ id: colorId, color: `#${giftData.colors[0].toString(16)}` });
+ }
+
+ setSelectedColorId(newColors[0].id);
+ setColors(newColors);
+ }, [ giftConfiguration ]);
+
+ const close = useCallback(() =>
+ {
+ setIsVisible(false);
+ setPageId(0);
+ setOfferId(0);
+ setReceiverName('');
+ setShowMyFace(true);
+ setMessage('');
+ setSelectedBoxIndex(0);
+ setSelectedRibbonIndex(0);
+ setSelectedColorId(colors[0].id);
+ }, [ colors ]);
+
+ const onCatalogEvent = useCallback((event: CatalogEvent) =>
+ {
+ switch(event.type)
+ {
+ case CatalogEvent.PURCHASE_SUCCESS:
+ close();
+ return;
+ case CatalogEvent.INIT_GIFT:
+ const castedEvent = (event as CatalogInitGiftEvent);
+ close();
+
+ setPageId(castedEvent.pageId);
+ setOfferId(castedEvent.offerId);
+ setIsVisible(true);
+ return;
+ case CatalogEvent.GIFT_RECEIVER_NOT_FOUND:
+ setReceiverNotFound(true);
+ return;
+ }
+ }, [ close ]);
+
+ useUiEvent(CatalogEvent.PURCHASE_SUCCESS, onCatalogEvent);
+ useUiEvent(CatalogEvent.INIT_GIFT, onCatalogEvent);
+ useUiEvent(CatalogEvent.GIFT_RECEIVER_NOT_FOUND, onCatalogEvent);
+
+ const isBoxDefault = useMemo(() =>
+ {
+ return giftConfiguration ? giftConfiguration.defaultStuffTypes.findIndex(s => s === giftConfiguration.boxTypes[selectedBoxIndex]) > -1 : true;
+ }, [ giftConfiguration, selectedBoxIndex ]);
+
+ const boxName = useMemo(() =>
+ {
+ return isBoxDefault ? 'catalog.gift_wrapping_new.box.default' : `catalog.gift_wrapping_new.box.${selectedBoxIndex}`;
+ }, [ isBoxDefault, selectedBoxIndex ]);
+
+ const ribbonName = useMemo(() =>
+ {
+ return `catalog.gift_wrapping_new.ribbon.${selectedRibbonIndex}`;
+ }, [ selectedRibbonIndex ]);
+
+ const priceText = useMemo(() =>
+ {
+ return isBoxDefault ? 'catalog.gift_wrapping_new.freeprice' : 'catalog.gift_wrapping_new.price';
+ }, [ isBoxDefault ]);
+
+ const extraData = useMemo(() =>
+ {
+ if(!giftConfiguration) return '';
+
+ return ((giftConfiguration.boxTypes[selectedBoxIndex] * 1000) + giftConfiguration.ribbonTypes[selectedRibbonIndex]).toString();
+ }, [ giftConfiguration, selectedBoxIndex, selectedRibbonIndex ]);
+
+ const isColorable = useMemo(() =>
+ {
+ if(!giftConfiguration) return false;
+
+ const boxType = giftConfiguration.boxTypes[selectedBoxIndex];
+
+ return (boxType === 8 || (boxType >= 3 && boxType <= 6)) ? false : true;
+ }, [ giftConfiguration, selectedBoxIndex ]);
+
+ const handleAction = useCallback((action: string) =>
+ {
+ switch(action)
+ {
+ case 'prev_box':
+ setSelectedBoxIndex(value =>
+ {
+ return (value === 0 ? maxBoxIndex : value - 1);
+ });
+ return;
+ case 'next_box':
+ setSelectedBoxIndex(value =>
+ {
+ return (value === maxBoxIndex ? 0 : value + 1);
+ });
+ return;
+ case 'prev_ribbon':
+ setSelectedRibbonIndex(value =>
+ {
+ return (value === 0 ? maxRibbonIndex : value - 1);
+ });
+ return;
+ case 'next_ribbon':
+ setSelectedRibbonIndex(value =>
+ {
+ return (value === maxRibbonIndex ? 0 : value + 1);
+ });
+ return;
+ case 'buy':
+ if(!receiverName || receiverName.length === 0)
+ {
+ setReceiverNotFound(true);
+ return;
+ }
+
+ SendMessageHook(new PurchaseFromCatalogAsGiftComposer(pageId, offerId, extraData, receiverName, message, selectedColorId, selectedBoxIndex, selectedRibbonIndex, showMyFace));
+ return;
+ }
+ }, [ extraData, maxBoxIndex, maxRibbonIndex, message, offerId, pageId, receiverName, selectedBoxIndex, selectedColorId, selectedRibbonIndex, showMyFace ]);
+
+ if(!giftConfiguration || !giftConfiguration.isEnabled || !isVisible) return null;
+
+ return (
+
+
+
+
+
+
setReceiverName(e.target.value) } />
+ { receiverNotFound &&
{ LocalizeText('catalog.gift_wrapping.receiver_not_found.title') }
}
+
+
+ setMessage(value) } />
+
+
+ setShowMyFace(value => !value) } />
+
+
+
+
+ { selectedColorId && }
+
+
+
+
+
+
+
+
+
{ LocalizeText(boxName) }
+
{ LocalizeText(priceText, ['price'], [giftConfiguration.price.toString()]) }
+
+
+
+
+
+
+
+
+
{ LocalizeText(ribbonName) }
+
+
+
+
+
+
{ LocalizeText('catalog.gift_wrapping.pick_color') }
+
+ { colors.map(color =>
+ {
+ return
+ }) }
+
+
+
+
{ LocalizeText('cancel') }
+
+
+
+
+ );
+};
diff --git a/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.scss b/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.scss
index 5aee7e7f..e2684851 100644
--- a/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.scss
+++ b/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.scss
@@ -6,5 +6,11 @@
height: 80px !important;
max-height: 80px !important;
}
+
+ .hc-banner {
+ width: 68px;
+ height: 40px;
+ background: url(../../../../../../assets/images/catalog/hc_big.png) center no-repeat;
+ }
}
}
diff --git a/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx b/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx
index 04424e33..c53ac536 100644
--- a/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx
+++ b/src/views/catalog/views/page/layout/vip-buy/CatalogLayoutVipBuyView.tsx
@@ -1,22 +1,43 @@
import { ClubOfferData, GetClubOffersMessageComposer, PurchaseFromCatalogComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
-import { Button } from 'react-bootstrap';
import { LocalizeText } from '../../../../../../api';
+import { CatalogEvent } from '../../../../../../events/catalog/CatalogEvent';
+import { useUiEvent } from '../../../../../../hooks';
import { SendMessageHook } from '../../../../../../hooks/messages/message-event';
import { NitroCardGridItemView } from '../../../../../../layout/card/grid/item/NitroCardGridItemView';
import { NitroCardGridView } from '../../../../../../layout/card/grid/NitroCardGridView';
+import { LoadingSpinnerView } from '../../../../../../layout/loading-spinner/LoadingSpinnerView';
import { GetCurrencyAmount } from '../../../../../purse/common/CurrencyHelper';
import { GLOBAL_PURSE } from '../../../../../purse/PurseView';
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
import { GetCatalogPageImage } from '../../../../common/CatalogUtilities';
import { useCatalogContext } from '../../../../context/CatalogContext';
+import { CatalogPurchaseState } from '../../purchase/purchase-button/CatalogPurchaseButtonView.types';
import { CatalogLayoutVipBuyViewProps } from './CatalogLayoutVipBuyView.types';
export const CatalogLayoutVipBuyView: FC = props =>
{
const { catalogState = null } = useCatalogContext();
const { pageParser = null, clubOffers = null, subscriptionInfo = null } = catalogState;
+
const [ pendingOffer, setPendingOffer ] = useState(null);
+ const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE);
+
+ const onCatalogEvent = useCallback((event: CatalogEvent) =>
+ {
+ switch(event.type)
+ {
+ case CatalogEvent.PURCHASE_SUCCESS:
+ setPurchaseState(CatalogPurchaseState.NONE);
+ return;
+ case CatalogEvent.PURCHASE_FAILED:
+ setPurchaseState(CatalogPurchaseState.FAILED);
+ return;
+ }
+ }, []);
+
+ useUiEvent(CatalogEvent.PURCHASE_SUCCESS, onCatalogEvent);
+ useUiEvent(CatalogEvent.PURCHASE_FAILED, onCatalogEvent);
const getOfferText = useCallback((offer: ClubOfferData) =>
{
@@ -77,130 +98,105 @@ export const CatalogLayoutVipBuyView: FC = props =
{
if(!pendingOffer) return;
+ setPurchaseState(CatalogPurchaseState.PURCHASE);
SendMessageHook(new PurchaseFromCatalogComposer(pageParser.pageId, pendingOffer.offerId, null, 1));
}, [ pendingOffer, pageParser ]);
useEffect(() =>
{
- if(clubOffers === null)
- {
- SendMessageHook(new GetClubOffersMessageComposer(1));
-
- return;
- }
+ if(clubOffers === null) SendMessageHook(new GetClubOffersMessageComposer(1));
}, [ clubOffers ]);
- const getPurchaseButton = (offer: ClubOfferData) =>
+ const setOffer = useCallback((offer: ClubOfferData) =>
{
- if(!offer) return null;
+ setPurchaseState(CatalogPurchaseState.NONE);
+ setPendingOffer(offer);
+ }, []);
- if(offer.priceCredits > GetCurrencyAmount(-1))
+ const getPurchaseButton = useCallback(() =>
+ {
+ if(!pendingOffer) return null;
+
+ if(pendingOffer.priceCredits > GetCurrencyAmount(-1))
{
- return ;
+ return ;
}
- if(offer.priceActivityPoints > GetCurrencyAmount(offer.priceActivityPointsType))
+ if(pendingOffer.priceActivityPoints > GetCurrencyAmount(pendingOffer.priceActivityPointsType))
{
- return ;
+ return ;
}
- return ;
- }
-
- console.log(pendingOffer)
+ switch(purchaseState)
+ {
+ case CatalogPurchaseState.CONFIRM:
+ return ;
+ case CatalogPurchaseState.PURCHASE:
+ return ;
+ case CatalogPurchaseState.FAILED:
+ return ;
+ case CatalogPurchaseState.NONE:
+ default:
+ return ;
+ }
+ }, [ pendingOffer, purchaseState, purchaseSubscription ]);
return (
<>
-
+
{ clubOffers && (clubOffers.length > 0) && clubOffers.map((offer, index) =>
{
return (
-
- { (pendingOffer === offer) &&
- <>
-
-
-
- { getPurchaseHeader() }
-
-
{ getPurchaseValidUntil() }
-
- { (offer.priceCredits > 0) &&
-
- { offer.priceCredits }
-
-
}
- { (offer.priceActivityPoints > 0) &&
-
- { offer.priceActivityPoints }
-
-
}
-
+
setOffer(offer) }>
+
+
+
{ getOfferText(offer) }
+
+ { (offer.priceCredits > 0) &&
+
+ { offer.priceCredits }
+
+
}
+ { (offer.priceActivityPoints > 0) &&
+
+ { offer.priceActivityPoints }
+
+
}
-
- > }
- { (pendingOffer !== offer) &&
- <>
-
-
-
- { getOfferText(offer) }
-
-
- { (offer.priceCredits > 0) &&
-
- { offer.priceCredits }
-
-
}
- { (offer.priceActivityPoints > 0) &&
-
- { offer.priceActivityPoints }
-
-
}
-
-
- { getPurchaseButton(offer) }
- > }
+
);
}) }
- {/*
- { clubOffers && (clubOffers.length > 0) && clubOffers.map((offer, index) =>
- {
- return (
-
-
-
-
- { getOfferText(offer) }
-
-
- { (offer.priceCredits > 0) &&
-
- { offer.priceCredits }
-
-
}
- { (offer.priceActivityPoints > 0) &&
-
- { offer.priceActivityPoints }
-
-
}
-
-
-
- );
- }) }
-
*/}
-
+
-
+
+ { pendingOffer &&
+
+
+
{ getPurchaseHeader() }
+
{ getPurchaseValidUntil() }
+
+
+ { (pendingOffer.priceCredits > 0) &&
+
+ { pendingOffer.priceCredits }
+
+
}
+ { (pendingOffer.priceActivityPoints > 0) &&
+
+ { pendingOffer.priceActivityPoints }
+
+
}
+
+
+ { getPurchaseButton() }
+
}
>
diff --git a/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx b/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx
index 840f8ef2..794319aa 100644
--- a/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx
+++ b/src/views/catalog/views/page/purchase/CatalogPurchaseView.tsx
@@ -71,7 +71,7 @@ export const CatalogPurchaseView: FC = props =>
- { offer.giftable && }
+ { offer.giftable && }
);
diff --git a/src/views/catalog/views/page/purchase/purchase-button/CatalogPurchaseButtonView.tsx b/src/views/catalog/views/page/purchase/purchase-button/CatalogPurchaseButtonView.tsx
index a1f50704..acc9bafb 100644
--- a/src/views/catalog/views/page/purchase/purchase-button/CatalogPurchaseButtonView.tsx
+++ b/src/views/catalog/views/page/purchase/purchase-button/CatalogPurchaseButtonView.tsx
@@ -36,7 +36,6 @@ export const CatalogPurchaseButtonView: FC
= pro
const purchase = useCallback(() =>
{
- console.log(pageId, offer.offerId, extra, quantity);
SendMessageHook(new PurchaseFromCatalogComposer(pageId, offer.offerId, extra, quantity));
}, [ pageId, offer, extra, quantity ]);
diff --git a/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.tsx b/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.tsx
index 21acd90d..b55f1aba 100644
--- a/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.tsx
+++ b/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.tsx
@@ -1,12 +1,19 @@
-import { FC } from 'react';
+import { FC, useCallback } from 'react';
import { LocalizeText } from '../../../../../../api';
+import { CatalogInitGiftEvent } from '../../../../../../events/catalog/CatalogInitGiftEvent';
+import { dispatchUiEvent } from '../../../../../../hooks';
import { CatalogPurchaseGiftButtonViewProps } from './CatalogPurchaseGiftButtonView.types';
export const CatalogPurchaseGiftButtonView: FC = props =>
{
- const { className = '', offer = null, pageId = -1, extra = null, quantity = 1, isPurchaseAllowed = true, beforePurchase = null } = props;
+ const { className = '', offer = null, pageId = -1, extra = null, disabled = false } = props;
+ const initGift = useCallback(() =>
+ {
+ dispatchUiEvent(new CatalogInitGiftEvent(pageId, offer.offerId, extra));
+ }, [ extra, offer, pageId ]);
+
return (
-
+
);
}
diff --git a/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.types.ts b/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.types.ts
index 53d4daf5..e3c3a580 100644
--- a/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.types.ts
+++ b/src/views/catalog/views/page/purchase/purchase-gift-button/CatalogPurchaseGiftButtonView.types.ts
@@ -6,7 +6,5 @@ export interface CatalogPurchaseGiftButtonViewProps
offer: CatalogPageMessageOfferData;
pageId: number;
extra?: string;
- quantity?: number;
- isPurchaseAllowed?: boolean;
- beforePurchase?: () => void;
+ disabled?: boolean;
}
diff --git a/src/views/friend-list/FriendListView.scss b/src/views/friend-list/FriendListView.scss
deleted file mode 100644
index c4e98765..00000000
--- a/src/views/friend-list/FriendListView.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-.nitro-friend-list {
- width: 250px;
-}
-
-@import './views//friend-bar/FriendBarView';
diff --git a/src/views/friend-list/views/friends/FriendListFriendsView.tsx b/src/views/friend-list/views/friends/FriendListFriendsView.tsx
deleted file mode 100644
index 7779c50c..00000000
--- a/src/views/friend-list/views/friends/FriendListFriendsView.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { FC } from 'react';
-import { FriendListFriendsItemView } from '../friends-item/FriendListFriendsItemView';
-import { FriendListFriendsViewProps } from './FriendListFriendsView.types';
-
-export const FriendListFriendsView: FC = props =>
-{
- const { list = null } = props;
-
- if(!list) return null;
-
- return (<>
- { list.map((friend, index) =>
- {
- return
- }) }
- >);
-}
diff --git a/src/views/friend-list/views/friends/FriendListFriendsView.types.ts b/src/views/friend-list/views/friends/FriendListFriendsView.types.ts
deleted file mode 100644
index b9727b9c..00000000
--- a/src/views/friend-list/views/friends/FriendListFriendsView.types.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { MessengerFriend } from './../../common/MessengerFriend';
-export interface FriendListFriendsViewProps
-{
- list: MessengerFriend[];
-}
diff --git a/src/views/friend-list/views/requests-item/FriendListRequestsItemView.types.ts b/src/views/friend-list/views/requests-item/FriendListRequestsItemView.types.ts
deleted file mode 100644
index bfef7b6b..00000000
--- a/src/views/friend-list/views/requests-item/FriendListRequestsItemView.types.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { MessengerRequest } from './../../common/MessengerRequest';
-
-export interface FriendListRequestsItemViewProps
-{
- request: MessengerRequest;
-}
diff --git a/src/views/friend-list/views/requests/FriendListRequestsView.tsx b/src/views/friend-list/views/requests/FriendListRequestsView.tsx
deleted file mode 100644
index 9041f49c..00000000
--- a/src/views/friend-list/views/requests/FriendListRequestsView.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { FC } from 'react';
-import { FriendListRequestsItemView } from '../requests-item/FriendListRequestsItemView';
-import { FriendListRequestsViewProps } from './FriendListRequestsView.types';
-
-export const FriendListRequestsView: FC = props =>
-{
- const { list = null } = props;
-
- if(!list) return null;
-
- return (<>
- { list.map((request, index) =>
- {
- return
- }) }
- >);
-};
diff --git a/src/views/friend-list/views/requests/FriendListRequestsView.types.ts b/src/views/friend-list/views/requests/FriendListRequestsView.types.ts
deleted file mode 100644
index 4c968d8e..00000000
--- a/src/views/friend-list/views/requests/FriendListRequestsView.types.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { MessengerRequest } from './../../common/MessengerRequest';
-
-export interface FriendListRequestsViewProps
-{
- list: MessengerRequest[];
-}
diff --git a/src/views/friend-list/FriendListMessageHandler.tsx b/src/views/friends/FriendListMessageHandler.tsx
similarity index 100%
rename from src/views/friend-list/FriendListMessageHandler.tsx
rename to src/views/friends/FriendListMessageHandler.tsx
diff --git a/src/views/friend-list/FriendListMessageHandler.types.ts b/src/views/friends/FriendListMessageHandler.types.ts
similarity index 100%
rename from src/views/friend-list/FriendListMessageHandler.types.ts
rename to src/views/friends/FriendListMessageHandler.types.ts
diff --git a/src/views/friends/FriendsView.scss b/src/views/friends/FriendsView.scss
new file mode 100644
index 00000000..1d882087
--- /dev/null
+++ b/src/views/friends/FriendsView.scss
@@ -0,0 +1,5 @@
+.nitro-friend-list {
+ width: 250px;
+}
+
+@import './views/friend-bar/FriendBarView';
diff --git a/src/views/friend-list/FriendListView.tsx b/src/views/friends/FriendsView.tsx
similarity index 91%
rename from src/views/friend-list/FriendListView.tsx
rename to src/views/friends/FriendsView.tsx
index 06ebf3b4..6e2d74eb 100644
--- a/src/views/friend-list/FriendListView.tsx
+++ b/src/views/friends/FriendsView.tsx
@@ -11,15 +11,13 @@ import { SendMessageHook } from '../../hooks/messages/message-event';
import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout';
import { FriendListContextProvider } from './context/FriendListContext';
import { FriendListMessageHandler } from './FriendListMessageHandler';
-import { FriendListViewProps } from './FriendListView.types';
import { FriendListReducer, initialFriendList } from './reducers/FriendListReducer';
import { FriendBarView } from './views/friend-bar/FriendBarView';
-import { FriendListFriendsView } from './views/friends/FriendListFriendsView';
-import { FriendListRequestsView } from './views/requests/FriendListRequestsView';
+import { FriendsListView } from './views/list/FriendsListView';
const TABS: string[] = ['friendlist.friends', 'generic.search'];
-export const FriendListView: FC = props =>
+export const FriendsView: FC<{}> = props =>
{
const [ friendListState, dispatchFriendListState ] = useReducer(FriendListReducer, initialFriendList);
const { friends = null, requests = null, settings = null } = friendListState;
@@ -120,14 +118,14 @@ export const FriendListView: FC = props =>
{ currentTab === 0 &&
-
-
+
+
-
+
{ requests.length > 0 &&
-
+
}
}
diff --git a/src/views/friend-list/FriendListView.types.ts b/src/views/friends/FriendsView.types.ts
similarity index 85%
rename from src/views/friend-list/FriendListView.types.ts
rename to src/views/friends/FriendsView.types.ts
index 9c7675de..14fa8b5c 100644
--- a/src/views/friend-list/FriendListView.types.ts
+++ b/src/views/friends/FriendsView.types.ts
@@ -1,6 +1,3 @@
-export interface FriendListViewProps
-{}
-
export class FriendListTabs
{
public static readonly FRIENDS: string = 'friendlist.friends';
diff --git a/src/views/friend-list/common/MessengerFriend.ts b/src/views/friends/common/MessengerFriend.ts
similarity index 100%
rename from src/views/friend-list/common/MessengerFriend.ts
rename to src/views/friends/common/MessengerFriend.ts
diff --git a/src/views/friend-list/common/MessengerRequest.ts b/src/views/friends/common/MessengerRequest.ts
similarity index 100%
rename from src/views/friend-list/common/MessengerRequest.ts
rename to src/views/friends/common/MessengerRequest.ts
diff --git a/src/views/friend-list/common/MessengerSettings.ts b/src/views/friends/common/MessengerSettings.ts
similarity index 100%
rename from src/views/friend-list/common/MessengerSettings.ts
rename to src/views/friends/common/MessengerSettings.ts
diff --git a/src/views/friend-list/context/FriendListContext.tsx b/src/views/friends/context/FriendListContext.tsx
similarity index 100%
rename from src/views/friend-list/context/FriendListContext.tsx
rename to src/views/friends/context/FriendListContext.tsx
diff --git a/src/views/friend-list/context/FriendListContext.type.ts b/src/views/friends/context/FriendListContext.type.ts
similarity index 100%
rename from src/views/friend-list/context/FriendListContext.type.ts
rename to src/views/friends/context/FriendListContext.type.ts
diff --git a/src/views/friend-list/reducers/FriendListReducer.tsx b/src/views/friends/reducers/FriendListReducer.tsx
similarity index 100%
rename from src/views/friend-list/reducers/FriendListReducer.tsx
rename to src/views/friends/reducers/FriendListReducer.tsx
diff --git a/src/views/friend-list/views/friend-bar-item/FriendBarItemView.scss b/src/views/friends/views/friend-bar-item/FriendBarItemView.scss
similarity index 100%
rename from src/views/friend-list/views/friend-bar-item/FriendBarItemView.scss
rename to src/views/friends/views/friend-bar-item/FriendBarItemView.scss
diff --git a/src/views/friend-list/views/friend-bar-item/FriendBarItemView.tsx b/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx
similarity index 100%
rename from src/views/friend-list/views/friend-bar-item/FriendBarItemView.tsx
rename to src/views/friends/views/friend-bar-item/FriendBarItemView.tsx
diff --git a/src/views/friend-list/views/friend-bar-item/FriendBarItemView.types.ts b/src/views/friends/views/friend-bar-item/FriendBarItemView.types.ts
similarity index 100%
rename from src/views/friend-list/views/friend-bar-item/FriendBarItemView.types.ts
rename to src/views/friends/views/friend-bar-item/FriendBarItemView.types.ts
diff --git a/src/views/friend-list/views/friend-bar/FriendBarView.scss b/src/views/friends/views/friend-bar/FriendBarView.scss
similarity index 100%
rename from src/views/friend-list/views/friend-bar/FriendBarView.scss
rename to src/views/friends/views/friend-bar/FriendBarView.scss
diff --git a/src/views/friend-list/views/friend-bar/FriendBarView.tsx b/src/views/friends/views/friend-bar/FriendBarView.tsx
similarity index 100%
rename from src/views/friend-list/views/friend-bar/FriendBarView.tsx
rename to src/views/friends/views/friend-bar/FriendBarView.tsx
diff --git a/src/views/friend-list/views/friend-bar/FriendBarView.types.ts b/src/views/friends/views/friend-bar/FriendBarView.types.ts
similarity index 100%
rename from src/views/friend-list/views/friend-bar/FriendBarView.types.ts
rename to src/views/friends/views/friend-bar/FriendBarView.types.ts
diff --git a/src/views/friend-list/views/friends-item/FriendListFriendsItemView.tsx b/src/views/friends/views/friend-item/FriendsListItemView.tsx
similarity index 94%
rename from src/views/friend-list/views/friends-item/FriendListFriendsItemView.tsx
rename to src/views/friends/views/friend-item/FriendsListItemView.tsx
index eee90ced..bac0415d 100644
--- a/src/views/friend-list/views/friends-item/FriendListFriendsItemView.tsx
+++ b/src/views/friends/views/friend-item/FriendsListItemView.tsx
@@ -4,9 +4,9 @@ import { LocalizeText } from '../../../../api';
import { SendMessageHook } from '../../../../hooks';
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
import { MessengerFriend } from '../../common/MessengerFriend';
-import { FriendListFriendsItemViewProps } from './FriendListFriendsItemView.types';
+import { FriendsListItemViewProps } from './FriendsListItemView.types';
-export const FriendListFriendsItemView: FC = props =>
+export const FriendsListItemView: FC = props =>
{
const { friend = null } = props;
diff --git a/src/views/friend-list/views/friends-item/FriendListFriendsItemView.types.ts b/src/views/friends/views/friend-item/FriendsListItemView.types.ts
similarity index 67%
rename from src/views/friend-list/views/friends-item/FriendListFriendsItemView.types.ts
rename to src/views/friends/views/friend-item/FriendsListItemView.types.ts
index a64cbd3b..df44d3b5 100644
--- a/src/views/friend-list/views/friends-item/FriendListFriendsItemView.types.ts
+++ b/src/views/friends/views/friend-item/FriendsListItemView.types.ts
@@ -1,6 +1,6 @@
import { MessengerFriend } from '../../common/MessengerFriend';
-export interface FriendListFriendsItemViewProps
+export interface FriendsListItemViewProps
{
friend: MessengerFriend;
}
diff --git a/src/views/friends/views/list/FriendsListView.tsx b/src/views/friends/views/list/FriendsListView.tsx
new file mode 100644
index 00000000..86ed2707
--- /dev/null
+++ b/src/views/friends/views/list/FriendsListView.tsx
@@ -0,0 +1,25 @@
+import React, { FC } from 'react';
+import { MessengerFriend } from '../../common/MessengerFriend';
+import { MessengerRequest } from '../../common/MessengerRequest';
+import { FriendsListItemView } from '../friend-item/FriendsListItemView';
+import { FriendsRequestItemView } from '../request-item/FriendsRequestItemView';
+import { FriendsListViewProps } from './FriendsListView.types';
+
+export const FriendsListView: FC = props =>
+{
+ const { list = null } = props;
+
+ if(!list) return null;
+
+ return (<>
+ { list.map((item, index) =>
+ {
+ if(item instanceof MessengerFriend)
+ return
+ else if(item instanceof MessengerRequest)
+ return
+ else
+ return null;
+ }) }
+ >);
+}
diff --git a/src/views/friends/views/list/FriendsListView.types.ts b/src/views/friends/views/list/FriendsListView.types.ts
new file mode 100644
index 00000000..8a4c4bc9
--- /dev/null
+++ b/src/views/friends/views/list/FriendsListView.types.ts
@@ -0,0 +1,7 @@
+import { MessengerFriend } from '../../common/MessengerFriend';
+import { MessengerRequest } from '../../common/MessengerRequest';
+
+export interface FriendsListViewProps
+{
+ list: MessengerFriend[] | MessengerRequest[];
+}
diff --git a/src/views/friend-list/views/requests-item/FriendListRequestsItemView.tsx b/src/views/friends/views/request-item/FriendsRequestItemView.tsx
similarity index 87%
rename from src/views/friend-list/views/requests-item/FriendListRequestsItemView.tsx
rename to src/views/friends/views/request-item/FriendsRequestItemView.tsx
index a0f57c5c..f25c42f9 100644
--- a/src/views/friend-list/views/requests-item/FriendListRequestsItemView.tsx
+++ b/src/views/friends/views/request-item/FriendsRequestItemView.tsx
@@ -2,9 +2,9 @@ import { AcceptFriendMessageComposer, DeclineFriendMessageComposer } from '@nitr
import { FC, useCallback } from 'react';
import { SendMessageHook } from '../../../../hooks/messages/message-event';
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
-import { FriendListRequestsItemViewProps } from './FriendListRequestsItemView.types';
+import { FriendsRequestItemViewProps } from './FriendsRequestItemView.types';
-export const FriendListRequestsItemView: FC = props =>
+export const FriendsRequestItemView: FC = props =>
{
const { request = null } = props;
diff --git a/src/views/friends/views/request-item/FriendsRequestItemView.types.ts b/src/views/friends/views/request-item/FriendsRequestItemView.types.ts
new file mode 100644
index 00000000..4f5c38d5
--- /dev/null
+++ b/src/views/friends/views/request-item/FriendsRequestItemView.types.ts
@@ -0,0 +1,6 @@
+import { MessengerRequest } from '../../common/MessengerRequest';
+
+export interface FriendsRequestItemViewProps
+{
+ request: MessengerRequest;
+}
diff --git a/src/views/groups/views/members/GroupMembersView.tsx b/src/views/groups/views/members/GroupMembersView.tsx
index cbf08364..0ab607e9 100644
--- a/src/views/groups/views/members/GroupMembersView.tsx
+++ b/src/views/groups/views/members/GroupMembersView.tsx
@@ -115,7 +115,7 @@ export const GroupMembersView: FC = props =>
}
searchMembers(pageData.pageIndex);
- }, [ pageData ]);
+ }, [ pageData, searchMembers ]);
const acceptMembership = useCallback((member) =>
{
@@ -124,7 +124,7 @@ export const GroupMembersView: FC = props =>
SendMessageHook(new GroupMembershipAcceptComposer(pageData.groupId, member.id));
searchMembers(pageData.pageIndex);
}
- }, [ pageData ]);
+ }, [ pageData, searchMembers ]);
const removeMemberOrDeclineMembership = useCallback((member) =>
{
@@ -138,66 +138,68 @@ export const GroupMembersView: FC = props =>
setRemovingMemberName(member.name);
SendMessageHook(new GroupConfirmRemoveMemberComposer(pageData.groupId, member.id));
}
- }, [ pageData ]);
+ }, [ pageData, searchMembers ]);
- if(!pageData) return null;
+ if(!groupId) return null;
return (
-
-
-
-
-
+
+ { pageData && <>
+
+
+
+
+
+
+ setSearchQuery(e.target.value) } onBlur={ () => searchMembers(pageData.pageIndex) } onKeyDown={ onKeyDown } />
+
+
-
- setSearchQuery(e.target.value) } onBlur={ () => searchMembers(pageData.pageIndex) } onKeyDown={ onKeyDown } />
-
-
-
-
- { pageData.result.map((member, index) =>
- {
- return (
-
-
-
{ GetUserProfile(member.id) } }>
-
-
-
-
{ GetUserProfile(member.id) } }>{ member.name }
- { member.rank !== GroupRank.REQUESTED &&
{ LocalizeText('group.members.since', ['date'], [member.joinedAt]) }
}
-
-
-
-
toggleAdmin(member) } />
+
+ { pageData.result.map((member, index) =>
+ {
+ return (
+
+
+
{ GetUserProfile(member.id) } }>
+
+
+
+
{ GetUserProfile(member.id) } }>{ member.name }
+ { member.rank !== GroupRank.REQUESTED &&
{ LocalizeText('group.members.since', ['date'], [member.joinedAt]) }
}
+
+
+
+ toggleAdmin(member) } />
+
+ { member.rank === GroupRank.REQUESTED &&
+ acceptMembership(member) } />
+
}
+ { member.rank !== GroupRank.OWNER && pageData.admin && member.id !== GetSessionDataManager().userId &&
+ removeMemberOrDeclineMembership(member) } />
+
}
- { member.rank === GroupRank.REQUESTED &&
- acceptMembership(member) } />
-
}
- { member.rank !== GroupRank.OWNER && pageData.admin && member.id !== GetSessionDataManager().userId &&
- removeMemberOrDeclineMembership(member) } />
-
}
-
- );
- }) }
-
-
-
-
+ );
+ }) }
-
{ LocalizeText('group.members.pageinfo', ['amount', 'page', 'totalPages'], [pageData.totalMembersCount.toString(), (pageData.pageIndex + 1).toString(), totalPages.toString()]) }
-
-
+
+
+
+
+
{ LocalizeText('group.members.pageinfo', ['amount', 'page', 'totalPages'], [pageData.totalMembersCount.toString(), (pageData.pageIndex + 1).toString(), totalPages.toString()]) }
+
+
+
-
-
+
+ > }
);
};
diff --git a/src/views/groups/views/room-information/GroupRoomInformationView.tsx b/src/views/groups/views/room-information/GroupRoomInformationView.tsx
index 8a66491d..af2f73ee 100644
--- a/src/views/groups/views/room-information/GroupRoomInformationView.tsx
+++ b/src/views/groups/views/room-information/GroupRoomInformationView.tsx
@@ -12,13 +12,13 @@ export const GroupRoomInformationView: FC<{}> = props =>
const [ groupId, setGroupId ] = useState
(null);
const [ groupInformation, setGroupInformation ] = useState(null);
const [ isExpended, setIsExpended ] = useState(true);
-
+
const onRoomInfoEvent = useCallback((event: RoomInfoEvent) =>
{
const parser = event.getParser();
setGroupInformation(null);
-
+
if(parser.data.habboGroupId)
{
setGroupId(parser.data.habboGroupId);
@@ -33,7 +33,7 @@ export const GroupRoomInformationView: FC<{}> = props =>
const parser = event.getParser();
if(parser.flag || groupId !== parser.id) return;
-
+ console.log(parser);
setGroupInformation(null);
setGroupInformation(parser);
}, [ groupId ]);
@@ -110,7 +110,7 @@ export const GroupRoomInformationView: FC<{}> = props =>
{ isExpended && <>
-
GetGroupInformation(groupInformation.id) }>
+
GetGroupInformation(groupId) }>
diff --git a/src/views/main/MainView.tsx b/src/views/main/MainView.tsx
index a28b8f5b..68269e58 100644
--- a/src/views/main/MainView.tsx
+++ b/src/views/main/MainView.tsx
@@ -2,11 +2,12 @@ import { RoomSessionEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { GetCommunication } from '../../api';
import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event';
+import { TransitionAnimation, TransitionAnimationTypes } from '../../layout';
import { AchievementsView } from '../achievements/AchievementsView';
import { AvatarEditorView } from '../avatar-editor/AvatarEditorView';
import { CameraWidgetView } from '../camera/CameraWidgetView';
import { CatalogView } from '../catalog/CatalogView';
-import { FriendListView } from '../friend-list/FriendListView';
+import { FriendsView } from '../friends/FriendsView';
import { GroupsView } from '../groups/GroupsView';
import { HotelView } from '../hotel-view/HotelView';
import { InventoryView } from '../inventory/InventoryView';
@@ -50,7 +51,9 @@ export const MainView: FC
= props =>
return (
- { landingViewVisible &&
}
+
+
+
@@ -60,7 +63,7 @@ export const MainView: FC
= props =>
-
+
diff --git a/src/views/room-host/RoomHostView.tsx b/src/views/room-host/RoomHostView.tsx
index 14211d80..5e1d15f6 100644
--- a/src/views/room-host/RoomHostView.tsx
+++ b/src/views/room-host/RoomHostView.tsx
@@ -3,6 +3,7 @@ import { FC, useCallback, useState } from 'react';
import { GetRoomSession, SetActiveRoomId, StartRoomSession } from '../../api';
import { useRoomEngineEvent } from '../../hooks/events/nitro/room/room-engine-event';
import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event';
+import { TransitionAnimation, TransitionAnimationTypes } from '../../layout';
import { RoomView } from '../room/RoomView';
export const RoomHostView: FC<{}> = props =>
@@ -49,8 +50,10 @@ export const RoomHostView: FC<{}> = props =>
useRoomSessionManagerEvent(RoomSessionEvent.ENDED, onRoomSessionEvent);
return (
-
-
-
+
+
+
+
+
);
}
diff --git a/src/views/room/RoomColorView.tsx b/src/views/room/RoomColorView.tsx
index b3201b7c..107ab6fe 100644
--- a/src/views/room/RoomColorView.tsx
+++ b/src/views/room/RoomColorView.tsx
@@ -1,4 +1,4 @@
-import { ColorConverter, NitroAdjustmentFilter, NitroContainer, NitroSprite, NitroTexture, RoomBackgroundColorEvent, RoomEngineEvent, RoomId, RoomObjectHSLColorEnabledEvent } from '@nitrots/nitro-renderer';
+import { ColorConverter, NitroAdjustmentFilter, NitroContainer, NitroSprite, NitroTexture, RoomBackgroundColorEvent, RoomEngineDimmerStateEvent, RoomEngineEvent, RoomId, RoomObjectHSLColorEnabledEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { GetNitroInstance, GetRoomEngine, RoomWidgetUpdateBackgroundColorPreviewEvent, RoomWidgetUpdateRoomViewEvent } from '../../api';
import { UseMountEffect } from '../../hooks';
@@ -11,8 +11,7 @@ export const RoomColorView: FC<{}> = props =>
const [ roomBackgroundColor, setRoomBackgroundColor ] = useState(0);
const [ originalRoomBackgroundColor, setOriginalRoomBackgroundColor ] = useState(0);
const [ roomFilter, setRoomFilter ] = useState(null);
- const [ roomFilterColor, setRoomFilterColor ] = useState(-1);
- const { roomSession = null, canvasId = -1, eventDispatcher = null } = useRoomContext();
+ const { roomSession = null, canvasId = -1, widgetHandler = null, eventDispatcher = null } = useRoomContext();
const getRenderingCanvas = useCallback(() =>
{
@@ -113,7 +112,6 @@ export const RoomColorView: FC<{}> = props =>
{
const newColor = ColorConverter.hslToRGB(((ColorConverter.rgbToHSL(color) & 0xFFFF00) + brightness));
- setRoomFilterColor(newColor);
updateRoomFilter(newColor);
}, [ updateRoomFilter ]);
@@ -139,11 +137,15 @@ export const RoomColorView: FC<{}> = props =>
return;
}
+ case RoomEngineDimmerStateEvent.ROOM_COLOR: {
+ widgetHandler.processEvent(event);
+ }
}
- }, [ updateRoomBackgroundColor, updateRoomFilterColor ]);
+ }, [ widgetHandler, updateRoomBackgroundColor, updateRoomFilterColor ]);
useRoomEngineEvent(RoomObjectHSLColorEnabledEvent.ROOM_BACKGROUND_COLOR, onRoomEngineEvent);
useRoomEngineEvent(RoomBackgroundColorEvent.ROOM_COLOR, onRoomEngineEvent);
+ useRoomEngineEvent(RoomEngineDimmerStateEvent.ROOM_COLOR, onRoomEngineEvent);
const onRoomWidgetUpdateRoomViewEvent = useCallback((event: RoomWidgetUpdateRoomViewEvent) =>
{
diff --git a/src/views/room/RoomView.tsx b/src/views/room/RoomView.tsx
index 882d7a76..89b96ef0 100644
--- a/src/views/room/RoomView.tsx
+++ b/src/views/room/RoomView.tsx
@@ -1,6 +1,6 @@
import { EventDispatcher, NitroRectangle, RoomGeometry, RoomVariableEnum, Vector3d } from '@nitrots/nitro-renderer';
import { FC, useEffect, useRef, useState } from 'react';
-import { DispatchMouseEvent, DispatchTouchEvent, DoorbellWidgetHandler, FurniChooserWidgetHandler, FurnitureContextMenuWidgetHandler, FurnitureCustomStackHeightWidgetHandler, FurnitureExternalImageWidgetHandler, GetNitroInstance, GetRoomEngine, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, RoomWidgetRoomToolsHandler, RoomWidgetUpdateRoomViewEvent, UserChooserWidgetHandler } from '../../api';
+import { DispatchMouseEvent, DispatchTouchEvent, DoorbellWidgetHandler, FurniChooserWidgetHandler, FurnitureContextMenuWidgetHandler, FurnitureCreditWidgetHandler, FurnitureCustomStackHeightWidgetHandler, FurnitureDimmerWidgetHandler, FurnitureExternalImageWidgetHandler, FurniturePresentWidgetHandler, GetNitroInstance, GetRoomEngine, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, RoomWidgetRoomToolsHandler, RoomWidgetUpdateRoomViewEvent, UserChooserWidgetHandler } from '../../api';
import { RoomContextProvider } from './context/RoomContext';
import { RoomColorView } from './RoomColorView';
import { RoomViewProps } from './RoomView.types';
@@ -34,13 +34,17 @@ export const RoomView: FC = props =>
widgetHandlerManager.registerHandler(new RoomWidgetRoomToolsHandler());
widgetHandlerManager.registerHandler(new RoomWidgetChatInputHandler());
widgetHandlerManager.registerHandler(new RoomWidgetChatHandler());
- widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
- widgetHandlerManager.registerHandler(new FurnitureCustomStackHeightWidgetHandler());
- widgetHandlerManager.registerHandler(new FurnitureExternalImageWidgetHandler());
- widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler());
widgetHandlerManager.registerHandler(new UserChooserWidgetHandler());
widgetHandlerManager.registerHandler(new DoorbellWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurnitureCreditWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurnitureCustomStackHeightWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurnitureExternalImageWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurniturePresentWidgetHandler());
+ widgetHandlerManager.registerHandler(new FurnitureDimmerWidgetHandler());
+
setWidgetHandler(widgetHandlerManager);
GetNitroInstance().renderer.resize(window.innerWidth, window.innerHeight);
diff --git a/src/views/room/widgets/RoomWidgetsView.tsx b/src/views/room/widgets/RoomWidgetsView.tsx
index b1f3b102..c2c8922d 100644
--- a/src/views/room/widgets/RoomWidgetsView.tsx
+++ b/src/views/room/widgets/RoomWidgetsView.tsx
@@ -1,6 +1,6 @@
-import { RoomEngineDimmerStateEvent, RoomEngineEvent, RoomEngineObjectEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomId, RoomObjectCategory, RoomObjectOperationType, RoomSessionChatEvent, RoomSessionDanceEvent, RoomSessionDimmerPresetsEvent, RoomSessionDoorbellEvent, RoomSessionErrorMessageEvent, RoomSessionEvent, RoomSessionFriendRequestEvent, RoomSessionPetInfoUpdateEvent, RoomSessionPresentEvent, RoomSessionUserBadgesEvent, RoomZoomEvent } from '@nitrots/nitro-renderer';
+import { RoomEngineEvent, RoomEngineObjectEvent, RoomEngineRoomAdEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomId, RoomObjectCategory, RoomObjectOperationType, RoomObjectVariable, RoomSessionChatEvent, RoomSessionDanceEvent, RoomSessionDimmerPresetsEvent, RoomSessionDoorbellEvent, RoomSessionErrorMessageEvent, RoomSessionEvent, RoomSessionFriendRequestEvent, RoomSessionPetInfoUpdateEvent, RoomSessionPresentEvent, RoomSessionUserBadgesEvent, RoomZoomEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
-import { CanManipulateFurniture, GetRoomEngine, IsFurnitureSelectionDisabled, LocalizeText, ProcessRoomObjectOperation, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent } from '../../../api';
+import { CanManipulateFurniture, GetRoomEngine, GetSessionDataManager, IsFurnitureSelectionDisabled, LocalizeText, ProcessRoomObjectOperation, RoomWidgetFurniToWidgetMessage, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent } from '../../../api';
import { useRoomEngineEvent, useRoomSessionManagerEvent } from '../../../hooks/events';
import { useRoomContext } from '../context/RoomContext';
import { AvatarInfoWidgetView } from './avatar-info/AvatarInfoWidgetView';
@@ -41,16 +41,22 @@ export const RoomWidgetsView: FC = props =>
return;
}
- case RoomEngineDimmerStateEvent.ROOM_COLOR: {
- return;
- }
}
}, [ eventDispatcher ]);
useRoomEngineEvent(RoomEngineEvent.NORMAL_MODE, onRoomEngineEvent);
useRoomEngineEvent(RoomEngineEvent.GAME_MODE, onRoomEngineEvent);
useRoomEngineEvent(RoomZoomEvent.ROOM_ZOOM, onRoomEngineEvent);
- useRoomEngineEvent(RoomEngineDimmerStateEvent.ROOM_COLOR, onRoomEngineEvent);
+
+ const handleRoomAdClick = useCallback((event: RoomEngineRoomAdEvent) =>
+ {
+
+ }, []);
+
+ const handleRoomAdTooltip = useCallback((event: RoomEngineRoomAdEvent) =>
+ {
+
+ }, []);
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) =>
{
@@ -118,12 +124,76 @@ export const RoomWidgetsView: FC = props =>
case RoomEngineObjectEvent.MOUSE_LEAVE:
updateEvent = new RoomWidgetRoomObjectUpdateEvent(RoomWidgetRoomObjectUpdateEvent.OBJECT_ROLL_OUT, objectId, category, event.roomId);
break;
- case RoomEngineUseProductEvent.USE_PRODUCT_FROM_INVENTORY:
- case RoomEngineUseProductEvent.USE_PRODUCT_FROM_ROOM:
+ case RoomEngineTriggerWidgetEvent.REQUEST_CREDITFURNI:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_CREDITFURNI, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_STICKIE:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_STICKIE, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_PRESENT:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_PRESENT, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_TROPHY:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_TROPHY, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_TEASER:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_TEASER, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_ECOTRONBOX:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_ECOTRONBOX, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_DIMMER:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_DIMMER, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_PLACEHOLDER:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_PLACEHOLDER, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_CLOTHING_CHANGE:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_CLOTHING_CHANGE, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_PLAYLIST_EDITOR:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_PLAYLIST_EDITOR, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_ACHIEVEMENT_RESOLUTION_ENGRAVING:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_ACHIEVEMENT_RESOLUTION_ENGRAVING, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_BADGE_DISPLAY_ENGRAVING:
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_BADGE_DISPLAY_ENGRAVING, objectId, category, event.roomId));
+ break;
+ case RoomEngineTriggerWidgetEvent.REQUEST_ACHIEVEMENT_RESOLUTION_FAILED: {
+ const roomObject = GetRoomEngine().getRoomObject(event.roomId, objectId, category);
+ const ownerId = roomObject.model.getValue(RoomObjectVariable.FURNITURE_OWNER_ID);
+
+ if(ownerId === GetSessionDataManager().userId)
+ {
+ widgetHandler.processWidgetMessage(new RoomWidgetFurniToWidgetMessage(RoomWidgetFurniToWidgetMessage.REQUEST_ACHIEVEMENT_RESOLUTION_FAILED, objectId, category, event.roomId));
+ }
+ break;
+ }
case RoomEngineTriggerWidgetEvent.OPEN_WIDGET:
case RoomEngineTriggerWidgetEvent.CLOSE_WIDGET:
+ case RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU:
+ case RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU:
+ case RoomEngineTriggerWidgetEvent.REMOVE_DIMMER:
+ case RoomEngineTriggerWidgetEvent.REQUEST_MANNEQUIN:
+ case RoomEngineUseProductEvent.USE_PRODUCT_FROM_INVENTORY:
+ case RoomEngineUseProductEvent.USE_PRODUCT_FROM_ROOM:
+ case RoomEngineTriggerWidgetEvent.REQUEST_BACKGROUND_COLOR:
+ case RoomEngineTriggerWidgetEvent.REQUEST_FRIEND_FURNITURE_ENGRAVING:
+ case RoomEngineTriggerWidgetEvent.REQUEST_HIGH_SCORE_DISPLAY:
+ case RoomEngineTriggerWidgetEvent.REQUEST_HIDE_HIGH_SCORE_DISPLAY:
+ case RoomEngineTriggerWidgetEvent.REQUEST_INTERNAL_LINK:
+ case RoomEngineTriggerWidgetEvent.REQUEST_ROOM_LINK:
widgetHandler.processEvent(event);
break;
+ case RoomEngineRoomAdEvent.FURNI_CLICK:
+ case RoomEngineRoomAdEvent.FURNI_DOUBLE_CLICK:
+ handleRoomAdClick(event);
+ break;
+ case RoomEngineRoomAdEvent.TOOLTIP_SHOW:
+ case RoomEngineRoomAdEvent.TOOLTIP_HIDE:
+ handleRoomAdTooltip(event);
+ break;
}
if(updateEvent)
@@ -134,7 +204,7 @@ export const RoomWidgetsView: FC = props =>
if(dispatchEvent) widgetHandler.eventDispatcher.dispatchEvent(updateEvent);
}
- }, [ roomSession, widgetHandler ]);
+ }, [ roomSession, widgetHandler, handleRoomAdClick, handleRoomAdTooltip ]);
useRoomEngineEvent(RoomEngineObjectEvent.SELECTED, onRoomEngineObjectEvent);
useRoomEngineEvent(RoomEngineObjectEvent.DESELECTED, onRoomEngineObjectEvent);
@@ -146,10 +216,37 @@ export const RoomWidgetsView: FC = props =>
useRoomEngineEvent(RoomEngineObjectEvent.REQUEST_MANIPULATION, onRoomEngineObjectEvent);
useRoomEngineEvent(RoomEngineObjectEvent.MOUSE_ENTER, onRoomEngineObjectEvent);
useRoomEngineEvent(RoomEngineObjectEvent.MOUSE_LEAVE, onRoomEngineObjectEvent);
- useRoomEngineEvent(RoomEngineUseProductEvent.USE_PRODUCT_FROM_INVENTORY, onRoomEngineObjectEvent);
- useRoomEngineEvent(RoomEngineUseProductEvent.USE_PRODUCT_FROM_ROOM, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_CREDITFURNI, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_STICKIE, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PRESENT, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_TROPHY, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_TEASER, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_ECOTRONBOX, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_DIMMER, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PLACEHOLDER, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_CLOTHING_CHANGE, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PLAYLIST_EDITOR, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_ACHIEVEMENT_RESOLUTION_ENGRAVING, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_BADGE_DISPLAY_ENGRAVING, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_ACHIEVEMENT_RESOLUTION_FAILED, onRoomEngineObjectEvent);
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.OPEN_WIDGET, onRoomEngineObjectEvent);
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.CLOSE_WIDGET, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REMOVE_DIMMER, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_MANNEQUIN, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineUseProductEvent.USE_PRODUCT_FROM_INVENTORY, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineUseProductEvent.USE_PRODUCT_FROM_ROOM, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_BACKGROUND_COLOR, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_FRIEND_FURNITURE_ENGRAVING, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_HIGH_SCORE_DISPLAY, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_HIDE_HIGH_SCORE_DISPLAY, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_INTERNAL_LINK, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_ROOM_LINK, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineRoomAdEvent.FURNI_CLICK, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineRoomAdEvent.FURNI_DOUBLE_CLICK, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineRoomAdEvent.TOOLTIP_SHOW, onRoomEngineObjectEvent);
+ useRoomEngineEvent(RoomEngineRoomAdEvent.TOOLTIP_HIDE, onRoomEngineObjectEvent);
const onRoomSessionEvent = useCallback((event: RoomSessionEvent) =>
{
diff --git a/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx b/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx
index 47b29509..d949cfaa 100644
--- a/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx
+++ b/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx
@@ -24,7 +24,7 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
const [ infoStandEvent, setInfoStandEvent ] = useState(null);
const [ isGameMode, setGameMode ] = useState(false);
const [ isDancing, setIsDancing ] = useState(false);
- const [ isDecorating, setIsDecorating ] = useState(GetRoomSession().isDecorating);
+ const [ isDecorating, setIsDecorating ] = useState(false);
const [ rentableBotChatEvent, setRentableBotChatEvent ] = useState(null);
const removeNameBubble = useCallback((index: number) =>
diff --git a/src/views/room/widgets/furniture/FurnitureWidgets.scss b/src/views/room/widgets/furniture/FurnitureWidgets.scss
index 688d0e6a..0fe453bc 100644
--- a/src/views/room/widgets/furniture/FurnitureWidgets.scss
+++ b/src/views/room/widgets/furniture/FurnitureWidgets.scss
@@ -6,3 +6,4 @@
@import './mannequin/FurnitureMannequinView';
@import './stickie/FurnitureStickieView';
@import './high-score/FurnitureHighScoreView';
+@import './gift-opening/FurnitureGiftOpeningView';
diff --git a/src/views/room/widgets/furniture/FurnitureWidgetsView.tsx b/src/views/room/widgets/furniture/FurnitureWidgetsView.tsx
index b37b0a8d..2d152199 100644
--- a/src/views/room/widgets/furniture/FurnitureWidgetsView.tsx
+++ b/src/views/room/widgets/furniture/FurnitureWidgetsView.tsx
@@ -7,10 +7,10 @@ import { FurnitureDimmerView } from './dimmer/FurnitureDimmerView';
import { FurnitureExchangeCreditView } from './exchange-credit/FurnitureExchangeCreditView';
import { FurnitureExternalImageView } from './external-image/FurnitureExternalImageView';
import { FurnitureFriendFurniView } from './friend-furni/FurnitureFriendFurniView';
+import { FurnitureGiftOpeningView } from './gift-opening/FurnitureGiftOpeningView';
import { FurnitureHighScoreView } from './high-score/FurnitureHighScoreView';
import { FurnitureManipulationMenuView } from './manipulation-menu/FurnitureManipulationMenuView';
import { FurnitureMannequinView } from './mannequin/FurnitureMannequinView';
-import { FurniturePresentView } from './present/FurniturePresentView';
import { FurnitureStickieView } from './stickie/FurnitureStickieView';
import { FurnitureTrophyView } from './trophy/FurnitureTrophyView';
@@ -23,11 +23,11 @@ export const FurnitureWidgetsView: FC<{}> = props =>
+
-
diff --git a/src/views/room/widgets/furniture/dimmer/DimmerFurnitureWidgetPresetItem.ts b/src/views/room/widgets/furniture/dimmer/DimmerFurnitureWidgetPresetItem.ts
new file mode 100644
index 00000000..3e8009af
--- /dev/null
+++ b/src/views/room/widgets/furniture/dimmer/DimmerFurnitureWidgetPresetItem.ts
@@ -0,0 +1,8 @@
+export class DimmerFurnitureWidgetPresetItem
+{
+ constructor(
+ public id: number = 0,
+ public type: number = 0,
+ public color: number = 0,
+ public light: number = 0) {}
+}
diff --git a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerData.ts b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerData.ts
index 3076cea2..0836e20f 100644
--- a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerData.ts
+++ b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerData.ts
@@ -2,6 +2,5 @@ export class FurnitureDimmerData
{
constructor(
public objectId: number,
- public category: number,
- public active: boolean) {}
+ public category: number) {}
}
diff --git a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.scss b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.scss
index cbea044c..1e671f8d 100644
--- a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.scss
+++ b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.scss
@@ -1,3 +1,13 @@
.nitro-dimmer {
width: 300px;
+
+ .dimmer-banner {
+ width: 56px;
+ height: 79px;
+ background: url(../../../../../assets/images/room-widgets/dimmer-widget/dimmer_banner.png) center no-repeat;
+ }
+
+ .color-swatch {
+ height: 30px;
+ }
}
diff --git a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx
index c868e9cd..7c2022a9 100644
--- a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx
+++ b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx
@@ -1,80 +1,205 @@
-import { FC, useCallback, useState } from 'react';
-import { LocalizeText } from '../../../../../api';
-import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../layout';
+import { NitroEvent } from '@nitrots/nitro-renderer';
+import { FC, useCallback, useEffect, useMemo, useState } from 'react';
+import ReactSlider from 'react-slider';
+import { ColorUtils, GetConfiguration, LocalizeText, RoomWidgetDimmerChangeStateMessage, RoomWidgetDimmerPreviewMessage, RoomWidgetDimmerSavePresetMessage, RoomWidgetUpdateDimmerEvent, RoomWidgetUpdateDimmerStateEvent } from '../../../../../api';
+import { BatchUpdates, CreateEventDispatcherHook } from '../../../../../hooks';
+import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../../layout';
import { useRoomContext } from '../../../context/RoomContext';
-import { FurnitureDimmerData } from './FurnitureDimmerData';
+import { DimmerFurnitureWidgetPresetItem } from './DimmerFurnitureWidgetPresetItem';
+
+const AVAILABLE_COLORS: number[] = [7665141, 21495, 15161822, 15353138, 15923281, 8581961, 0];
+const HTML_COLORS: string[] = ['#74F5F5', '#0053F7', '#E759DE', '#EA4532', '#F2F851', '#82F349', '#000000'];
+const MIN_BRIGHTNESS: number = 75;
+const MAX_BRIGHTNESS: number = 255;
export const FurnitureDimmerView: FC<{}> = props =>
{
+ const [ isVisible, setIsVisible ] = useState(false);
+ const [ presets, setPresets ] = useState([]);
+ const [ selectedPresetId, setSelectedPresetId ] = useState(0);
+ const [ dimmerState, setDimmerState ] = useState(0);
+ const [ lastDimmerState, setLastDimmerState ] = useState(0);
+ const [ effectId, setEffectId ] = useState(0);
+ const [ color, setColor ] = useState(0xFFFFFF);
+ const [ brightness, setBrightness ] = useState(0xFF);
+ const [ selectedEffectId, setSelectedEffectId ] = useState(0);
+ const [ selectedColor, setSelectedColor ] = useState(0);
+ const [ selectedBrightness, setSelectedBrightness ] = useState(0);
+
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
- const [ dimmerData, setDimmerData ] = useState(null);
- // const onNitroEvent = useCallback((event: NitroEvent) =>
- // {
- // switch(event.type)
- // {
- // case RoomEngineTriggerWidgetEvent.REQUEST_DIMMER: {
- // const widgetEvent = (event as RoomEngineTriggerWidgetEvent);
-
- // const roomObject = GetRoomEngine().getRoomObject(widgetEvent.roomId, widgetEvent.objectId, widgetEvent.category);
-
- // if(!roomObject) return;
-
- // const data = roomObject.model.getValue(RoomObjectVariable.FURNITURE_DATA);
-
- // console.log('data', data);
-
- // setDimmerData(new FurnitureDimmerData(widgetEvent.objectId, widgetEvent.category, false));
- // return;
- // }
- // case RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED: {
- // const widgetEvent = (event as RoomWidgetRoomObjectUpdateEvent);
-
- // setDimmerData(prevState =>
- // {
- // if(!prevState || (widgetEvent.id !== prevState.objectId) || (widgetEvent.category !== prevState.category)) return prevState;
-
- // return null;
- // });
- // return;
- // }
- // case RoomWidgetDimmerUpdateEvent.RWDUE_PRESETS: {
- // const widgetEvent = (event as RoomWidgetDimmerUpdateEvent);
-
- // console.log(widgetEvent);
- // return;
- // }
- // case RoomWidgetDimmerStateUpdateEvent.RWDSUE_DIMMER_STATE: {
- // const widgetEvent = (event as RoomWidgetDimmerStateUpdateEvent);
-
- // console.log(widgetEvent);
- // return;
- // }
- // }
- // }, []);
-
- // useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_DIMMER, onNitroEvent);
- // CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED, props.events, onNitroEvent);
- // CreateEventDispatcherHook(RoomWidgetDimmerUpdateEvent.RWDUE_PRESETS, props.events, onNitroEvent);
- // CreateEventDispatcherHook(RoomWidgetDimmerStateUpdateEvent.RWDSUE_DIMMER_STATE, props.events, onNitroEvent);
-
- const processAction = useCallback((type: string, value: string = null) =>
+ const onNitroEvent = useCallback((event: NitroEvent) =>
{
- switch(type)
+ switch(event.type)
{
- case 'close':
- setDimmerData(null);
+ case RoomWidgetUpdateDimmerEvent.PRESETS: {
+ const widgetEvent = (event as RoomWidgetUpdateDimmerEvent);
+
+ const presets: DimmerFurnitureWidgetPresetItem[] = [];
+
+ for(const preset of widgetEvent.presets) presets.push(new DimmerFurnitureWidgetPresetItem(preset.id, preset.type, preset.color, preset.brightness));
+
+ setPresets(presets);
+ setSelectedPresetId(widgetEvent.selectedPresetId);
+ setIsVisible(true);
return;
+ }
+ case RoomWidgetUpdateDimmerEvent.HIDE: {
+ setIsVisible(false);
+
+ return;
+ }
+ case RoomWidgetUpdateDimmerStateEvent.DIMMER_STATE: {
+ const widgetEvent = (event as RoomWidgetUpdateDimmerStateEvent);
+
+ BatchUpdates(() =>
+ {
+ let prevDimmerState = 0;
+
+ setDimmerState(prevValue =>
+ {
+ setLastDimmerState(prevValue);
+
+ return widgetEvent.state;
+ });
+
+ setLastDimmerState(prevDimmerState);
+ setSelectedPresetId(widgetEvent.presetId);
+ setEffectId(widgetEvent.effectId);
+ setSelectedEffectId(widgetEvent.effectId);
+ setColor(widgetEvent.color);
+ setSelectedColor(widgetEvent.color);
+ setBrightness(widgetEvent.brightness);
+ setSelectedBrightness(widgetEvent.brightness);
+ });
+ return;
+ }
}
}, []);
- if(!dimmerData) return null;
+ CreateEventDispatcherHook(RoomWidgetUpdateDimmerEvent.PRESETS, eventDispatcher, onNitroEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdateDimmerEvent.HIDE, eventDispatcher, onNitroEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdateDimmerStateEvent.DIMMER_STATE, eventDispatcher, onNitroEvent);
+
+ const selectPresetId = useCallback((id: number) =>
+ {
+ const preset = presets[(id - 1)];
+
+ if(!preset) return;
+
+ setSelectedPresetId(preset.id);
+ setSelectedEffectId(preset.type);
+ setSelectedColor(preset.color);
+ setSelectedBrightness(preset.light);
+ }, [ presets ]);
+
+ const close = useCallback(() =>
+ {
+ widgetHandler.processWidgetMessage(new RoomWidgetDimmerPreviewMessage(color, brightness, (effectId === 2)));
+
+ setIsVisible(false);
+ }, [ widgetHandler, color, brightness, effectId ]);
+
+ const toggleState = useCallback(() =>
+ {
+ widgetHandler.processWidgetMessage(new RoomWidgetDimmerChangeStateMessage());
+ }, [ widgetHandler ]);
+
+ const applyChanges = useCallback(() =>
+ {
+ if(dimmerState === 0) return;
+
+ const selectedPresetIndex = (selectedPresetId - 1);
+
+ if((selectedPresetId < 1) || (selectedPresetId > presets.length)) return;
+
+ const preset = presets[selectedPresetIndex];
+
+ if(!preset || ((selectedEffectId === preset.type) && (selectedColor === preset.color) && (selectedBrightness === preset.light))) return;
+
+ setPresets(prevValue =>
+ {
+ const newValue = [ ...prevValue ];
+
+ newValue[selectedPresetIndex] = new DimmerFurnitureWidgetPresetItem(preset.id, selectedEffectId, selectedColor, selectedBrightness);
+
+ return newValue;
+ });
+
+ widgetHandler.processWidgetMessage(new RoomWidgetDimmerSavePresetMessage(preset.id, selectedEffectId, selectedColor, selectedBrightness, true));
+ }, [ widgetHandler, dimmerState, selectedPresetId, presets, selectedEffectId, selectedColor, selectedBrightness ]);
+
+ const scaledBrightness = useCallback((value: number) =>
+ {
+ return ~~((((value - MIN_BRIGHTNESS) * (100 - 0)) / (MAX_BRIGHTNESS - MIN_BRIGHTNESS)) + 0);
+ }, []);
+
+ const isFreeColorMode = useMemo(() =>
+ {
+ return GetConfiguration('widget.dimmer.colorwheel', false);
+ }, []);
+
+ useEffect(() =>
+ {
+ if((dimmerState === 0) && (lastDimmerState === 0)) return;
+
+ widgetHandler.processWidgetMessage(new RoomWidgetDimmerPreviewMessage(selectedColor, selectedBrightness, (selectedEffectId === 2)));
+ }, [ widgetHandler, dimmerState, lastDimmerState, selectedColor, selectedBrightness, selectedEffectId ]);
+
+ if(!isVisible) return null;
return (
- processAction('close') } />
-
-
+
+
+ { (dimmerState === 0) &&
+
+
+
{ LocalizeText('widget.dimmer.info.off') }
+
+
}
+ { (dimmerState === 1) &&
+ <>
+
+ { presets.map(preset =>
+ {
+ return selectPresetId(preset.id) }>{ LocalizeText(`widget.dimmer.tab.${preset.id}`) }
+ }) }
+
+
+
+
+ { isFreeColorMode &&
+
setSelectedColor(ColorUtils.convertFromHex(event.target.value)) } /> }
+ { !isFreeColorMode &&
+
+ { AVAILABLE_COLORS.map((color, index) =>
+ {
+ return
setSelectedColor(color) } style={{ backgroundColor: HTML_COLORS[index] }}>
;
+ }) }
+
}
+
+
+
+
setSelectedBrightness(value) }
+ thumbClassName={ 'thumb percent' }
+ renderThumb={ (props, state) => { scaledBrightness(state.valueNow) }
} />
+
+
+ setSelectedEffectId(event.target.checked ? 2 : 1) } />
+
+
+
+
+
+
+
+ > }
);
diff --git a/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditData.ts b/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditData.ts
deleted file mode 100644
index eeb128b3..00000000
--- a/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditData.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export class FurnitureExchangeCreditData
-{
- constructor(
- public objectId: number,
- public category: number,
- public value: number) {}
-}
diff --git a/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditView.tsx b/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditView.tsx
index 43204da6..e8f6387b 100644
--- a/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditView.tsx
+++ b/src/views/room/widgets/furniture/exchange-credit/FurnitureExchangeCreditView.tsx
@@ -1,73 +1,51 @@
-import { FurnitureExchangeComposer, NitroEvent, RoomEngineTriggerWidgetEvent, RoomObjectVariable } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
-import { GetRoomEngine, GetRoomSession, IsOwnerOfFurniture, LocalizeText, RoomWidgetRoomObjectUpdateEvent } from '../../../../../api';
+import { LocalizeText, RoomWidgetCreditFurniRedeemMessage, RoomWidgetUpdateCreditFurniEvent } from '../../../../../api';
+import { BatchUpdates } from '../../../../../hooks';
import { CreateEventDispatcherHook } from '../../../../../hooks/events/event-dispatcher.base';
-import { useRoomEngineEvent } from '../../../../../hooks/events/nitro/room/room-engine-event';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../layout';
import { useRoomContext } from '../../../context/RoomContext';
-import { FurnitureExchangeCreditData } from './FurnitureExchangeCreditData';
export const FurnitureExchangeCreditView: FC<{}> = props =>
{
+ const [ objectId, setObjectId ] = useState(-1);
+ const [ value, setValue ] = useState(0);
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
- const [ exchangeCreditData, setExchangeCreditData ] = useState(null);
- const onNitroEvent = useCallback((event: NitroEvent) =>
+ const onRoomWidgetUpdateCreditFurniEvent = useCallback((event: RoomWidgetUpdateCreditFurniEvent) =>
{
- switch(event.type)
- {
- case RoomEngineTriggerWidgetEvent.REQUEST_CREDITFURNI: {
- const widgetEvent = (event as RoomEngineTriggerWidgetEvent);
-
- const roomObject = GetRoomEngine().getRoomObject(widgetEvent.roomId, widgetEvent.objectId, widgetEvent.category);
-
- if(!roomObject || !IsOwnerOfFurniture(roomObject)) return;
-
- const value = roomObject.model.getValue(RoomObjectVariable.FURNITURE_CREDIT_VALUE);
-
- setExchangeCreditData(new FurnitureExchangeCreditData(widgetEvent.objectId, widgetEvent.category, value));
- return;
- }
- case RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED: {
- const widgetEvent = (event as RoomWidgetRoomObjectUpdateEvent);
-
- setExchangeCreditData(prevState =>
- {
- if(!prevState || (widgetEvent.id !== prevState.objectId) || (widgetEvent.category !== prevState.category)) return prevState;
-
- return null;
- });
- return;
- }
- }
+ setObjectId(event.objectId);
+ setValue(event.value);
}, []);
- useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_CREDITFURNI, onNitroEvent);
- CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED, eventDispatcher, onNitroEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdateCreditFurniEvent.CREDIT_FURNI_UPDATE, eventDispatcher, onRoomWidgetUpdateCreditFurniEvent);
const processAction = useCallback((type: string, value: string = null) =>
{
switch(type)
{
case 'close':
- setExchangeCreditData(null);
+ BatchUpdates(() =>
+ {
+ setObjectId(-1);
+ setValue(0);
+ });
return;
case 'redeem':
- if(!exchangeCreditData) return null;
-
- GetRoomSession().connection.send(new FurnitureExchangeComposer(exchangeCreditData.objectId));
+ widgetHandler.processWidgetMessage(new RoomWidgetCreditFurniRedeemMessage(RoomWidgetCreditFurniRedeemMessage.REDEEM, objectId));
+
+ processAction('close');
return;
}
- }, [exchangeCreditData]);
+ }, [ widgetHandler, objectId ]);
- if(!exchangeCreditData) return null;
+ if(objectId === -1) return null;
return (
processAction('close') } />
- { LocalizeText('widgets.furniture.credit.redeem.value', [ 'value' ], [ exchangeCreditData.value.toString() ]) }
+ { LocalizeText('widgets.furniture.credit.redeem.value', [ 'value' ], [ value.toString() ]) }
diff --git a/src/views/room/widgets/furniture/gift-opening/FurnitureGiftOpeningView.scss b/src/views/room/widgets/furniture/gift-opening/FurnitureGiftOpeningView.scss
new file mode 100644
index 00000000..9719609c
--- /dev/null
+++ b/src/views/room/widgets/furniture/gift-opening/FurnitureGiftOpeningView.scss
@@ -0,0 +1,3 @@
+.nitro-gift-opening {
+ min-width: 340px;
+}
diff --git a/src/views/room/widgets/furniture/gift-opening/FurnitureGiftOpeningView.tsx b/src/views/room/widgets/furniture/gift-opening/FurnitureGiftOpeningView.tsx
new file mode 100644
index 00000000..f0aabaf5
--- /dev/null
+++ b/src/views/room/widgets/furniture/gift-opening/FurnitureGiftOpeningView.tsx
@@ -0,0 +1,227 @@
+import { RoomObjectCategory, RoomObjectOperationType } from '@nitrots/nitro-renderer';
+import { FC, useCallback, useMemo, useState } from 'react';
+import { CreateLinkEvent, GetRoomEngine, GetSessionDataManager, LocalizeText, RoomWidgetPresentOpenMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdatePresentDataEvent } from '../../../../../api';
+import { CreateEventDispatcherHook } from '../../../../../hooks/events/event-dispatcher.base';
+import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutGiftCardView } from '../../../../../layout';
+import { ProductTypeEnum } from '../../../../catalog/common/ProductTypeEnum';
+import { useRoomContext } from '../../../context/RoomContext';
+
+const FLOOR: string = 'floor';
+const WALLPAPER: string = 'wallpaper';
+const LANDSCAPE: string = 'landscape';
+
+export const FurnitureGiftOpeningView: FC<{}> = props =>
+{
+ const [ objectId, setObjectId ] = useState(-1);
+ const [ classId, setClassId ] = useState(-1);
+ const [ itemType, setItemType ] = useState(null);
+ const [ text, setText ] = useState(null);
+ const [ isOwnerOfFurniture, setIsOwnerOfFurniture ] = useState(false);
+ const [ senderName, setSenderName ] = useState(null);
+ const [ senderFigure, setSenderFigure ] = useState(null);
+ const [ placedItemId, setPlacedItemId ] = useState(-1);
+ const [ placedItemType, setPlacedItemType ] = useState(null);
+ const [ placedInRoom, setPlacedInRoom ] = useState(false);
+ const [ imageUrl, setImageUrl ] = useState(null);
+ const [ openRequested, setOpenRequested ] = useState(false);
+ const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
+
+ const clearGift = useCallback(() =>
+ {
+ if(!openRequested) setObjectId(-1);
+
+ setText(null);
+ setIsOwnerOfFurniture(false);
+ }, [ openRequested ]);
+
+ const getGiftImageUrl = useCallback((name: string) =>
+ {
+ return '';
+ }, []);
+
+ const onRoomWidgetUpdatePresentDataEvent = useCallback((event: RoomWidgetUpdatePresentDataEvent) =>
+ {
+ switch(event.type)
+ {
+ case RoomWidgetUpdatePresentDataEvent.PACKAGEINFO: {
+ setOpenRequested(false);
+ setObjectId(event.objectId);
+ setText(event.giftMessage);
+ setIsOwnerOfFurniture(event.isController);
+ setSenderName(event.purchaserName);
+ setSenderFigure(event.purchaserFigure);
+ setImageUrl(event.imageUrl);
+ return;
+ }
+ case RoomWidgetUpdatePresentDataEvent.CONTENTS_FLOOR:
+ case RoomWidgetUpdatePresentDataEvent.CONTENTS_LANDSCAPE:
+ case RoomWidgetUpdatePresentDataEvent.CONTENTS_WALLPAPER: {
+ setObjectId(event.objectId);
+ setClassId(event.classId);
+ setItemType(event.itemType);
+ setText(event.giftMessage);
+ setIsOwnerOfFurniture(event.isController);
+ setPlacedItemId(event.placedItemId);
+ setPlacedItemType(event.placedItemType);
+ setPlacedInRoom(event.placedInRoom);
+
+ let imageType: string = null;
+
+ if(event.type === RoomWidgetUpdatePresentDataEvent.CONTENTS_FLOOR) imageType = 'packagecard_icon_floor';
+ else if(event.type === RoomWidgetUpdatePresentDataEvent.CONTENTS_LANDSCAPE) imageType = 'packagecard_icon_landscape';
+ else if(event.type === RoomWidgetUpdatePresentDataEvent.CONTENTS_WALLPAPER) imageType = 'packagecard_icon_wallpaper';
+
+ setImageUrl(getGiftImageUrl(imageType));
+ return;
+ }
+ case RoomWidgetUpdatePresentDataEvent.CONTENTS_CLUB: {
+ setObjectId(event.objectId);
+ setClassId(event.classId);
+ setItemType(event.itemType);
+ setText(event.giftMessage);
+ setIsOwnerOfFurniture(event.isController);
+ setImageUrl(getGiftImageUrl('packagecard_icon_hc'));
+ return;
+ }
+ case RoomWidgetUpdatePresentDataEvent.CONTENTS: {
+ if(!openRequested) return;
+
+ setObjectId(event.objectId);
+ setClassId(event.classId);
+ setItemType(event.itemType);
+ setText(event.giftMessage);
+ setIsOwnerOfFurniture(event.isController);
+ setPlacedItemId(event.placedItemId);
+ setPlacedItemType(event.placedItemType);
+ setPlacedInRoom(event.placedInRoom);
+
+ return;
+ }
+ case RoomWidgetUpdatePresentDataEvent.CONTENTS_IMAGE: {
+ if(!openRequested) return;
+
+ setImageUrl(event.imageUrl);
+ }
+ }
+ }, [ openRequested, getGiftImageUrl ]);
+
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.PACKAGEINFO, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.CONTENTS, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.CONTENTS_FLOOR, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.CONTENTS_LANDSCAPE, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.CONTENTS_WALLPAPER, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.CONTENTS_CLUB, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+ CreateEventDispatcherHook(RoomWidgetUpdatePresentDataEvent.CONTENTS_IMAGE, eventDispatcher, onRoomWidgetUpdatePresentDataEvent);
+
+ const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
+ {
+ if(event.id === objectId) clearGift();
+
+ if(event.id === placedItemId)
+ {
+ if(placedInRoom) setPlacedInRoom(false);
+ }
+ }, [ objectId, placedItemId, placedInRoom, clearGift ]);
+
+ CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
+
+ const close = useCallback(() =>
+ {
+ setObjectId(-1);
+ setOpenRequested(false);
+ setPlacedItemId(-1);
+ setPlacedInRoom(false);
+ setText(null);
+ setIsOwnerOfFurniture(false);
+ }, [ clearGift ]);
+
+ const isSpaces = useMemo(() =>
+ {
+ if(itemType !== ProductTypeEnum.WALL) return false;
+
+ const furniData = GetSessionDataManager().getWallItemData(classId);
+
+ if(!furniData) return false;
+
+ const className = furniData.className;
+
+ return (className === FLOOR || className === LANDSCAPE || className === WALLPAPER);
+ }, [ classId, itemType ]);
+
+ const productName = useMemo(() =>
+ {
+ if(objectId === -1) return '';
+
+ if(isSpaces)
+ return 'widget.furni.present.spaces.message_opened';
+
+ return 'widget.furni.present.message_opened';
+ }, [ objectId, isSpaces ]);
+
+ const handleAction = useCallback((action: string) =>
+ {
+ switch(action)
+ {
+ case 'give_gift':
+ CreateLinkEvent('catalog/open');
+ return;
+ case 'open':
+ setOpenRequested(true);
+ widgetHandler.processWidgetMessage(new RoomWidgetPresentOpenMessage(RoomWidgetPresentOpenMessage.OPEN_PRESENT, objectId));
+ return;
+ case 'room':
+ return;
+ case 'inventory':
+ if((placedItemId > 0) && placedInRoom)
+ {
+ if(placedItemType === ProductTypeEnum.PET)
+ {
+ roomSession.pickupPet(placedItemId);
+ }
+ else
+ {
+ const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, placedItemId, RoomObjectCategory.FLOOR);
+
+ if(roomObject) GetRoomEngine().processRoomObjectOperation(roomObject.id, RoomObjectCategory.FLOOR, RoomObjectOperationType.OBJECT_PICKUP);
+ }
+ }
+
+ close();
+ return;
+ }
+ }, [ roomSession, widgetHandler, objectId, placedInRoom, placedItemId, placedItemType, close ]);
+
+ if(objectId === -1) return null;
+
+ return (
+
+
+
+ { placedItemId === -1 && <>
+
+ { isOwnerOfFurniture &&
+ { senderName && }
+
+
}
+ > }
+ { placedItemId !== -1 && <>
+
+
+
![]({)
+
+
+ { LocalizeText(productName, ['product'], [text]) }
+
+
+
+
+
+
+ { senderName && <>
+
+ > }
+ > }
+
+
+ );
+}
diff --git a/src/views/room/widgets/furniture/present/FurniturePresentView.scss b/src/views/room/widgets/furniture/present/FurniturePresentView.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/views/room/widgets/furniture/present/FurniturePresentView.tsx b/src/views/room/widgets/furniture/present/FurniturePresentView.tsx
deleted file mode 100644
index 3516185a..00000000
--- a/src/views/room/widgets/furniture/present/FurniturePresentView.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { NitroEvent, RoomEngineTriggerWidgetEvent } from '@nitrots/nitro-renderer';
-import { FC } from 'react';
-import { useRoomEngineEvent } from '../../../../../hooks/events/nitro/room/room-engine-event';
-import { useRoomContext } from '../../../context/RoomContext';
-
-export const FurniturePresentView: FC<{}> = props =>
-{
- const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
-
- const onNitroEvent = (event: NitroEvent) =>
- {
- console.log(event);
- };
-
- useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PRESENT, onNitroEvent);
-
- return null;
-}
diff --git a/src/views/shared/currency-icon/CurrencyIcon.scss b/src/views/shared/currency-icon/CurrencyIcon.scss
index 4134543b..743b94ec 100644
--- a/src/views/shared/currency-icon/CurrencyIcon.scss
+++ b/src/views/shared/currency-icon/CurrencyIcon.scss
@@ -1,6 +1,6 @@
.nitro-currency-icon {
background-position: center;
background-repeat: no-repeat;
- width: 20px;
- height: 20px;
+ width: 18px;
+ height: 17px;
}
diff --git a/src/views/shared/furni-image/FurniImageView.tsx b/src/views/shared/furni-image/FurniImageView.tsx
index e73bfa84..63c006ca 100644
--- a/src/views/shared/furni-image/FurniImageView.tsx
+++ b/src/views/shared/furni-image/FurniImageView.tsx
@@ -41,7 +41,7 @@ export const FurniImageView: FC = props =>
if(imageResult)
{
const image = imageResult.getImage();
-
+
image.onload = () => setImageElement(image);
}
}, [ type, spriteId, direction, extras ]);
diff --git a/src/views/toolbar/ToolbarView.tsx b/src/views/toolbar/ToolbarView.tsx
index 4d017724..74b22062 100644
--- a/src/views/toolbar/ToolbarView.tsx
+++ b/src/views/toolbar/ToolbarView.tsx
@@ -178,11 +178,6 @@ export const ToolbarView: FC = props =>
{ (unseenInventoryCount > 0) && (
{ unseenInventoryCount }
) }
- handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }>
-
- { (unseenFriendListCount > 0) && (
-
{ unseenFriendListCount }
) }
-
{ isInRoom && (
handleToolbarItemClick(ToolbarViewItems.CAMERA_ITEM) }>
@@ -194,6 +189,13 @@ export const ToolbarView: FC
= props =>
+
+
handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }>
+
+ { (unseenFriendListCount > 0) && (
+
{ unseenFriendListCount }
) }
+
+