+
setSearchValue(event.target.value) } />
diff --git a/src/views/inventory/views/pet/InventoryPetView.tsx b/src/views/inventory/views/pet/InventoryPetView.tsx
index 5d8d8d90..b9949c95 100644
--- a/src/views/inventory/views/pet/InventoryPetView.tsx
+++ b/src/views/inventory/views/pet/InventoryPetView.tsx
@@ -2,10 +2,15 @@ import { RequestPetsComposer, RoomObjectVariable } from '@nitrots/nitro-renderer
import { FC, useEffect } from 'react';
import { GetRoomEngine, LocalizeText } from '../../../../api';
import { SendMessageHook } from '../../../../hooks/messages/message-event';
+import { NitroLayoutBase } from '../../../../layout/base';
+import { NitroLayoutFlexColumn } from '../../../../layout/flex-column/NitroLayoutFlexColumn';
+import { NitroLayoutGridColumn } from '../../../../layout/grid/column/NitroLayoutGridColumn';
+import { NitroLayoutGrid } from '../../../../layout/grid/NitroLayoutGrid';
import { RoomPreviewerView } from '../../../shared/room-previewer/RoomPreviewerView';
import { attemptPetPlacement } from '../../common/PetUtilities';
import { useInventoryContext } from '../../context/InventoryContext';
import { InventoryPetActions } from '../../reducers/InventoryPetReducer';
+import { InventoryCategoryEmptyView } from '../category-empty/InventoryCategoryEmptyView';
import { InventoryPetViewProps } from './InventoryPetView.types';
import { InventoryPetResultsView } from './results/InventoryPetResultsView';
@@ -62,35 +67,23 @@ export const InventoryPetView: FC
= props =>
roomPreviewer.addPetIntoRoom(petData.figureString);
}, [ roomPreviewer, petItem ]);
- if(!petItems || !petItems.length)
- {
- return (
-
-
-
-
- { LocalizeText('inventory.empty.pets.title') }
-
-
{ LocalizeText('inventory.empty.pets.desc') }
-
-
- );
- }
+ if(!petItems || !petItems.length) return ;
return (
-
-
+
+
-
-
-
- { petItem &&
-
{ petItem.petData.name }
- { !!roomSession &&
}
-
}
-
-
+
+
+
+
+
+ { petItem &&
+
+ { petItem.petData.name }
+ { !!roomSession && }
+ }
+
+
);
}
diff --git a/src/views/inventory/views/trade/InventoryTradeView.tsx b/src/views/inventory/views/trade/InventoryTradeView.tsx
index 5969daec..f376e890 100644
--- a/src/views/inventory/views/trade/InventoryTradeView.tsx
+++ b/src/views/inventory/views/trade/InventoryTradeView.tsx
@@ -2,8 +2,12 @@ import { FurnitureListComposer, IObjectData, TradingAcceptComposer, TradingConfi
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { LocalizeText } from '../../../../api';
import { SendMessageHook } from '../../../../hooks/messages';
+import { NitroLayoutButton, NitroLayoutFlex, NitroLayoutFlexColumn } from '../../../../layout';
+import { NitroLayoutBase } from '../../../../layout/base';
import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView';
import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView';
+import { NitroLayoutGridColumn } from '../../../../layout/grid/column/NitroLayoutGridColumn';
+import { NitroLayoutGrid } from '../../../../layout/grid/NitroLayoutGrid';
import { FurniCategory } from '../../common/FurniCategory';
import { GroupItem } from '../../common/GroupItem';
import { IFurnitureItem } from '../../common/IFurnitureItem';
@@ -224,67 +228,81 @@ export const InventoryTradeView: FC = props =>
}, [ tradeData, dispatchFurnitureState ]);
return (
-
-
-
-
- { filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) =>
- {
- const count = item.getUnlockedCount();
-
- return (
- (count && setGroupItem(item)) }>
- { ((count > 0) && (groupItem === item)) &&
- }
-
- );
- }) }
-
-
{ groupItem ? groupItem.name : LocalizeText('catalog_selectproduct') }
-
-
-
-
{ LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:
+
+
+
+
- { Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
+ { filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) =>
{
- const item = (tradeData.ownUser.items.getWithIndex(i) || null);
-
- if(!item) return ;
+ const count = item.getUnlockedCount();
return (
- setOwnGroupItem(item) }>
- { (ownGroupItem === item) &&
-
-
-
-
{ tradeData.otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:
-
- { Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
- {
- const item = (tradeData.otherUser.items.getWithIndex(i) || null);
+
+
+ { groupItem ? groupItem.name : LocalizeText('catalog_selectproduct') }
+
+
+
+
+
+
+ { LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:
+
+ { Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
+ {
+ const item = (tradeData.ownUser.items.getWithIndex(i) || null);
- if(!item) return ;
+ if(!item) return ;
- return setOtherGroupItem(item) } />;
- }) }
- { otherGroupItem ? otherGroupItem.name : LocalizeText('catalog_selectproduct') }
-
-
-
- { LocalizeText('generic.cancel') }
+ return (
+ setOwnGroupItem(item) }>
+ { (ownGroupItem === item) &&
+ removeItem(item) }>
+
+ }
+
+ );
+ }) }
+
+
+
+ { ownGroupItem ? ownGroupItem.name : LocalizeText('catalog_selectproduct') }
+
+
+
+
+ { tradeData.otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:
+
+ { Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
+ {
+ const item = (tradeData.otherUser.items.getWithIndex(i) || null);
+
+ if(!item) return ;
+
+ return setOtherGroupItem(item) } />;
+ }) }
+
+
+
+ { otherGroupItem ? otherGroupItem.name : LocalizeText('catalog_selectproduct') }
+
+
+
+
+ { LocalizeText('generic.cancel') }
{ getTradeButton }
-
-
-
+
+
+
);
}
diff --git a/src/views/main/MainView.tsx b/src/views/main/MainView.tsx
index 68269e58..49e28a61 100644
--- a/src/views/main/MainView.tsx
+++ b/src/views/main/MainView.tsx
@@ -9,6 +9,7 @@ import { CameraWidgetView } from '../camera/CameraWidgetView';
import { CatalogView } from '../catalog/CatalogView';
import { FriendsView } from '../friends/FriendsView';
import { GroupsView } from '../groups/GroupsView';
+import { HelpView } from '../help/HelpView';
import { HotelView } from '../hotel-view/HotelView';
import { InventoryView } from '../inventory/InventoryView';
import { ModToolsView } from '../mod-tools/ModToolsView';
@@ -69,6 +70,7 @@ export const MainView: FC = props =>
+
);
}
diff --git a/src/views/navigator/NavigatorView.scss b/src/views/navigator/NavigatorView.scss
index d29e353b..a438267d 100644
--- a/src/views/navigator/NavigatorView.scss
+++ b/src/views/navigator/NavigatorView.scss
@@ -1,11 +1,6 @@
.nitro-navigator {
- width: 400px;
-
- .content-area {
- min-height: 400px;
- height: 400px;
- resize: vertical;
- }
+ width: $navigator-width;
+ height: $navigator-height;
}
.nitro-navigator-doorbell {
diff --git a/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx b/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx
index 385a0a4f..8fe49ce2 100644
--- a/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx
+++ b/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx
@@ -1,8 +1,8 @@
import { RoomBannedUsersComposer, RoomBannedUsersEvent, RoomSettingsEvent, RoomUsersWithRightsComposer, RoomUsersWithRightsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../api';
-import { FriendListEvent } from '../../../../events';
-import { FriendListContentEvent } from '../../../../events/friend-list/FriendListContentEvent';
+import { FriendsEvent } from '../../../../events';
+import { FriendListContentEvent } from '../../../../events/friends/FriendListContentEvent';
import { dispatchUiEvent, useUiEvent } from '../../../../hooks';
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
@@ -87,7 +87,7 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
useEffect(() =>
{
- if(roomSettingsData) dispatchUiEvent(new FriendListEvent(FriendListEvent.REQUEST_FRIEND_LIST));
+ if(roomSettingsData) dispatchUiEvent(new FriendsEvent(FriendsEvent.REQUEST_FRIEND_LIST));
}, [roomSettingsData])
const save = useCallback((data: RoomSettingsData) =>
diff --git a/src/views/notification-center/NotificationCenterMessageHandler.tsx b/src/views/notification-center/NotificationCenterMessageHandler.tsx
index de974b13..9afc098d 100644
--- a/src/views/notification-center/NotificationCenterMessageHandler.tsx
+++ b/src/views/notification-center/NotificationCenterMessageHandler.tsx
@@ -1,20 +1,14 @@
-import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, ClubGiftNotificationEvent, HabboBroadcastMessageEvent, HotelClosesAndWillOpenAtEvent, HotelWillShutdownEvent, ModeratorMessageEvent, MOTDNotificationEvent, NotificationDialogMessageEvent, PetAddedToInventoryEvent, RespectReceivedEvent, RoomEnterEvent, Vector3d } from '@nitrots/nitro-renderer';
+import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, HabboBroadcastMessageEvent, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelWillCloseInMinutesEvent, InfoFeedEnableMessageEvent, MaintenanceStatusMessageEvent, ModeratorCautionEvent, ModeratorMessageEvent, MOTDNotificationEvent, NotificationDialogMessageEvent, PetLevelNotificationEvent, PetReceivedMessageEvent, RespectReceivedEvent, RoomEnterEvent, UserBannedMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
-import { GetRoomEngine, GetSessionDataManager, LocalizeBadgeName, LocalizeText } from '../../api';
-import { NotificationCenterAlertEvent } from '../../events';
-import { dispatchUiEvent } from '../../hooks/events';
+import { GetConfiguration, GetRoomEngine, GetSessionDataManager, LocalizeBadgeName, LocalizeText } from '../../api';
import { CreateMessageHook } from '../../hooks/messages';
-import { HotelWillShutdownNotification } from './common/HotelWillShutdownNotification';
-import { NotificationType } from './common/NotificationType';
+import { NotificationBubbleType } from './common/NotificationBubbleType';
import { NotificationUtilities } from './common/NotificationUtilities';
-import { useNotificationCenterContext } from './context/NotificationCenterContext';
+import { ProductImageUtility } from './common/ProductImageUtility';
import { INotificationCenterMessageHandlerProps } from './NotificationCenterMessageHandler.types';
-import { NotificationCenterActions } from './reducers/NotificationCenterReducer';
export const NotificationCenterMessageHandler: FC
= props =>
{
- const { dispatchNotificationCenterState = null } = useNotificationCenterContext();
-
const onRespectReceivedEvent = useCallback((event: RespectReceivedEvent) =>
{
const parser = event.getParser();
@@ -24,8 +18,8 @@ export const NotificationCenterMessageHandler: FC('currency.asset.icon.url', '').replace('%type%', parser.type.toString());
+ break;
+ }
+
+ NotificationUtilities.showSingleBubble(LocalizeText('notifications.text.loyalty.received', [ 'amount' ], [ parser.amountChanged.toString() ]), NotificationBubbleType.INFO, imageUrl);
}, []);
CreateMessageHook(ActivityPointNotificationMessageEvent, onActivityPointNotificationMessageEvent);
+ const onUserBannedMessageEvent = useCallback((event: UserBannedMessageEvent) =>
+ {
+ const parser = event.getParser();
+
+ NotificationUtilities.handleUserBannedMessage(parser.message);
+ }, []);
+
+ CreateMessageHook(UserBannedMessageEvent, onUserBannedMessageEvent);
+
const onHotelClosesAndWillOpenAtEvent = useCallback((event: HotelClosesAndWillOpenAtEvent) =>
{
const parser = event.getParser();
@@ -89,7 +103,7 @@ export const NotificationCenterMessageHandler: FC
+ const onPetReceivedMessageEvent = useCallback((event: PetReceivedMessageEvent) =>
{
const parser = event.getParser();
@@ -101,10 +115,10 @@ export const NotificationCenterMessageHandler: FC
{
@@ -119,24 +133,67 @@ export const NotificationCenterMessageHandler: FC
+ const onPetLevelNotificationEvent = useCallback((event: PetLevelNotificationEvent) =>
{
const parser = event.getParser();
- dispatchNotificationCenterState({
- type: NotificationCenterActions.ADD_NOTIFICATION,
- payload: {
- notification: new HotelWillShutdownNotification(parser.minutes)
- }
- });
- }, [ dispatchNotificationCenterState ]);
+ let imageUrl: string = null;
- CreateMessageHook(HotelWillShutdownEvent, onHotelWillShutdownEvent);
+ const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.figureData.typeId, parser.figureData.paletteId, parseInt(parser.figureData.color, 16), new Vector3d(45 * 3), 64, null, true);
+
+ if(imageResult) imageUrl = imageResult.getImage().src;
+
+ NotificationUtilities.showSingleBubble(LocalizeText('notifications.text.petlevel', [ 'pet_name', 'level' ], [ parser.petName, parser.level.toString() ]), NotificationBubbleType.PETLEVEL, imageUrl);
+ }, []);
+
+ CreateMessageHook(PetLevelNotificationEvent, onPetLevelNotificationEvent);
+
+ const onInfoFeedEnableMessageEvent = useCallback((event: InfoFeedEnableMessageEvent) =>
+ {
+ const parser = event.getParser();
+
+ NotificationUtilities.BUBBLES_DISABLED = !(parser.enabled);
+ }, []);
+
+ CreateMessageHook(InfoFeedEnableMessageEvent, onInfoFeedEnableMessageEvent);
+
+ const onClubGiftSelectedEvent = useCallback((event: ClubGiftSelectedEvent) =>
+ {
+ const parser = event.getParser();
+
+ if(!parser.products || !parser.products.length) return;
+
+ const productData = parser.products[0];
+
+ if(!productData) return;
+
+ NotificationUtilities.showSingleBubble(LocalizeText('notifications.text.club_gift.selected'), NotificationBubbleType.INFO, ProductImageUtility.getProductImageUrl(productData.productType, productData.furniClassId, productData.extraParam))
+ }, []);
+
+ CreateMessageHook(ClubGiftSelectedEvent, onClubGiftSelectedEvent);
+
+ const onMaintenanceStatusMessageEvent = useCallback((event: MaintenanceStatusMessageEvent) =>
+ {
+ const parser = event.getParser();
+
+ NotificationUtilities.handleHotelMaintenanceMessage(parser.minutesUntilMaintenance, parser.duration);
+ }, []);
+
+ CreateMessageHook(MaintenanceStatusMessageEvent, onMaintenanceStatusMessageEvent);
+
+ const onModeratorCautionEvent = useCallback((event: ModeratorCautionEvent) =>
+ {
+ const parser = event.getParser();
+
+ NotificationUtilities.handleModeratorCaution(parser.message, parser.url);
+ }, []);
+
+ CreateMessageHook(ModeratorCautionEvent, onModeratorCautionEvent);
const onNotificationDialogMessageEvent = useCallback((event: NotificationDialogMessageEvent) =>
{
@@ -147,5 +204,23 @@ export const NotificationCenterMessageHandler: FC
+ {
+ const parser = event.getParser();
+
+ NotificationUtilities.handleHotelClosingMessage(parser.openMinute);
+ }, []);
+
+ CreateMessageHook(HotelWillCloseInMinutesEvent, onHotelWillCloseInMinutesEvent);
+
+ const onHotelClosedAndOpensEvent = useCallback((event: HotelClosedAndOpensEvent) =>
+ {
+ const parser = event.getParser();
+
+ NotificationUtilities.handleLoginFailedHotelClosedMessage(parser.openHour, parser.openMinute);
+ }, []);
+
+ CreateMessageHook(HotelClosedAndOpensEvent, onHotelClosedAndOpensEvent);
+
return null;
}
diff --git a/src/views/notification-center/NotificationCenterView.scss b/src/views/notification-center/NotificationCenterView.scss
index 78a94d63..671ea3e7 100644
--- a/src/views/notification-center/NotificationCenterView.scss
+++ b/src/views/notification-center/NotificationCenterView.scss
@@ -1,12 +1,3 @@
-.nitro-alert {
- width: 350px;
-
- .content-area {
- min-height: 125px;
- max-height: 300px;
- }
-}
-
.nitro-notification-center-container {
position: absolute;
top: 0;
diff --git a/src/views/notification-center/NotificationCenterView.tsx b/src/views/notification-center/NotificationCenterView.tsx
index ace8d3e4..0367b604 100644
--- a/src/views/notification-center/NotificationCenterView.tsx
+++ b/src/views/notification-center/NotificationCenterView.tsx
@@ -1,40 +1,42 @@
import { FC, ReactNode, useCallback, useMemo, useState } from 'react';
-import { NotificationCenterAlertEvent } from '../../events';
+import { createPortal } from 'react-dom';
+import { NotificationAlertEvent } from '../../events';
import { NotificationBubbleEvent } from '../../events/notification-center/NotificationBubbleEvent';
import { useUiEvent } from '../../hooks/events';
-import { NotificationItem } from './common/NotificationItem';
-import { NotificationType } from './common/NotificationType';
+import { NotificationAlertItem } from './common/NotificationAlertItem';
+import { NotificationBubbleItem } from './common/NotificationBubbleItem';
+import { NotificationBubbleType } from './common/NotificationBubbleType';
import { NotificationCenterMessageHandler } from './NotificationCenterMessageHandler';
import { NotificationCenterViewProps } from './NotificationCenterView.types';
-import { NotificationCenterBroadcastMessageView } from './views/broadcast-message/NotificationCenterBroadcastMessageView';
+import { GetAlertLayout } from './views/alert-layouts/GetAlertLayout';
import { GetBubbleLayout } from './views/bubble-layouts/GetBubbleLayout';
export const NotificationCenterView: FC = props =>
{
- const [ alerts, setAlerts ] = useState([]);
- const [ bubbleAlerts, setBubbleAlerts ] = useState([]);
+ const [ alerts, setAlerts ] = useState([]);
+ const [ bubbleAlerts, setBubbleAlerts ] = useState([]);
- const onNotificationCenterAlertEvent = useCallback((event: NotificationCenterAlertEvent) =>
+ const onNotificationAlertEvent = useCallback((event: NotificationAlertEvent) =>
{
- setAlerts(prevValue =>
- {
- return [ ...prevValue, event ];
- });
+ console.log(event);
+ const alertItem = new NotificationAlertItem(event.messages, event.alertType, event.clickUrl, event.clickUrlText, event.title, event.imageUrl);
+
+ setAlerts(prevValue => [ alertItem, ...prevValue ]);
}, []);
- useUiEvent(NotificationCenterAlertEvent.HOTEL_ALERT, onNotificationCenterAlertEvent);
+ useUiEvent(NotificationAlertEvent.ALERT, onNotificationAlertEvent);
const onNotificationBubbleEvent = useCallback((event: NotificationBubbleEvent) =>
{
console.log(event);
- const notificationItem = new NotificationItem(event.message, event.notificationType, event.imageUrl, event.linkUrl);
+ const notificationItem = new NotificationBubbleItem(event.message, event.notificationType, event.imageUrl, event.linkUrl);
setBubbleAlerts(prevValue => [ notificationItem, ...prevValue ]);
}, []);
useUiEvent(NotificationBubbleEvent.NEW_BUBBLE, onNotificationBubbleEvent);
- const closeAlert = useCallback((alert: NotificationCenterAlertEvent) =>
+ const closeAlert = useCallback((alert: NotificationAlertItem) =>
{
setAlerts(prevValue =>
{
@@ -47,7 +49,7 @@ export const NotificationCenterView: FC = props =>
});
}, []);
- const closeBubbleAlert = useCallback((item: NotificationItem) =>
+ const closeBubbleAlert = useCallback((item: NotificationBubbleItem) =>
{
setBubbleAlerts(prevValue =>
{
@@ -60,6 +62,22 @@ export const NotificationCenterView: FC = props =>
})
}, []);
+ const getAlerts = useMemo(() =>
+ {
+ if(!alerts || !alerts.length) return null;
+
+ const elements: ReactNode[] = [];
+
+ for(const alert of alerts)
+ {
+ const element = GetAlertLayout(alert, () => closeAlert(alert));
+
+ elements.push(element);
+ }
+
+ return elements;
+ }, [ alerts, closeAlert ]);
+
const getBubbleAlerts = useMemo(() =>
{
if(!bubbleAlerts || !bubbleAlerts.length) return null;
@@ -70,7 +88,7 @@ export const NotificationCenterView: FC = props =>
{
const element = GetBubbleLayout(alert, () => closeBubbleAlert(alert));
- if(alert.notificationType === NotificationType.CLUBGIFT)
+ if(alert.notificationType === NotificationBubbleType.CLUBGIFT)
{
elements.unshift(element);
@@ -89,15 +107,7 @@ export const NotificationCenterView: FC = props =>
{ getBubbleAlerts }
- { (alerts.length > 0) && alerts.map((alert, index) =>
- {
- switch(alert.type)
- {
- case NotificationCenterAlertEvent.HOTEL_ALERT:
- default:
- return closeAlert(alert) } />;
- }
- })}
+ { createPortal(getAlerts, document.getElementById('nitro-alerts-container')) }
>
);
}
diff --git a/src/views/notification-center/common/BroadcastMessageNotification.ts b/src/views/notification-center/common/BroadcastMessageNotification.ts
deleted file mode 100644
index ddf0fa0d..00000000
--- a/src/views/notification-center/common/BroadcastMessageNotification.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { NitroNotification } from './Notification';
-
-export class BroadcastMessageNotification extends NitroNotification
-{}
diff --git a/src/views/notification-center/common/DialogMessageNotification.ts b/src/views/notification-center/common/DialogMessageNotification.ts
deleted file mode 100644
index a3201658..00000000
--- a/src/views/notification-center/common/DialogMessageNotification.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { NitroNotification } from './Notification';
-
-export class DialogMessageNotification extends NitroNotification
-{
- private _type: string;
- private _parameters: Map;
-
- constructor(type: string, parameters: Map)
- {
- super();
- this._type = type;
- this._parameters = parameters;
- }
-
- public get type(): string
- {
- return this._type;
- }
-
- public get parameters(): Map
- {
- return this._parameters;
- }
-}
diff --git a/src/views/notification-center/common/HotelWillShutdownNotification.ts b/src/views/notification-center/common/HotelWillShutdownNotification.ts
deleted file mode 100644
index 9f30c1ae..00000000
--- a/src/views/notification-center/common/HotelWillShutdownNotification.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { NitroNotification } from './Notification';
-
-export class HotelWillShutdownNotification extends NitroNotification
-{
- private _minutes: number;
-
- constructor(minutes: number)
- {
- super();
- this._minutes = minutes;
- }
-
- public get minutes(): number
- {
- return this._minutes;
- }
-}
diff --git a/src/views/notification-center/common/MOTDNotification.ts b/src/views/notification-center/common/MOTDNotification.ts
deleted file mode 100644
index f543507d..00000000
--- a/src/views/notification-center/common/MOTDNotification.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { NitroNotification } from './Notification';
-
-export class MOTDNotification extends NitroNotification
-{
- private _messages: string[];
-
- constructor(messages: string[])
- {
- super();
- this._messages = [];
-
- for(const message of messages) this._messages.push(message.replace(/\r\n|\r|\n/g, '
'));
- }
-
- public get messages(): string[]
- {
- return this._messages;
- }
-}
diff --git a/src/views/notification-center/common/ModeratorMessageNotification.ts b/src/views/notification-center/common/ModeratorMessageNotification.ts
deleted file mode 100644
index ed324b11..00000000
--- a/src/views/notification-center/common/ModeratorMessageNotification.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { NitroNotification } from './Notification';
-
-export class ModeratorMessageNotification extends NitroNotification
-{
- private _link: string;
-
- constructor(message: string, link: string)
- {
- super(message);
- this._link = link;
- }
-
- public get link(): string
- {
- return this._link;
- }
-}
diff --git a/src/views/notification-center/common/Notification.ts b/src/views/notification-center/common/Notification.ts
deleted file mode 100644
index 2f170cce..00000000
--- a/src/views/notification-center/common/Notification.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-export class NitroNotification
-{
- public static CURRENT_ID: number = 0;
-
- private _id: number;
- private _title: string;
- private _message: string;
- private _dismissed: boolean = false;
- private _timestamp: number;
-
- constructor(message: string = null, title: string = null)
- {
- this._id = ++NitroNotification.CURRENT_ID;
- this._title = title;
- this._timestamp = Date.now();
-
- if(message) this._message = message.replace(/\r\n|\r|\n/g, '
');
- }
-
- public dismiss(): void
- {
- this._dismissed = true;
- }
-
- public get id(): number
- {
- return this._id;
- }
-
- public get title(): string
- {
- return this._title;
- }
-
- public get message(): string
- {
- return this._message;
- }
-
- public get dismissed(): boolean
- {
- return this._dismissed;
- }
-
- public get timestamp(): number
- {
- return this._timestamp;
- }
-}
diff --git a/src/views/notification-center/common/NotificationAlertItem.ts b/src/views/notification-center/common/NotificationAlertItem.ts
new file mode 100644
index 00000000..b3432276
--- /dev/null
+++ b/src/views/notification-center/common/NotificationAlertItem.ts
@@ -0,0 +1,62 @@
+import { NotificationBubbleType } from './NotificationBubbleType';
+
+export class NotificationAlertItem
+{
+ private static ITEM_ID: number = -1;
+
+ private _id: number;
+ private _messages: string[];
+ private _alertType: string;
+ private _clickUrl: string;
+ private _clickUrlText: string;
+ private _title: string;
+ private _imageUrl: string;
+
+ constructor(messages: string[], alertType: string = NotificationBubbleType.INFO, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null)
+ {
+ NotificationAlertItem.ITEM_ID += 1;
+
+ this._id = NotificationAlertItem.ITEM_ID;
+ this._messages = messages;
+ this._alertType = alertType;
+ this._clickUrl = clickUrl;
+ this._clickUrlText = clickUrlText;
+ this._title = title;
+ this._imageUrl = imageUrl;
+ }
+
+ public get id(): number
+ {
+ return this._id;
+ }
+
+ public get messages(): string[]
+ {
+ return this._messages;
+ }
+
+ public get alertType(): string
+ {
+ return this._alertType;
+ }
+
+ public get clickUrl(): string
+ {
+ return this._clickUrl;
+ }
+
+ public get clickUrlText(): string
+ {
+ return this._clickUrlText;
+ }
+
+ public get title(): string
+ {
+ return this._title;
+ }
+
+ public get imageUrl(): string
+ {
+ return this._imageUrl;
+ }
+}
diff --git a/src/views/notification-center/common/NotificationAlertType.ts b/src/views/notification-center/common/NotificationAlertType.ts
new file mode 100644
index 00000000..9a4b192b
--- /dev/null
+++ b/src/views/notification-center/common/NotificationAlertType.ts
@@ -0,0 +1,7 @@
+export class NotificationAlertType
+{
+ public static DEFAULT: string = 'default';
+ public static MOTD: string = 'motd';
+ public static MODERATION: string = 'moderation';
+ public static EVENT: string = 'event';
+}
diff --git a/src/views/notification-center/common/NotificationItem.ts b/src/views/notification-center/common/NotificationBubbleItem.ts
similarity index 75%
rename from src/views/notification-center/common/NotificationItem.ts
rename to src/views/notification-center/common/NotificationBubbleItem.ts
index 9387db74..fe90dab7 100644
--- a/src/views/notification-center/common/NotificationItem.ts
+++ b/src/views/notification-center/common/NotificationBubbleItem.ts
@@ -1,6 +1,6 @@
-import { NotificationType } from './NotificationType';
+import { NotificationBubbleType } from './NotificationBubbleType';
-export class NotificationItem
+export class NotificationBubbleItem
{
private static ITEM_ID: number = -1;
@@ -10,11 +10,11 @@ export class NotificationItem
private _iconUrl: string;
private _linkUrl: string;
- constructor(message: string, notificationType: string = NotificationType.INFO, iconUrl: string = null, linkUrl: string = null)
+ constructor(message: string, notificationType: string = NotificationBubbleType.INFO, iconUrl: string = null, linkUrl: string = null)
{
- NotificationItem.ITEM_ID += 1;
+ NotificationBubbleItem.ITEM_ID += 1;
- this._id = NotificationItem.ITEM_ID;
+ this._id = NotificationBubbleItem.ITEM_ID;
this._message = message;
this._notificationType = notificationType;
this._iconUrl = iconUrl;
diff --git a/src/views/notification-center/common/NotificationType.ts b/src/views/notification-center/common/NotificationBubbleType.ts
similarity index 95%
rename from src/views/notification-center/common/NotificationType.ts
rename to src/views/notification-center/common/NotificationBubbleType.ts
index dff016d8..cce38f5b 100644
--- a/src/views/notification-center/common/NotificationType.ts
+++ b/src/views/notification-center/common/NotificationBubbleType.ts
@@ -1,4 +1,4 @@
-export class NotificationType
+export class NotificationBubbleType
{
public static FRIENDOFFLINE: string = 'friendoffline';
public static FRIENDONLINE: string = 'friendonline';
diff --git a/src/views/notification-center/common/NotificationUtilities.ts b/src/views/notification-center/common/NotificationUtilities.ts
index a80247b4..c4dd1bd9 100644
--- a/src/views/notification-center/common/NotificationUtilities.ts
+++ b/src/views/notification-center/common/NotificationUtilities.ts
@@ -1,10 +1,11 @@
import { HabboWebTools, RoomEnterEffect } from '@nitrots/nitro-renderer';
import { CreateLinkEvent, GetConfiguration, GetNitroInstance, LocalizeText } from '../../../api';
-import { SimpleAlertUIEvent } from '../../../events';
+import { NotificationAlertEvent } from '../../../events';
import { NotificationBubbleEvent } from '../../../events/notification-center/NotificationBubbleEvent';
import { dispatchUiEvent } from '../../../hooks';
import { CatalogPageName } from '../../catalog/common/CatalogPageName';
-import { NotificationType } from './NotificationType';
+import { NotificationAlertType } from './NotificationAlertType';
+import { NotificationBubbleType } from './NotificationBubbleType';
export class NotificationUtilities
{
@@ -12,6 +13,8 @@ export class NotificationUtilities
private static MODERATION_DISCLAIMER_DELAY_MS: number = 5000;
private static MODERATION_DISCLAIMER_TIMEOUT: ReturnType = null;
+ public static BUBBLES_DISABLED: boolean = false;
+
private static cleanText(text: string): string
{
return text.replace(/\\r/g, '\r')
@@ -68,62 +71,92 @@ export class NotificationUtilities
const configuration = this.getNotificationConfig(('notification.' + type));
- if(configuration)
- {
- for(const key in configuration) options.set(key, configuration[key]);
- }
+ if(configuration) for(const key in configuration) options.set(key, configuration[key]);
console.log(options);
+ const title = this.getNotificationPart(options, type, 'title', true);
+ const message = this.getNotificationPart(options, type, 'message', true).replace(/\\r/g, '\r');
+ const linkTitle = this.getNotificationPart(options, type, 'linkTitle', false);
+ const linkUrl = this.getNotificationPart(options, type, 'linkUrl', false);
+ const image = this.getNotificationImageUrl(options, type);
+
if(options.get('display') === 'BUBBLE')
{
- const message = this.getNotificationPart(options, type, 'message', true);
- const linkUrl = this.getNotificationPart(options, type, 'linkUrl', false);
- const isEventLink = (linkUrl && linkUrl.substr(0, 6) === 'event');
- const image = this.getNotificationImageUrl(options, type);
-
- dispatchUiEvent(new NotificationBubbleEvent(LocalizeText(message), NotificationType.INFO, LocalizeText(image), (isEventLink ? linkUrl.substr(6) : linkUrl)));
+ this.showSingleBubble(LocalizeText(message), NotificationBubbleType.INFO, LocalizeText(image), linkUrl);
}
else
{
-
+ this.simpleAlert(message, NotificationAlertType.EVENT, linkUrl, linkTitle, title, image);
}
}
public static showSingleBubble(message: string, type: string, imageUrl: string = null, internalLink: string = null): void
{
+ if(this.BUBBLES_DISABLED) return;
+
dispatchUiEvent(new NotificationBubbleEvent(message, type, imageUrl, internalLink));
}
- public static simpleAlert(message: string, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null): void
- {
- if(!title || !title.length) title = LocalizeText('notifications.broadcast.title');
-
- dispatchUiEvent(new SimpleAlertUIEvent(message, clickUrl, clickUrlText, title, imageUrl));
- }
-
- public static alert(title: string, message: string): void
- {
- dispatchUiEvent(new SimpleAlertUIEvent(message, null, null, title, null));
- }
-
public static showClubGiftNotification(numGifts: number): void
{
if(numGifts <= 0) return;
- dispatchUiEvent(new NotificationBubbleEvent(numGifts.toString(), NotificationType.CLUBGIFT, null, 'catalog/open/' + CatalogPageName.CLUB_GIFTS));
+ this.showSingleBubble(numGifts.toString(), NotificationBubbleType.CLUBGIFT, null, ('catalog/open/' + CatalogPageName.CLUB_GIFTS));
}
- public static showModeratorMessage(message: string, url: string = null): void
+ public static handleMOTD(messages: string[]): void
{
- this.simpleAlert(this.cleanText(message), url, LocalizeText('mod.alert.link'), LocalizeText('mod.alert.title'));
+ messages = messages.map(message => this.cleanText(message));
+
+ dispatchUiEvent(new NotificationAlertEvent(messages, NotificationAlertType.MOTD, null, null, LocalizeText('notifications.motd.title')));
+ }
+
+ public static simpleAlert(message: string, type: string, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null): void
+ {
+ if(!title || !title.length) title = LocalizeText('notifications.broadcast.title');
+
+ dispatchUiEvent(new NotificationAlertEvent([ this.cleanText(message) ], type, clickUrl, clickUrlText, title, imageUrl));
+ }
+
+ public static showModeratorMessage(message: string, url: string = null, showHabboWay: boolean = true): void
+ {
+ this.simpleAlert(message, NotificationAlertType.MODERATION, url, LocalizeText('mod.alert.link'), LocalizeText('mod.alert.title'));
+ }
+
+ public static handleModeratorCaution(message: string, url: string = null): void
+ {
+ this.showModeratorMessage(message, url);
+ }
+
+ public static handleModeratorMessage(message: string, url: string = null): void
+ {
+ this.showModeratorMessage(message, url, false);
+ }
+
+ public static handleUserBannedMessage(message: string): void
+ {
+ this.showModeratorMessage(message);
}
public static handleHotelClosedMessage(open: number, minute: number, thrownOut: boolean): void
{
- const text: string = LocalizeText(('opening.hours.' + (thrownOut ? 'disconnected' : 'closed')), [ 'h', 'm'], [ this.getTimeZeroPadded(open), this.getTimeZeroPadded(minute) ]);;
+ this.simpleAlert( LocalizeText(('opening.hours.' + (thrownOut ? 'disconnected' : 'closed')), [ 'h', 'm'], [ this.getTimeZeroPadded(open), this.getTimeZeroPadded(minute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
+ }
- this.alert(LocalizeText('opening.hours.title'), text);
+ public static handleHotelMaintenanceMessage(minutesUntilMaintenance: number, duration: number): void
+ {
+ this.simpleAlert(LocalizeText('maintenance.shutdown', [ 'm', 'd' ], [ minutesUntilMaintenance.toString(), duration.toString() ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
+ }
+
+ public static handleHotelClosingMessage(minutes: number): void
+ {
+ this.simpleAlert(LocalizeText('opening.hours.shutdown', [ 'm' ], [ minutes.toString() ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
+ }
+
+ public static handleLoginFailedHotelClosedMessage(openHour: number, openMinutes: number): void
+ {
+ this.simpleAlert(LocalizeText('opening.hours.disconnected', [ 'h', 'm' ], [ openHour.toString(), openMinutes.toString() ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
}
public static openUrl(url: string): void
@@ -134,7 +167,7 @@ export class NotificationUtilities
}
else
{
- CreateLinkEvent(url);
+ CreateLinkEvent(url.substring(6));
}
}
@@ -153,7 +186,7 @@ export class NotificationUtilities
{
if(this.MODERATION_DISCLAIMER_SHOWN) return;
- this.showSingleBubble(LocalizeText('mod.chatdisclaimer'), NotificationType.INFO);
+ this.showSingleBubble(LocalizeText('mod.chatdisclaimer'), NotificationBubbleType.INFO);
this.MODERATION_DISCLAIMER_SHOWN = true;
}
diff --git a/src/views/notification-center/common/ProductImageUtility.ts b/src/views/notification-center/common/ProductImageUtility.ts
new file mode 100644
index 00000000..9078754c
--- /dev/null
+++ b/src/views/notification-center/common/ProductImageUtility.ts
@@ -0,0 +1,59 @@
+import { CatalogPageMessageProductData } from '@nitrots/nitro-renderer';
+import { GetRoomEngine } from '../../../api';
+import { FurniCategory } from '../../catalog/common/FurniCategory';
+
+export class ProductImageUtility
+{
+ public static getProductImageUrl(productType: string, furniClassId: number, extraParam: string): string
+ {
+ let imageUrl: string = null;
+
+ switch(productType)
+ {
+ case CatalogPageMessageProductData.S:
+ imageUrl = GetRoomEngine().getFurnitureFloorIconUrl(furniClassId);
+ break;
+ case CatalogPageMessageProductData.I:
+ const productCategory = this.getProductCategory(CatalogPageMessageProductData.I, furniClassId);
+
+ if(productCategory === 1)
+ {
+ imageUrl = GetRoomEngine().getFurnitureWallIconUrl(furniClassId, extraParam);
+ }
+ else
+ {
+ switch(productCategory)
+ {
+ case FurniCategory.WALL_PAPER:
+ break;
+ case FurniCategory.LANDSCAPE:
+ break;
+ case FurniCategory.FLOOR:
+ break;
+ }
+ }
+ break;
+ case CatalogPageMessageProductData.E:
+ // fx_icon_furniClassId_png
+ break;
+ }
+
+ return imageUrl;
+ }
+
+ private static getProductCategory(productType: string, furniClassId: number): number
+ {
+ if(productType === CatalogPageMessageProductData.S) return 1;
+
+ if(productType === CatalogPageMessageProductData.I)
+ {
+ if(furniClassId === 3001) return FurniCategory.WALL_PAPER;
+
+ if(furniClassId === 3002) return FurniCategory.FLOOR;
+
+ if(furniClassId === 4057) return FurniCategory.LANDSCAPE;
+ }
+
+ return 1;
+ }
+}
diff --git a/src/views/notification-center/context/NotificationCenterContext.tsx b/src/views/notification-center/context/NotificationCenterContext.tsx
deleted file mode 100644
index 036cd97b..00000000
--- a/src/views/notification-center/context/NotificationCenterContext.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createContext, FC, useContext } from 'react';
-import { INotificationCenterContext, NotificationCenterContextProps } from './NotificationCenterContext.types';
-
-const NotificationCenterContext = createContext({
- notificationCenterState: null,
- dispatchNotificationCenterState: null
-});
-
-export const NotificationCenterContextProvider: FC = props =>
-{
- return { props.children }
-}
-
-export const useNotificationCenterContext = () => useContext(NotificationCenterContext);
diff --git a/src/views/notification-center/context/NotificationCenterContext.types.ts b/src/views/notification-center/context/NotificationCenterContext.types.ts
deleted file mode 100644
index 8e5358f4..00000000
--- a/src/views/notification-center/context/NotificationCenterContext.types.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Dispatch, ProviderProps } from 'react';
-import { INotificationCenterAction, INotificationCenterState } from '../reducers/NotificationCenterReducer';
-
-export interface INotificationCenterContext
-{
- notificationCenterState: INotificationCenterState;
- dispatchNotificationCenterState: Dispatch;
-}
-
-export interface NotificationCenterContextProps extends ProviderProps
-{
-
-}
diff --git a/src/views/notification-center/reducers/NotificationCenterReducer.tsx b/src/views/notification-center/reducers/NotificationCenterReducer.tsx
deleted file mode 100644
index 8d861033..00000000
--- a/src/views/notification-center/reducers/NotificationCenterReducer.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import { Reducer } from 'react';
-import { NitroNotification } from '../common/Notification';
-
-export interface INotificationCenterState
-{
- notifications: NitroNotification[];
-}
-
-export interface INotificationCenterAction
-{
- type: string;
- payload: {
- id?: number;
- notification?: NitroNotification;
- };
-}
-
-export class NotificationCenterActions
-{
- public static ADD_NOTIFICATION: string = 'NCA_ADD_NOTIFICATION';
- public static REMOVE_NOTIFICATION: string = 'NCA_REMOVE_NOTIFICATION';
- public static DISMISS_NOTIFICATION: string = 'NCA_DISMISS_NOTIFICATION';
-}
-
-export const initialNotificationCenter: INotificationCenterState = {
- notifications: []
-}
-
-export const NotificationCenterReducer: Reducer = (state, action) =>
-{
- switch(action.type)
- {
- case NotificationCenterActions.ADD_NOTIFICATION: {
- const notification = (action.payload.notification || null);
-
- if(!notification) return state;
-
- const notifications = [ ...state.notifications, notification ];
-
- return { ...state, notifications };
- }
- case NotificationCenterActions.REMOVE_NOTIFICATION: {
- const id = (action.payload.id || null);
-
- if(!id) return state;
-
- if(!state.notifications) return state;
-
- const notifications = Array.from(state.notifications);
- const notificationIndex = notifications.findIndex(notification => notification.id === id);
-
- if(notificationIndex === -1) return state;
-
- notifications.splice(notificationIndex, 1);
-
- return { ...state, notifications };
- }
- case NotificationCenterActions.DISMISS_NOTIFICATION: {
- const id = (action.payload.id || null);
-
- if(!id) return state;
-
- if(!state.notifications) return state;
-
- const notifications = Array.from(state.notifications);
- const notificationIndex = notifications.findIndex(notification => notification.id === id);
-
- if(notificationIndex === -1) return state;
-
- notifications[notificationIndex].dismiss();
-
- return { ...state, notifications };
- }
- default:
- return state;
- }
-}
diff --git a/src/views/notification-center/views/alert-base/NotificationCenterAlertBase.tsx b/src/views/notification-center/views/alert-base/NotificationCenterAlertBase.tsx
deleted file mode 100644
index e071e39b..00000000
--- a/src/views/notification-center/views/alert-base/NotificationCenterAlertBase.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { FC } from 'react';
-import { LocalizeText } from '../../../../api';
-import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
-import { NotificationCenterAlertBaseProps } from './NotificationCenterAlertBase.types';
-
-
-export const NotificationCenterAlertBase: FC = props =>
-{
- const { headerText = LocalizeText('mod.alert.title'), onClose = null, children = null } = props;
-
- return (
-
-
-
- { children }
-
-
- );
-}
diff --git a/src/views/notification-center/views/alert-base/NotificationCenterAlertBase.types.ts b/src/views/notification-center/views/alert-base/NotificationCenterAlertBase.types.ts
deleted file mode 100644
index e7c08d27..00000000
--- a/src/views/notification-center/views/alert-base/NotificationCenterAlertBase.types.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface NotificationCenterAlertBaseProps
-{
- headerText?: string;
- onClose: () => void;
-}
diff --git a/src/views/notification-center/views/alert-layouts/GetAlertLayout.tsx b/src/views/notification-center/views/alert-layouts/GetAlertLayout.tsx
new file mode 100644
index 00000000..fb774c6e
--- /dev/null
+++ b/src/views/notification-center/views/alert-layouts/GetAlertLayout.tsx
@@ -0,0 +1,19 @@
+import { NotificationAlertItem } from '../../common/NotificationAlertItem';
+import { NotificationAlertType } from '../../common/NotificationAlertType';
+import { NotificationDefaultAlertView } from './default/NotificationDefaultAlertView';
+import { NotificationEventAlertView } from './event/NotificationEventAlertView';
+
+export const GetAlertLayout = (item: NotificationAlertItem, close: () => void) =>
+{
+ if(!item) return null;
+
+ const props = { key: item.id, item, close };
+
+ switch(item.alertType)
+ {
+ case NotificationAlertType.EVENT:
+ return
+ default:
+ return
+ }
+}
diff --git a/src/views/notification-center/views/alert-layouts/NotificationAlertLayoutView.types.ts b/src/views/notification-center/views/alert-layouts/NotificationAlertLayoutView.types.ts
new file mode 100644
index 00000000..57c77873
--- /dev/null
+++ b/src/views/notification-center/views/alert-layouts/NotificationAlertLayoutView.types.ts
@@ -0,0 +1,7 @@
+import { NotificationAlertItem } from '../../common/NotificationAlertItem';
+
+export interface NotificationAlertLayoutViewProps
+{
+ item: NotificationAlertItem;
+ close: () => void;
+}
diff --git a/src/views/notification-center/views/alert-layouts/default/NotificationDefaultAlertView.tsx b/src/views/notification-center/views/alert-layouts/default/NotificationDefaultAlertView.tsx
new file mode 100644
index 00000000..5b567410
--- /dev/null
+++ b/src/views/notification-center/views/alert-layouts/default/NotificationDefaultAlertView.tsx
@@ -0,0 +1,35 @@
+import { FC, useCallback } from 'react';
+import { LocalizeText } from '../../../../../api';
+import { NotificationAlertView } from '../../../../../layout';
+import { NotificationUtilities } from '../../../common/NotificationUtilities';
+import { NotificationDefaultAlertViewProps } from './NotificationDefaultAlertView.types';
+
+export const NotificationDefaultAlertView: FC = props =>
+{
+ const { item = null, close = null, ...rest } = props;
+
+ const visitUrl = useCallback(() =>
+ {
+ NotificationUtilities.openUrl(item.clickUrl);
+
+ close();
+ }, [ item, close ]);
+
+ return (
+
+ { (item.messages.length > 0) && item.messages.map((message, index) =>
+ {
+ const htmlText = message.replace(/\r\n|\r|\n/g, '
');
+
+ return (
+
+ );
+ }) }
+
+ { LocalizeText('generic.close') }
+
+ { item.clickUrl && item.clickUrl.length &&
+ { LocalizeText(item.clickUrlText) } }
+
+ );
+}
diff --git a/src/views/notification-center/views/alert-layouts/default/NotificationDefaultAlertView.types.ts b/src/views/notification-center/views/alert-layouts/default/NotificationDefaultAlertView.types.ts
new file mode 100644
index 00000000..287d8ca3
--- /dev/null
+++ b/src/views/notification-center/views/alert-layouts/default/NotificationDefaultAlertView.types.ts
@@ -0,0 +1,7 @@
+import { DetailsHTMLAttributes } from 'react';
+import { NotificationAlertLayoutViewProps } from '../NotificationAlertLayoutView.types';
+
+export interface NotificationDefaultAlertViewProps extends NotificationAlertLayoutViewProps, DetailsHTMLAttributes
+{
+
+}
diff --git a/src/views/notification-center/views/alert-layouts/event/NotificationEventAlertView.tsx b/src/views/notification-center/views/alert-layouts/event/NotificationEventAlertView.tsx
new file mode 100644
index 00000000..8910e22e
--- /dev/null
+++ b/src/views/notification-center/views/alert-layouts/event/NotificationEventAlertView.tsx
@@ -0,0 +1,33 @@
+import { FC, useCallback } from 'react';
+import { LocalizeText } from '../../../../../api';
+import { NotificationAlertView } from '../../../../../layout';
+import { NotificationUtilities } from '../../../common/NotificationUtilities';
+import { NotificationEventAlertViewProps } from './NotificationEventAlertView.types';
+
+export const NotificationEventAlertView: FC = props =>
+{
+ const { item = null, close = null, ...rest } = props;
+
+ const visitUrl = useCallback(() =>
+ {
+ NotificationUtilities.openUrl(item.clickUrl);
+
+ close();
+ }, [ item, close ]);
+
+ return (
+
+ { (item.messages.length > 0) && item.messages.map((message, index) =>
+ {
+ const htmlText = message.replace(/\r\n|\r|\n/g, '
');
+
+ return (
+
+ );
+ }) }
+
+ { LocalizeText(item.clickUrlText) }
+
+
+ );
+}
diff --git a/src/views/notification-center/views/alert-layouts/event/NotificationEventAlertView.types.ts b/src/views/notification-center/views/alert-layouts/event/NotificationEventAlertView.types.ts
new file mode 100644
index 00000000..1d8b2906
--- /dev/null
+++ b/src/views/notification-center/views/alert-layouts/event/NotificationEventAlertView.types.ts
@@ -0,0 +1,7 @@
+import { DetailsHTMLAttributes } from 'react';
+import { NotificationAlertLayoutViewProps } from '../NotificationAlertLayoutView.types';
+
+export interface NotificationEventAlertViewProps extends NotificationAlertLayoutViewProps, DetailsHTMLAttributes
+{
+
+}
diff --git a/src/views/notification-center/views/broadcast-message/NotificationCenterBroadcastMessageView.tsx b/src/views/notification-center/views/broadcast-message/NotificationCenterBroadcastMessageView.tsx
deleted file mode 100644
index 04908525..00000000
--- a/src/views/notification-center/views/broadcast-message/NotificationCenterBroadcastMessageView.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { FC, useMemo } from 'react';
-import { LocalizeText } from '../../../../api';
-import { NotificationCenterAlertBase } from '../alert-base/NotificationCenterAlertBase';
-import { NotificationCenterBroadcastMessageViewProps } from './NotificationCenterBroadcastMessageView.types';
-
-export const NotificationCenterBroadcastMessageView: FC = props =>
-{
- const { notification = null, onClose = null } = props;
-
- const message = useMemo(() =>
- {
- let finalMessage = '';
-
- notification.message.forEach(message =>
- {
- finalMessage += message.replace(/\r\n|\r|\n/g, '
');
- });
-
- return finalMessage;
- }, [ notification ]);
-
- return (
-
-
-
- { LocalizeText('generic.close') }
-
-
- );
-};
diff --git a/src/views/notification-center/views/broadcast-message/NotificationCenterBroadcastMessageView.types.ts b/src/views/notification-center/views/broadcast-message/NotificationCenterBroadcastMessageView.types.ts
deleted file mode 100644
index bd89dd38..00000000
--- a/src/views/notification-center/views/broadcast-message/NotificationCenterBroadcastMessageView.types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { NotificationCenterAlertEvent } from '../../../../events';
-
-export class NotificationCenterBroadcastMessageViewProps
-{
- notification: NotificationCenterAlertEvent;
- onClose: () => void;
-}
diff --git a/src/views/notification-center/views/bubble-layouts/GetBubbleLayout.tsx b/src/views/notification-center/views/bubble-layouts/GetBubbleLayout.tsx
index 08492b92..4426df56 100644
--- a/src/views/notification-center/views/bubble-layouts/GetBubbleLayout.tsx
+++ b/src/views/notification-center/views/bubble-layouts/GetBubbleLayout.tsx
@@ -1,9 +1,9 @@
-import { NotificationItem } from '../../common/NotificationItem';
-import { NotificationType } from '../../common/NotificationType';
+import { NotificationBubbleItem } from '../../common/NotificationBubbleItem';
+import { NotificationBubbleType } from '../../common/NotificationBubbleType';
import { NotificationClubGiftBubbleView } from './club-gift/NotificationClubGiftBubbleView';
import { NotificationDefaultBubbleView } from './default/NotificationDefaultBubbleView';
-export const GetBubbleLayout = (item: NotificationItem, close: () => void) =>
+export const GetBubbleLayout = (item: NotificationBubbleItem, close: () => void) =>
{
if(!item) return null;
@@ -11,7 +11,7 @@ export const GetBubbleLayout = (item: NotificationItem, close: () => void) =>
switch(item.notificationType)
{
- case NotificationType.CLUBGIFT:
+ case NotificationBubbleType.CLUBGIFT:
return
default:
return
diff --git a/src/views/notification-center/views/bubble-layouts/NotificationBubbleLayoutView.types.ts b/src/views/notification-center/views/bubble-layouts/NotificationBubbleLayoutView.types.ts
index ca1fd341..5f9c81d6 100644
--- a/src/views/notification-center/views/bubble-layouts/NotificationBubbleLayoutView.types.ts
+++ b/src/views/notification-center/views/bubble-layouts/NotificationBubbleLayoutView.types.ts
@@ -1,7 +1,7 @@
-import { NotificationItem } from '../../common/NotificationItem';
+import { NotificationBubbleItem } from '../../common/NotificationBubbleItem';
export interface NotificationBubbleLayoutViewProps
{
- item: NotificationItem;
+ item: NotificationBubbleItem;
close: () => void;
}
diff --git a/src/views/notification-center/views/hotel-will-shutdown/HotelWillShutdownView.tsx b/src/views/notification-center/views/hotel-will-shutdown/HotelWillShutdownView.tsx
deleted file mode 100644
index 650de0e4..00000000
--- a/src/views/notification-center/views/hotel-will-shutdown/HotelWillShutdownView.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { FC } from 'react';
-import { LocalizeText } from '../../../../api';
-import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
-import { NotificationTrayItemView } from '../tray-item/NotificationTrayItemView';
-import { HotelWillShutdownViewProps } from './HotelWillShutdownView.types';
-
-export const HotelWillShutdownView: FC = props =>
-{
- const { notification = null, inTray = null, onButtonClick = null } = props;
-
- if(!notification) return null;
-
- const content = <>{ LocalizeText('opening.hours.shutdown', ['m'], [notification.minutes.toString()]) }>;
-
- if(inTray)
- return (
- onButtonClick('remove_notification') } />
- );
-
- return (
-
- onButtonClick('dismiss_notification') } />
-
- { content }
-
-
- );
-};
diff --git a/src/views/notification-center/views/hotel-will-shutdown/HotelWillShutdownView.types.ts b/src/views/notification-center/views/hotel-will-shutdown/HotelWillShutdownView.types.ts
deleted file mode 100644
index 89915153..00000000
--- a/src/views/notification-center/views/hotel-will-shutdown/HotelWillShutdownView.types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { HotelWillShutdownNotification } from '../../common/HotelWillShutdownNotification';
-import { NotificationViewProps } from '../../NotificationCenterView.types';
-
-export class HotelWillShutdownViewProps extends NotificationViewProps
-{
- notification: HotelWillShutdownNotification;
-}
diff --git a/src/views/notification-center/views/moderator-message/ModeratorMessageView.tsx b/src/views/notification-center/views/moderator-message/ModeratorMessageView.tsx
deleted file mode 100644
index 341d31ea..00000000
--- a/src/views/notification-center/views/moderator-message/ModeratorMessageView.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { FC } from 'react';
-import { LocalizeText } from '../../../../api';
-import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
-import { NotificationTrayItemView } from '../tray-item/NotificationTrayItemView';
-import { ModeratorMessageViewProps } from './ModeratorMessageView.types';
-
-export const ModeratorMessageView: FC = props =>
-{
- const { notification = null, inTray = null, onButtonClick = null } = props;
-
- if(!notification) return null;
-
- const content = <>
-
-
- >;
-
- if(inTray)
- return (
- onButtonClick('remove_notification') } />
- );
-
- return (
-
- onButtonClick('dismiss_notification') } />
-
- { content }
-
-
- );
-};
diff --git a/src/views/notification-center/views/moderator-message/ModeratorMessageView.types.ts b/src/views/notification-center/views/moderator-message/ModeratorMessageView.types.ts
deleted file mode 100644
index 2e7c63de..00000000
--- a/src/views/notification-center/views/moderator-message/ModeratorMessageView.types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { ModeratorMessageNotification } from '../../common/ModeratorMessageNotification';
-import { NotificationViewProps } from '../../NotificationCenterView.types';
-
-export class ModeratorMessageViewProps extends NotificationViewProps
-{
- notification: ModeratorMessageNotification;
-}
diff --git a/src/views/notification-center/views/motd/NotificationCenterMotdView.tsx b/src/views/notification-center/views/motd/NotificationCenterMotdView.tsx
deleted file mode 100644
index 1039f298..00000000
--- a/src/views/notification-center/views/motd/NotificationCenterMotdView.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { FC } from 'react';
-import { NotificationCenterBroadcastMessageView } from '../broadcast-message/NotificationCenterBroadcastMessageView';
-import { NotificationCenterMotdViewProps } from './NotificationCenterMotdView.types';
-
-export const NotificationCenterMotdView: FC = props =>
-{
- const { notification = null, onClose = null } = props;
-
- return ;
-}
diff --git a/src/views/notification-center/views/motd/NotificationCenterMotdView.types.ts b/src/views/notification-center/views/motd/NotificationCenterMotdView.types.ts
deleted file mode 100644
index 921e8634..00000000
--- a/src/views/notification-center/views/motd/NotificationCenterMotdView.types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { NotificationCenterAlertEvent } from '../../../../events';
-
-export interface NotificationCenterMotdViewProps
-{
- notification: NotificationCenterAlertEvent;
- onClose: () => void;
-}
diff --git a/src/views/notification-center/views/tray-item/NotificationTrayItemView.tsx b/src/views/notification-center/views/tray-item/NotificationTrayItemView.tsx
deleted file mode 100644
index cc836c6a..00000000
--- a/src/views/notification-center/views/tray-item/NotificationTrayItemView.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { FC } from 'react';
-import { NotificationTrayItemViewProps } from './NotificationTrayItemView.types';
-
-export const NotificationTrayItemView: FC = props =>
-{
- const { title = null, content = null, timestamp = null, onCloseClick = null } = props;
-
- return (
-
-
-
- { content }
-
-
- { timestamp }
-
-
- );
-};
diff --git a/src/views/notification-center/views/tray-item/NotificationTrayItemView.types.ts b/src/views/notification-center/views/tray-item/NotificationTrayItemView.types.ts
deleted file mode 100644
index c84e1793..00000000
--- a/src/views/notification-center/views/tray-item/NotificationTrayItemView.types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export class NotificationTrayItemViewProps
-{
- title: string;
- content: any;
- timestamp: number;
- onCloseClick: () => void;
-}
diff --git a/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx b/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx
index d949cfaa..a12d17bc 100644
--- a/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx
+++ b/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx
@@ -1,6 +1,6 @@
import { RoomEnterEffect, RoomObjectCategory } from '@nitrots/nitro-renderer';
import { FC, useCallback, useMemo, useState } from 'react';
-import { GetRoomSession, GetSessionDataManager, RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../../../api';
+import { GetRoomSession, GetSessionDataManager, RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../../../api';
import { CreateEventDispatcherHook } from '../../../../hooks/events/event-dispatcher.base';
import { useRoomContext } from '../../context/RoomContext';
import { AvatarInfoWidgetAvatarView } from './views/avatar/AvatarInfoWidgetAvatarView';
@@ -264,6 +264,13 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
// useUiEvent(FriendEnteredRoomEvent.ENTERED, onFriendEnteredRoomEvent);
+ const onRoomWidgetUpdateDecorateModeEvent = useCallback((event: RoomWidgetUpdateDecorateModeEvent) =>
+ {
+ setIsDecorating(event.isDecorating);
+ }, []);
+
+ CreateEventDispatcherHook(RoomWidgetUpdateDecorateModeEvent.UPDATE_DECORATE, eventDispatcher, onRoomWidgetUpdateDecorateModeEvent);
+
const decorateView = useMemo(() =>
{
GetRoomSession().isDecorating = isDecorating;
@@ -274,7 +281,7 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
const userName = GetSessionDataManager().userName;
const roomIndex = GetRoomSession().ownRoomIndex;
- return ;
+ return ;
}, [ isDecorating ]);
const currentView = useMemo(() =>
@@ -316,7 +323,7 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
{
if(RoomEnterEffect.isRunning()) return null;
- return ;
+ return ;
}
return ;
diff --git a/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.tsx b/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.tsx
index 5a365394..95b752b0 100644
--- a/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.tsx
+++ b/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.tsx
@@ -1,6 +1,7 @@
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
-import { FC } from 'react';
-import { LocalizeText } from '../../../../../../api';
+import { FC, useCallback } from 'react';
+import { LocalizeText, RoomWidgetUpdateDecorateModeEvent } from '../../../../../../api';
+import { useRoomContext } from '../../../../context/RoomContext';
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
import { ContextMenuListView } from '../../../context-menu/views/list/ContextMenuListView';
@@ -8,12 +9,18 @@ import { AvatarInfoWidgetDecorateViewProps } from './AvatarInfoWidgetDecorateVie
export const AvatarInfoWidgetDecorateView: FC = props =>
{
- const { userId = -1, userName = '', roomIndex = -1, setIsDecorating = null } = props;
+ const { userId = -1, userName = '', roomIndex = -1 } = props;
+ const { eventDispatcher = null } = useRoomContext();
+
+ const stopDecorating = useCallback(() =>
+ {
+ eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(false));
+ }, [ eventDispatcher ]);
return (
- setIsDecorating(false) }>
+
{ LocalizeText('widget.avatar.stop_decorating') }
diff --git a/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.types.ts b/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.types.ts
index 2440f17a..86c19e35 100644
--- a/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.types.ts
+++ b/src/views/room/widgets/avatar-info/views/decorate/AvatarInfoWidgetDecorateView.types.ts
@@ -1,9 +1,7 @@
-import { Dispatch, SetStateAction } from 'react';
export interface AvatarInfoWidgetDecorateViewProps
{
userId: number;
userName: string;
roomIndex: number;
- setIsDecorating: Dispatch>;
}
diff --git a/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.tsx b/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.tsx
index c5555ec3..1fa8c8e0 100644
--- a/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.tsx
+++ b/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.tsx
@@ -1,6 +1,6 @@
import { AvatarAction, AvatarExpressionEnum, RoomObjectCategory, UserProfileComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
-import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
+import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUserActionMessage } from '../../../../../../api';
import { AvatarEditorEvent } from '../../../../../../events';
import { dispatchUiEvent, SendMessageHook } from '../../../../../../hooks';
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
@@ -18,9 +18,9 @@ const MODE_SIGNS = 4;
export const AvatarInfoWidgetOwnAvatarView: FC = props =>
{
- const { userData = null, isDancing = false, setIsDecorating = null, close = null } = props;
+ const { userData = null, isDancing = false, close = null } = props;
const [ mode, setMode ] = useState((isDancing && HasHabboClub()) ? MODE_CLUB_DANCES : MODE_NORMAL);
- const { roomSession = null, widgetHandler = null } = useRoomContext();
+ const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
const processAction = useCallback((name: string) =>
{
@@ -40,7 +40,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC
{
diff --git a/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.types.ts b/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.types.ts
index e462efa6..00db768e 100644
--- a/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.types.ts
+++ b/src/views/room/widgets/avatar-info/views/own-avatar/AvatarInfoWidgetOwnAvatarView.types.ts
@@ -1,10 +1,8 @@
-import { Dispatch, SetStateAction } from 'react';
import { RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api';
export interface AvatarInfoWidgetOwnAvatarViewProps
{
userData: RoomWidgetUpdateInfostandUserEvent;
isDancing: boolean;
- setIsDecorating: Dispatch>;
close: () => void;
}
diff --git a/src/views/room/widgets/chat-input/ChatInputView.tsx b/src/views/room/widgets/chat-input/ChatInputView.tsx
index c1ac2a3b..534dd93c 100644
--- a/src/views/room/widgets/chat-input/ChatInputView.tsx
+++ b/src/views/room/widgets/chat-input/ChatInputView.tsx
@@ -260,11 +260,18 @@ export const ChatInputView: FC<{}> = props =>
}
}, [ onKeyDownEvent ]);
+ useEffect(() =>
+ {
+ if(!inputRef.current) return;
+
+ inputRef.current.parentElement.dataset.value = chatValue;
+ }, [ chatValue ]);
+
return (
createPortal(
, document.getElementById('toolbar-chat-input-container'))
diff --git a/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss b/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss
index 9bdbcb6b..9337ed85 100644
--- a/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss
+++ b/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss
@@ -696,7 +696,6 @@
justify-content: center;
height: 100%;
max-height: 24px;
- image-rendering: -webkit-optimize-contrast;
overflow: hidden;
.user-image {
@@ -707,8 +706,9 @@
height: 130px;
background-repeat: no-repeat;
background-position: center;
- transform: scale(0.5) translateZ(0);
+ transform: scale(0.5);
overflow: hidden;
+ image-rendering: -webkit-optimize-contrast;
}
}
diff --git a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx
index f65f2664..d1f88b64 100644
--- a/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx
+++ b/src/views/room/widgets/furniture/dimmer/FurnitureDimmerView.tsx
@@ -55,16 +55,8 @@ export const FurnitureDimmerView: FC<{}> = props =>
BatchUpdates(() =>
{
- let prevDimmerState = 0;
-
- setDimmerState(prevValue =>
- {
- setLastDimmerState(prevValue);
-
- return widgetEvent.state;
- });
-
- setLastDimmerState(prevDimmerState);
+ setLastDimmerState(dimmerState);
+ setDimmerState(widgetEvent.state);
setSelectedPresetId(widgetEvent.presetId);
setEffectId(widgetEvent.effectId);
setSelectedEffectId(widgetEvent.effectId);
@@ -73,10 +65,11 @@ export const FurnitureDimmerView: FC<{}> = props =>
setBrightness(widgetEvent.brightness);
setSelectedBrightness(widgetEvent.brightness);
});
+
return;
}
}
- }, []);
+ }, [ dimmerState ]);
CreateEventDispatcherHook(RoomWidgetUpdateDimmerEvent.PRESETS, eventDispatcher, onNitroEvent);
CreateEventDispatcherHook(RoomWidgetUpdateDimmerEvent.HIDE, eventDispatcher, onNitroEvent);
@@ -144,6 +137,8 @@ export const FurnitureDimmerView: FC<{}> = props =>
{
if((dimmerState === 0) && (lastDimmerState === 0)) return;
+ console.log('ye')
+
widgetHandler.processWidgetMessage(new RoomWidgetDimmerPreviewMessage(selectedColor, selectedBrightness, (selectedEffectId === 2)));
}, [ widgetHandler, dimmerState, lastDimmerState, selectedColor, selectedBrightness, selectedEffectId ]);
diff --git a/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.tsx b/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.tsx
index d7b60d69..33752c8f 100644
--- a/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.tsx
+++ b/src/views/room/widgets/furniture/manipulation-menu/FurnitureManipulationMenuView.tsx
@@ -1,36 +1,17 @@
import { RoomObjectOperationType } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
-import { ProcessRoomObjectOperation, RoomWidgetRoomObjectUpdateEvent } from '../../../../../api';
+import { ProcessRoomObjectOperation, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDecorateModeEvent } from '../../../../../api';
+import { BatchUpdates } from '../../../../../hooks';
import { CreateEventDispatcherHook } from '../../../../../hooks/events/event-dispatcher.base';
import { useRoomContext } from '../../../context/RoomContext';
import { ObjectLocationView } from '../../object-location/ObjectLocationView';
export const FurnitureManipulationMenuView: FC<{}> = props =>
{
- const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ isVisible, setIsVisible ] = useState(false);
const [ objectId, setObjectId ] = useState(-1);
const [ objectType, setObjectType ] = useState(-1);
-
- const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
- {
- switch(event.type)
- {
- case RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION: {
- setIsVisible(true);
- setObjectId(event.id);
- setObjectType(event.category);
- return;
- }
- case RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED: {
- return;
- }
- case RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED: {
- setIsVisible(false);
- return;
- }
- }
- }, []);
+ const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
const rotateFurniture = useCallback(() =>
{
@@ -42,22 +23,87 @@ export const FurnitureManipulationMenuView: FC<{}> = props =>
ProcessRoomObjectOperation(objectId, objectType, RoomObjectOperationType.OBJECT_MOVE);
}, [ objectId, objectType ]);
- useEffect(() =>
+ const pickupFurniture = useCallback(() =>
{
- if(!isVisible) return;
+ ProcessRoomObjectOperation(objectId, objectType, RoomObjectOperationType.OBJECT_PICKUP);
+ }, [ objectId, objectType ]);
- moveFurniture();
- }, [ isVisible, moveFurniture ]);
+ const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
+ {
+ switch(event.type)
+ {
+ case RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION: {
+ BatchUpdates(() =>
+ {
+ setIsVisible(true);
+ setObjectId(event.id);
+ setObjectType(event.category);
+ });
+ return;
+ }
+ case RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED: {
+ if(event.id === objectId)
+ {
+ BatchUpdates(() =>
+ {
+ setIsVisible(false);
+ setObjectId(-1);
+ setObjectType(-1);
+ });
+ }
+ return;
+ }
+ case RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED: {
+ BatchUpdates(() =>
+ {
+ setIsVisible(false);
+ setObjectId(-1);
+ setObjectType(-1);
+ });
+ return;
+ }
+ }
+ }, [ objectId ]);
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
+ const onRoomWidgetUpdateDecorateModeEvent = useCallback((event: RoomWidgetUpdateDecorateModeEvent) =>
+ {
+ if(event.isDecorating) return;
+
+ moveFurniture();
+
+ BatchUpdates(() =>
+ {
+ setIsVisible(false);
+ setObjectId(-1);
+ setObjectType(-1);
+ });
+ }, [ moveFurniture ]);
+
+ CreateEventDispatcherHook(RoomWidgetUpdateDecorateModeEvent.UPDATE_DECORATE, eventDispatcher, onRoomWidgetUpdateDecorateModeEvent);
+
+ useEffect(() =>
+ {
+ if(!isVisible)
+ {
+ eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(false));
+
+ return;
+ }
+
+ eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(true));
+
+ moveFurniture();
+ }, [ eventDispatcher, isVisible, moveFurniture ]);
+
if(!isVisible) return null;
return (
-
+
diff --git a/src/views/shared/avatar-image/AvatarImage.scss b/src/views/shared/avatar-image/AvatarImage.scss
index f85ca9c4..07022cae 100644
--- a/src/views/shared/avatar-image/AvatarImage.scss
+++ b/src/views/shared/avatar-image/AvatarImage.scss
@@ -3,7 +3,12 @@
width: 90px;
height: 130px;
background-repeat: no-repeat;
- background-position-x: center;
- background-position-y: -8px !important;
+ background-position: center -8px;
pointer-events: none;
+ image-rendering: pixelated;
+
+ &.scale-0-5,
+ &.scale-0-75 {
+ image-rendering: -webkit-optimize-contrast;
+ }
}
diff --git a/src/views/shared/avatar-image/AvatarImageView.tsx b/src/views/shared/avatar-image/AvatarImageView.tsx
index 5d2a2a33..94ffac65 100644
--- a/src/views/shared/avatar-image/AvatarImageView.tsx
+++ b/src/views/shared/avatar-image/AvatarImageView.tsx
@@ -1,5 +1,5 @@
import { AvatarScaleType, AvatarSetType } from '@nitrots/nitro-renderer';
-import { FC, useEffect, useRef, useState } from 'react';
+import { FC, useEffect, useMemo, useRef, useState } from 'react';
import { GetAvatarRenderManager } from '../../../api';
import { AvatarImageViewProps } from './AvatarImageView.types';
@@ -10,6 +10,19 @@ export const AvatarImageView: FC = props =>
const [ randomValue, setRandomValue ] = useState(-1);
const isDisposed = useRef(false);
+ const getScaleStyle = useMemo(() =>
+ {
+ if(scale === .5) return '0-5';
+
+ if(scale === .75) return '0-75';
+
+ if(scale === 1.25) return '1-25';
+
+ if(scale === 1.50) return '1-50';
+
+ return scale.toString();
+ }, [ scale ]);
+
useEffect(() =>
{
const avatarImage = GetAvatarRenderManager().createAvatarImage(figure, AvatarScaleType.LARGE, gender, {
@@ -50,5 +63,5 @@ export const AvatarImageView: FC = props =>
const url = `url('${ avatarUrl }')`;
- return ;
+ return ;
}
diff --git a/src/views/shared/badge-image/BadgeImage.scss b/src/views/shared/badge-image/BadgeImage.scss
index d7067045..b08e2de8 100644
--- a/src/views/shared/badge-image/BadgeImage.scss
+++ b/src/views/shared/badge-image/BadgeImage.scss
@@ -1,7 +1,7 @@
.badge-image {
position: relative;
- width: 100%;
- height: 100%;
+ width: 45px;
+ height: 45px;
background-repeat: no-repeat;
background-position: center;
diff --git a/src/views/shared/room-previewer/RoomPreviewerView.scss b/src/views/shared/room-previewer/RoomPreviewerView.scss
index 55328299..e6192624 100644
--- a/src/views/shared/room-previewer/RoomPreviewerView.scss
+++ b/src/views/shared/room-previewer/RoomPreviewerView.scss
@@ -12,7 +12,6 @@
background-color: $light;
background-repeat: no-repeat;
background-position: center;
- image-rendering: auto;
&.border-0 {
&::after {
diff --git a/src/views/shared/room-previewer/RoomPreviewerView.tsx b/src/views/shared/room-previewer/RoomPreviewerView.tsx
index d30bdb54..4691fd45 100644
--- a/src/views/shared/room-previewer/RoomPreviewerView.tsx
+++ b/src/views/shared/room-previewer/RoomPreviewerView.tsx
@@ -6,9 +6,7 @@ import { RoomPreviewerViewProps } from './RoomPreviewerView.types';
export const RoomPreviewerView: FC = props =>
{
const { roomPreviewer = null, height = 0 } = props;
-
const [ renderingCanvas, setRenderingCanvas ] = useState(null);
-
const elementRef = useRef();
const update = useCallback((time: number) =>
@@ -41,9 +39,6 @@ export const RoomPreviewerView: FC = props =>
const canvas = roomPreviewer.getRenderingCanvas();
- elementRef.current.style.width = `${ width }px`;
- elementRef.current.style.height = `${ height }px`;
-
setRenderingCanvas(canvas);
canvas.canvasUpdated = true;
@@ -59,34 +54,31 @@ export const RoomPreviewerView: FC = props =>
GetNitroInstance().ticker.add(update);
- function resize(): void
- {
- if(!roomPreviewer) return;
+ const resizeObserver = new ResizeObserver(() =>
+ {
+ if(!roomPreviewer || !elementRef.current) return;
- const width = elementRef.current.parentElement.offsetWidth;
+ const width = elementRef.current.parentElement.offsetWidth;
- elementRef.current.style.width = `${ width }px`;
- elementRef.current.style.height = `${ height }px`;
+ roomPreviewer.modifyRoomCanvas(width, height);
- roomPreviewer.modifyRoomCanvas(width, height);
-
- update(-1);
- }
-
- window.addEventListener('resize', resize);
+ update(-1);
+ });
+
+ resizeObserver.observe(elementRef.current);
return () =>
{
- GetNitroInstance().ticker.remove(update);
+ resizeObserver.disconnect();
- window.removeEventListener('resize', resize);
+ GetNitroInstance().ticker.remove(update);
}
}, [ renderingCanvas, roomPreviewer, elementRef, height, setupPreviewer, update ]);
return (
);
diff --git a/src/views/toolbar/ToolbarView.scss b/src/views/toolbar/ToolbarView.scss
index 44abb043..57401e81 100644
--- a/src/views/toolbar/ToolbarView.scss
+++ b/src/views/toolbar/ToolbarView.scss
@@ -29,31 +29,28 @@
align-items: center;
justify-content: center;
cursor: pointer;
- width: 50px;
- margin: 0 1px;
+ //margin: 0 1px;
position: relative;
- .toolbar-avatar {
- height: 50px;
+ &.item-avatar {
+ width: 50px;
+ height: 45px;
+ overflow: hidden;
.avatar-image {
margin-left: -5px;
- margin-top: -30px;
- }
-
- &:hover, &.active {
- height: 53px;
+ margin-top: 25px;
}
}
.icon,
- .toolbar-avatar {
+ &.item-avatar {
position: relative;
- transition: transform .2s ease-out;
+ //transition: transform .2s ease-out;
&:hover, &.active {
- -webkit-transform: translate(0, -3px);
- transform: translate(0, -3px);
+ -webkit-transform: translate(-1px, -1px);
+ transform: translate(-1px, -1px);
filter: drop-shadow(2px 2px 0 rgba($black, 0.8));
}
}
@@ -68,7 +65,7 @@
.count {
top: 0rem;
- right: 5px;
+ right: 2px;
font-size: 10px;
}
}
diff --git a/src/views/toolbar/ToolbarView.tsx b/src/views/toolbar/ToolbarView.tsx
index 74b22062..4d10456b 100644
--- a/src/views/toolbar/ToolbarView.tsx
+++ b/src/views/toolbar/ToolbarView.tsx
@@ -1,7 +1,7 @@
import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, UserProfileComposer, Wait } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
-import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop } from '../../api';
-import { AvatarEditorEvent, CatalogEvent, FriendListEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events';
+import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop, OpenMessengerChat } from '../../api';
+import { AvatarEditorEvent, CatalogEvent, FriendsEvent, FriendsMessengerIconEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events';
import { AchievementsUIEvent } from '../../events/achievements';
import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent';
import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent';
@@ -14,6 +14,10 @@ import { AvatarImageView } from '../shared/avatar-image/AvatarImageView';
import { ToolbarMeView } from './me/ToolbarMeView';
import { ToolbarViewItems, ToolbarViewProps } from './ToolbarView.types';
+const CHAT_ICON_HIDDEN: number = 0;
+const CHAT_ICON_SHOWING: number = 1;
+const CHAT_ICON_UNREAD: number = 2;
+
export const ToolbarView: FC = props =>
{
const { isInRoom } = props;
@@ -21,6 +25,7 @@ export const ToolbarView: FC = props =>
const [ userInfo, setUserInfo ] = useState(null);
const [ userFigure, setUserFigure ] = useState(null);
const [ isMeExpanded, setMeExpanded ] = useState(false);
+ const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN);
const [ unseenInventoryCount, setUnseenInventoryCount ] = useState(0);
const unseenFriendListCount = 0;
@@ -45,6 +50,13 @@ export const ToolbarView: FC = props =>
CreateMessageHook(FigureUpdateEvent, onUserFigureEvent);
+ const onFriendsMessengerIconEvent = useCallback((event: FriendsMessengerIconEvent) =>
+ {
+ setChatIconType(event.iconType);
+ }, []);
+
+ useUiEvent(FriendsMessengerIconEvent.UPDATE_ICON, onFriendsMessengerIconEvent);
+
const onUnseenItemTrackerUpdateEvent = useCallback((event: UnseenItemTrackerUpdateEvent) =>
{
setUnseenInventoryCount(event.count);
@@ -107,7 +119,7 @@ export const ToolbarView: FC = props =>
dispatchUiEvent(new CatalogEvent(CatalogEvent.TOGGLE_CATALOG));
return;
case ToolbarViewItems.FRIEND_LIST_ITEM:
- dispatchUiEvent(new CatalogEvent(FriendListEvent.TOGGLE_FRIEND_LIST));
+ dispatchUiEvent(new CatalogEvent(FriendsEvent.TOGGLE_FRIEND_LIST));
return;
case ToolbarViewItems.CAMERA_ITEM:
dispatchUiEvent(new RoomWidgetCameraEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA));
@@ -131,6 +143,9 @@ export const ToolbarView: FC = props =>
dispatchUiEvent(new UserSettingsUIEvent(UserSettingsUIEvent.TOGGLE_USER_SETTINGS));
setMeExpanded(false);
return;
+ case ToolbarViewItems.FRIEND_CHAT_ITEM:
+ OpenMessengerChat();
+ return;
}
}, []);
@@ -148,20 +163,16 @@ export const ToolbarView: FC = props =>
-
-
-
-
setMeExpanded(!isMeExpanded) }>
-
-
+
+
+
setMeExpanded(!isMeExpanded) }>
+
+ { (unseenAchievementsCount > 0) &&
+
{ unseenAchievementsCount }
}
- { (unseenAchievementsCount > 0) && (
-
{ unseenAchievementsCount }
) }
-
-
{ isInRoom && (
-
+
) }
{ !isInRoom && (
@@ -188,13 +199,20 @@ export const ToolbarView: FC = props =>
-
-
+
+
handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }>
{ (unseenFriendListCount > 0) && (
{ unseenFriendListCount }
) }
+ { ((chatIconType === CHAT_ICON_SHOWING) || (chatIconType === CHAT_ICON_UNREAD)) &&
+
handleToolbarItemClick(ToolbarViewItems.FRIEND_CHAT_ITEM) }>
+ { (chatIconType === CHAT_ICON_SHOWING) &&
}
+ { (chatIconType === CHAT_ICON_UNREAD) &&
}
+ { (unseenFriendListCount > 0) &&
+
{ unseenFriendListCount }
}
+
}
diff --git a/src/views/toolbar/ToolbarView.types.ts b/src/views/toolbar/ToolbarView.types.ts
index 0670bca7..48a376d1 100644
--- a/src/views/toolbar/ToolbarView.types.ts
+++ b/src/views/toolbar/ToolbarView.types.ts
@@ -9,6 +9,7 @@ export class ToolbarViewItems
public static INVENTORY_ITEM: string = 'TVI_INVENTORY_ITEM';
public static CATALOG_ITEM: string = 'TVI_CATALOG_ITEM';
public static FRIEND_LIST_ITEM: string = 'TVI_FRIEND_LIST_ITEM';
+ public static FRIEND_CHAT_ITEM: string = 'TVI_FRIEND_CHAT_ITEM';
public static CLOTHING_ITEM: string = 'TVI_CLOTHING_ITEM';
public static CAMERA_ITEM: string = 'TVI_CAMERA_ITEM';
public static MOD_TOOLS_ITEM: string = 'TVI_MOD_TOOLS_ITEM';
diff --git a/src/views/user-profile/views/badges-container/BadgesContainerView.tsx b/src/views/user-profile/views/badges-container/BadgesContainerView.tsx
index cba4e091..323e9254 100644
--- a/src/views/user-profile/views/badges-container/BadgesContainerView.tsx
+++ b/src/views/user-profile/views/badges-container/BadgesContainerView.tsx
@@ -1,4 +1,5 @@
import { FC } from 'react';
+import { NitroCardGridItemView, NitroCardGridView } from '../../../../layout';
import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView';
import { BadgesContainerViewProps } from './BadgesContainerView.types';
@@ -7,21 +8,36 @@ export const BadgesContainerView: FC
= props =>
const { badges = null } = props;
return (
-
-
-
- {
- badges.map( (badge, index) =>
-{
- return (
-
-
-
- )
- })
- }
-
-
+
+
+ { badges && (badges.length > 0) && badges.map((badge, index) =>
+ {
+ return (
+
+
+
+ )
+ }) }
+
- );
+ )
+
+// return (
+//
+//
+//
+// {
+// badges.map( (badge, index) =>
+// {
+// return (
+//
+//
+//
+// )
+// })
+// }
+//
+//
+//
+// );
}
diff --git a/tsconfig.json b/tsconfig.json
index df4dcf04..ac2a9fd7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -24,6 +24,6 @@
},
"include": [
"src",
- "node_modules/@nitrots/nitro-renderer/**/*.ts",
+ "node_modules/@nitrots/nitro-renderer/src/**/*.ts",
]
}