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 }
) } +
+