Update notification system

This commit is contained in:
Bill 2022-07-23 22:58:34 -04:00
parent 51db1f3aa3
commit 1461f43a6d
42 changed files with 569 additions and 675 deletions

View File

@ -1,27 +0,0 @@
import { NotificationUtilities } from '../notification';
import { LocalizeText } from '../utils';
import { TradingNotificationType } from './TradingNotificationType';
export const TradingNotificationMessage = (type: number, otherUsername: string = '') =>
{
switch(type)
{
case TradingNotificationType.ALERT_SCAM:
NotificationUtilities.simpleAlert(LocalizeText('inventory.trading.warning.other_not_offering'), null, null, null, LocalizeText('inventory.trading.notification.title'));
return;
case TradingNotificationType.HOTEL_TRADING_DISABLED:
case TradingNotificationType.YOU_NOT_ALLOWED:
case TradingNotificationType.THEY_NOT_ALLOWED:
case TradingNotificationType.ROOM_DISABLED:
case TradingNotificationType.YOU_OPEN:
case TradingNotificationType.THEY_OPEN:
NotificationUtilities.simpleAlert(LocalizeText(`inventory.trading.openfail.${ type }`, [ 'otherusername' ], [ otherUsername ]), null, null, null, LocalizeText('inventory.trading.openfail.title'));
return;
case TradingNotificationType.ERROR_WHILE_COMMIT:
NotificationUtilities.simpleAlert(`${ LocalizeText('inventory.trading.notification.caption') }, ${ LocalizeText('inventory.trading.notification.commiterror.info') }`, null, null, null, LocalizeText('inventory.trading.notification.title'));
return;
case TradingNotificationType.THEY_CANCELLED:
NotificationUtilities.simpleAlert(LocalizeText('inventory.trading.info.closed'), null, null, null, LocalizeText('inventory.trading.notification.title'));
return;
}
}

View File

@ -10,7 +10,6 @@ export * from './IUnseenItemTracker';
export * from './PetUtilities'; export * from './PetUtilities';
export * from './TradeState'; export * from './TradeState';
export * from './TradeUserData'; export * from './TradeUserData';
export * from './TradingNotificationMessage';
export * from './TradingNotificationType'; export * from './TradingNotificationType';
export * from './TradingUtilities'; export * from './TradingUtilities';
export * from './UnseenItemCategory'; export * from './UnseenItemCategory';

16
src/api/nitro/OpenUrl.ts Normal file
View File

@ -0,0 +1,16 @@
import { HabboWebTools } from '@nitrots/nitro-renderer';
import { CreateLinkEvent } from './CreateLinkEvent';
export const OpenUrl = (url: string) =>
{
if(!url || !url.length) return;
if(url.startsWith('http'))
{
HabboWebTools.openWebPage(url);
}
else
{
CreateLinkEvent(url);
}
}

View File

@ -10,6 +10,7 @@ export * from './GetConnection';
export * from './GetLocalization'; export * from './GetLocalization';
export * from './GetNitroInstance'; export * from './GetNitroInstance';
export * from './GetTicker'; export * from './GetTicker';
export * from './OpenUrl';
export * from './RemoveLinkEventTracker'; export * from './RemoveLinkEventTracker';
export * from './RemoveWorkerEventTracker'; export * from './RemoveWorkerEventTracker';
export * from './room'; export * from './room';

View File

@ -1,213 +0,0 @@
import { HabboWebTools, RoomEnterEffect } from '@nitrots/nitro-renderer';
import { NotificationAlertEvent, NotificationConfirmEvent } from '../../events';
import { NotificationBubbleEvent } from '../../events/notification-center/NotificationBubbleEvent';
import { DispatchUiEvent } from '../events';
import { CreateLinkEvent, GetConfiguration, GetNitroInstance } from '../nitro';
import { LocalizeText, PlaySound } from '../utils';
import { NotificationAlertType } from './NotificationAlertType';
import { NotificationBubbleType } from './NotificationBubbleType';
export class NotificationUtilities
{
private static MODERATION_DISCLAIMER_SHOWN: boolean = false;
private static MODERATION_DISCLAIMER_DELAY_MS: number = 5000;
private static MODERATION_DISCLAIMER_TIMEOUT: ReturnType<typeof setTimeout> = null;
public static BUBBLES_DISABLED: boolean = false;
private static cleanText(text: string): string
{
return text.replace(/\\r/g, '\r')
}
private static getTimeZeroPadded(time: number): string
{
const text = ('0' + time);
return text.substr((text.length - 2), text.length);
}
private static getMainNotificationConfig(): { [key: string]: { delivery?: string, display?: string; title?: string; image?: string }}
{
return GetConfiguration<{ [key: string]: { delivery?: string, display?: string; title?: string; image?: string }}>('notification', {});
}
private static getNotificationConfig(key: string): { delivery?: string, display?: string; title?: string; image?: string }
{
const mainConfig = this.getMainNotificationConfig();
if(!mainConfig) return null;
return mainConfig[key];
}
public static getNotificationPart(options: Map<string, string>, type: string, key: string, localize: boolean): string
{
if(options.has(key)) return options.get(key);
const localizeKey = [ 'notification', type, key ].join('.');
if(GetNitroInstance().localization.hasValue(localizeKey) || localize)
{
return LocalizeText(localizeKey, Array.from(options.keys()), Array.from(options.values()));
}
return null;
}
public static getNotificationImageUrl(options: Map<string, string>, type: string): string
{
let imageUrl = options.get('image');
if(!imageUrl) imageUrl = GetConfiguration<string>('image.library.notifications.url', '').replace('%image%', type.replace(/\./g, '_'));
return LocalizeText(imageUrl);
}
public static showNotification(type: string, options: Map<string, string> = null): void
{
if(!options) options = new Map();
const configuration = this.getNotificationConfig(('notification.' + type));
if(configuration) for(const key in configuration) options.set(key, configuration[key]);
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')
{
this.showSingleBubble(LocalizeText(message), NotificationBubbleType.INFO, image, linkUrl);
}
else
{
this.simpleAlert(message, type, linkUrl, linkTitle, title, image);
}
if(options.get('sound')) PlaySound(options.get('sound'));
}
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 showClubGiftNotification(numGifts: number): void
{
if(numGifts <= 0) return;
this.showSingleBubble(numGifts.toString(), NotificationBubbleType.CLUBGIFT, null, ('catalog/open/' + GetConfiguration('catalog.links')['hc.hc_gifts']));
}
public static handleMOTD(messages: string[]): void
{
messages = messages.map(message => this.cleanText(message));
DispatchUiEvent(new NotificationAlertEvent(messages, NotificationAlertType.MOTD, null, null, LocalizeText('notifications.motd.title')));
}
public static confirm(message: string, onConfirm: Function, onCancel: Function, confirmText: string = null, cancelText: string = null, title: string = null, type: string = null): void
{
if(!confirmText || !confirmText.length) confirmText = LocalizeText('generic.confirm');
if(!cancelText || !cancelText.length) cancelText = LocalizeText('generic.cancel');
if(!title || !title.length) title = LocalizeText('notifications.broadcast.title');
DispatchUiEvent(new NotificationConfirmEvent(type, this.cleanText(message), onConfirm, onCancel, confirmText, cancelText, title));
}
public static simpleAlert(message: string, type: string = null, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null): void
{
if(!title || !title.length) title = LocalizeText('notifications.broadcast.title');
if(!type || !type.length) type = NotificationAlertType.DEFAULT;
DispatchUiEvent(new NotificationAlertEvent([ this.cleanText(message) ], type, clickUrl, clickUrlText, title, imageUrl));
}
public static showNitroAlert(): void
{
DispatchUiEvent(new NotificationAlertEvent(null, NotificationAlertType.NITRO));
}
public static showModeratorMessage(message: string, url: string = null, showHabboWay: boolean = true): void
{
this.simpleAlert(message, NotificationAlertType.DEFAULT, 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
{
this.simpleAlert( LocalizeText(('opening.hours.' + (thrownOut ? 'disconnected' : 'closed')), [ 'h', 'm' ], [ this.getTimeZeroPadded(open), this.getTimeZeroPadded(minute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
}
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
{
if(!url || !url.length) return;
if(url.startsWith('http'))
{
HabboWebTools.openWebPage(url);
}
else
{
CreateLinkEvent(url);
}
}
public static showModerationDisclaimer(): void
{
if(RoomEnterEffect.isRunning())
{
if(this.MODERATION_DISCLAIMER_TIMEOUT) return;
this.MODERATION_DISCLAIMER_TIMEOUT = setTimeout(() =>
{
this.showModerationDisclaimer();
}, (RoomEnterEffect.totalRunningTime + this.MODERATION_DISCLAIMER_DELAY_MS));
}
else
{
if(this.MODERATION_DISCLAIMER_SHOWN) return;
this.showSingleBubble(LocalizeText('mod.chatdisclaimer'), NotificationBubbleType.INFO);
this.MODERATION_DISCLAIMER_SHOWN = true;
}
}
}

View File

@ -4,4 +4,3 @@ export * from './NotificationBubbleItem';
export * from './NotificationBubbleType'; export * from './NotificationBubbleType';
export * from './NotificationConfirmItem'; export * from './NotificationConfirmItem';
export * from './NotificationConfirmType'; export * from './NotificationConfirmType';
export * from './NotificationUtilities';

View File

@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { NitroRectangle, TextureUtils } from '@nitrots/nitro-renderer'; import { NitroRectangle, TextureUtils } from '@nitrots/nitro-renderer';
import { FC, useCallback, useRef } from 'react'; import { FC, useCallback, useRef } from 'react';
import { CameraPicture, GetRoomEngine, GetRoomSession, LocalizeText, NotificationUtilities, PlaySound, SoundNames } from '../../../api'; import { CameraPicture, GetRoomEngine, GetRoomSession, LocalizeText, PlaySound, SoundNames } from '../../../api';
import { Column, DraggableWindow, Flex } from '../../../common'; import { Column, DraggableWindow, Flex } from '../../../common';
import { useCamera } from '../../../hooks'; import { useCamera, useNotification } from '../../../hooks';
export interface CameraWidgetCaptureViewProps export interface CameraWidgetCaptureViewProps
{ {
@ -18,6 +18,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
{ {
const { onClose = null, onEdit = null, onDelete = null } = props; const { onClose = null, onEdit = null, onDelete = null } = props;
const { cameraRoll = null, setCameraRoll = null, selectedPictureIndex = -1, setSelectedPictureIndex = null } = useCamera(); const { cameraRoll = null, setCameraRoll = null, selectedPictureIndex = -1, setSelectedPictureIndex = null } = useCamera();
const { simpleAlert = null } = useNotification();
const elementRef = useRef<HTMLDivElement>(); const elementRef = useRef<HTMLDivElement>();
const selectedPicture = ((selectedPictureIndex > -1) ? cameraRoll[selectedPictureIndex] : null); const selectedPicture = ((selectedPictureIndex > -1) ? cameraRoll[selectedPictureIndex] : null);
@ -45,7 +46,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
if(clone.length >= CAMERA_ROLL_LIMIT) if(clone.length >= CAMERA_ROLL_LIMIT)
{ {
NotificationUtilities.simpleAlert(LocalizeText('camera.full.body')); simpleAlert(LocalizeText('camera.full.body'));
clone.pop(); clone.pop();
} }
@ -54,7 +55,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
clone.push(new CameraPicture(texture, TextureUtils.generateImageUrl(texture))); clone.push(new CameraPicture(texture, TextureUtils.generateImageUrl(texture)));
setCameraRoll(clone); setCameraRoll(clone);
}, [ cameraRoll, selectedPictureIndex, getCameraBounds, setCameraRoll, setSelectedPictureIndex ]); }, [ cameraRoll, selectedPictureIndex, getCameraBounds, setCameraRoll, setSelectedPictureIndex, simpleAlert ]);
return ( return (
<DraggableWindow uniqueKey="nitro-camera-capture"> <DraggableWindow uniqueKey="nitro-camera-capture">

View File

@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { RedeemVoucherMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent } from '@nitrots/nitro-renderer'; import { RedeemVoucherMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../api'; import { LocalizeText, SendMessageComposer } from '../../../../../api';
import { Button, Flex } from '../../../../../common'; import { Button, Flex } from '../../../../../common';
import { useMessageEvent } from '../../../../../hooks'; import { useMessageEvent, useNotification } from '../../../../../hooks';
export interface CatalogRedeemVoucherViewProps export interface CatalogRedeemVoucherViewProps
{ {
@ -15,6 +15,7 @@ export const CatalogRedeemVoucherView: FC<CatalogRedeemVoucherViewProps> = props
const { text = null } = props; const { text = null } = props;
const [ voucher, setVoucher ] = useState<string>(''); const [ voucher, setVoucher ] = useState<string>('');
const [ isWaiting, setIsWaiting ] = useState(false); const [ isWaiting, setIsWaiting ] = useState(false);
const { simpleAlert = null } = useNotification();
const redeemVoucher = () => const redeemVoucher = () =>
{ {
@ -33,11 +34,11 @@ export const CatalogRedeemVoucherView: FC<CatalogRedeemVoucherViewProps> = props
if(parser.productName) message = LocalizeText('catalog.alert.voucherredeem.ok.description.furni', [ 'productName', 'productDescription' ], [ parser.productName, parser.productDescription ]); if(parser.productName) message = LocalizeText('catalog.alert.voucherredeem.ok.description.furni', [ 'productName', 'productDescription' ], [ parser.productName, parser.productDescription ]);
NotificationUtilities.simpleAlert(message, null, null, null, LocalizeText('catalog.alert.voucherredeem.ok.title')); simpleAlert(message, null, null, null, LocalizeText('catalog.alert.voucherredeem.ok.title'));
setIsWaiting(false); setIsWaiting(false);
setVoucher(''); setVoucher('');
}, []); }, [ simpleAlert ]);
useMessageEvent(VoucherRedeemOkMessageEvent, onVoucherRedeemOkMessageEvent); useMessageEvent(VoucherRedeemOkMessageEvent, onVoucherRedeemOkMessageEvent);
@ -45,10 +46,10 @@ export const CatalogRedeemVoucherView: FC<CatalogRedeemVoucherViewProps> = props
{ {
const parser = event.getParser(); const parser = event.getParser();
NotificationUtilities.simpleAlert(LocalizeText(`catalog.alert.voucherredeem.error.description.${ parser.errorCode }`), null, null, null, LocalizeText('catalog.alert.voucherredeem.error.title')); simpleAlert(LocalizeText(`catalog.alert.voucherredeem.error.description.${ parser.errorCode }`), null, null, null, LocalizeText('catalog.alert.voucherredeem.error.title'));
setIsWaiting(false); setIsWaiting(false);
}, []); }, [ simpleAlert ]);
useMessageEvent(VoucherRedeemErrorMessageEvent, onVoucherRedeemErrorMessageEvent); useMessageEvent(VoucherRedeemErrorMessageEvent, onVoucherRedeemErrorMessageEvent);

View File

@ -1,8 +1,8 @@
import { CancelMarketplaceOfferMessageComposer, GetMarketplaceOwnOffersMessageComposer, MarketplaceCancelOfferResultEvent, MarketplaceOwnOffersEvent, RedeemMarketplaceOfferCreditsMessageComposer } from '@nitrots/nitro-renderer'; import { CancelMarketplaceOfferMessageComposer, GetMarketplaceOwnOffersMessageComposer, MarketplaceCancelOfferResultEvent, MarketplaceOwnOffersEvent, RedeemMarketplaceOfferCreditsMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../../../../../api'; import { LocalizeText, NotificationAlertType, SendMessageComposer } from '../../../../../../api';
import { Button, Column, Text } from '../../../../../../common'; import { Button, Column, Text } from '../../../../../../common';
import { useMessageEvent } from '../../../../../../hooks'; import { useMessageEvent, useNotification } from '../../../../../../hooks';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from '../CatalogLayout.types';
import { CatalogLayoutMarketplaceItemView, OWN_OFFER } from './CatalogLayoutMarketplaceItemView'; import { CatalogLayoutMarketplaceItemView, OWN_OFFER } from './CatalogLayoutMarketplaceItemView';
import { MarketplaceOfferData } from './common/MarketplaceOfferData'; import { MarketplaceOfferData } from './common/MarketplaceOfferData';
@ -12,6 +12,7 @@ export const CatalogLayoutMarketplaceOwnItemsView: FC<CatalogLayoutProps> = prop
{ {
const [ creditsWaiting, setCreditsWaiting ] = useState(0); const [ creditsWaiting, setCreditsWaiting ] = useState(0);
const [ offers, setOffers ] = useState<MarketplaceOfferData[]>([]); const [ offers, setOffers ] = useState<MarketplaceOfferData[]>([]);
const { simpleAlert = null } = useNotification();
const onMarketPlaceOwnOffersEvent = useCallback((event: MarketplaceOwnOffersEvent) => const onMarketPlaceOwnOffersEvent = useCallback((event: MarketplaceOwnOffersEvent) =>
{ {
@ -42,13 +43,13 @@ export const CatalogLayoutMarketplaceOwnItemsView: FC<CatalogLayoutProps> = prop
if(!parser.success) if(!parser.success)
{ {
NotificationUtilities.simpleAlert(LocalizeText('catalog.marketplace.cancel_failed'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.marketplace.operation_failed.topic')); simpleAlert(LocalizeText('catalog.marketplace.cancel_failed'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.marketplace.operation_failed.topic'));
return; return;
} }
setOffers(prevValue => prevValue.filter(value => (value.offerId !== parser.offerId))); setOffers(prevValue => prevValue.filter(value => (value.offerId !== parser.offerId)));
}, []); }, [ simpleAlert ]);
useMessageEvent(MarketplaceCancelOfferResultEvent, onMarketplaceCancelOfferResultEvent); useMessageEvent(MarketplaceCancelOfferResultEvent, onMarketplaceCancelOfferResultEvent);

View File

@ -1,8 +1,8 @@
import { BuyMarketplaceOfferMessageComposer, GetMarketplaceOffersMessageComposer, MarketplaceBuyOfferResultEvent, MarketPlaceOffersEvent } from '@nitrots/nitro-renderer'; import { BuyMarketplaceOfferMessageComposer, GetMarketplaceOffersMessageComposer, MarketplaceBuyOfferResultEvent, MarketPlaceOffersEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useMemo, useState } from 'react'; import { FC, useCallback, useMemo, useState } from 'react';
import { LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../../../../../api'; import { LocalizeText, NotificationAlertType, SendMessageComposer } from '../../../../../../api';
import { Button, ButtonGroup, Column, Text } from '../../../../../../common'; import { Button, ButtonGroup, Column, Text } from '../../../../../../common';
import { useMessageEvent, usePurse } from '../../../../../../hooks'; import { useMessageEvent, useNotification, usePurse } from '../../../../../../hooks';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from '../CatalogLayout.types';
import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView'; import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView';
import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView'; import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView';
@ -25,6 +25,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
const [ offers, setOffers ] = useState(new Map<number, MarketplaceOfferData>()); const [ offers, setOffers ] = useState(new Map<number, MarketplaceOfferData>());
const [ lastSearch, setLastSearch ] = useState<IMarketplaceSearchOptions>({ minPrice: -1, maxPrice: -1, query: '', type: 3 }); const [ lastSearch, setLastSearch ] = useState<IMarketplaceSearchOptions>({ minPrice: -1, maxPrice: -1, query: '', type: 3 });
const { getCurrencyAmount = null } = usePurse(); const { getCurrencyAmount = null } = usePurse();
const { simpleAlert = null, showConfirm = null } = useNotification();
const requestOffers = useCallback((options: IMarketplaceSearchOptions) => const requestOffers = useCallback((options: IMarketplaceSearchOptions) =>
{ {
@ -50,18 +51,18 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
{ {
if(offerData.price > getCurrencyAmount(-1)) if(offerData.price > getCurrencyAmount(-1))
{ {
NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.notenough.credits.description'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.alert.notenough.title')); simpleAlert(LocalizeText('catalog.alert.notenough.credits.description'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.alert.notenough.title'));
return; return;
} }
const offerId = offerData.offerId; const offerId = offerData.offerId;
NotificationUtilities.confirm(LocalizeText('catalog.marketplace.confirm_header'), () => showConfirm(LocalizeText('catalog.marketplace.confirm_header'), () =>
{ {
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(offerId)); SendMessageComposer(new BuyMarketplaceOfferMessageComposer(offerId));
}, },
null, null, null, LocalizeText('catalog.marketplace.confirm_title')); null, null, null, LocalizeText('catalog.marketplace.confirm_title'));
}, [ getCurrencyAmount ]); }, [ getCurrencyAmount, simpleAlert, showConfirm ]);
const onMarketPlaceOffersEvent = useCallback( (event: MarketPlaceOffersEvent) => const onMarketPlaceOffersEvent = useCallback( (event: MarketPlaceOffersEvent) =>
{ {
@ -99,7 +100,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
newVal.delete(parser.requestedOfferId); newVal.delete(parser.requestedOfferId);
return newVal; return newVal;
}); });
NotificationUtilities.simpleAlert(LocalizeText('catalog.marketplace.not_available_header'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.marketplace.not_available_title')); simpleAlert(LocalizeText('catalog.marketplace.not_available_header'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.marketplace.not_available_title'));
break; break;
case 3: case 3:
// our shit was updated // our shit was updated
@ -121,7 +122,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
return newVal; return newVal;
}); });
NotificationUtilities.confirm(LocalizeText('catalog.marketplace.confirm_higher_header') + showConfirm(LocalizeText('catalog.marketplace.confirm_higher_header') +
'\n' + LocalizeText('catalog.marketplace.confirm_price', [ 'price' ], [ parser.newPrice.toString() ]), () => '\n' + LocalizeText('catalog.marketplace.confirm_price', [ 'price' ], [ parser.newPrice.toString() ]), () =>
{ {
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(parser.offerId)); SendMessageComposer(new BuyMarketplaceOfferMessageComposer(parser.offerId));
@ -129,10 +130,10 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
null, null, null, LocalizeText('catalog.marketplace.confirm_higher_title')); null, null, null, LocalizeText('catalog.marketplace.confirm_higher_title'));
break; break;
case 4: case 4:
NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.notenough.credits.description'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.alert.notenough.title')); simpleAlert(LocalizeText('catalog.alert.notenough.credits.description'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.alert.notenough.title'));
break; break;
} }
}, [ lastSearch, requestOffers ]); }, [ lastSearch, requestOffers, simpleAlert, showConfirm ]);
useMessageEvent(MarketPlaceOffersEvent, onMarketPlaceOffersEvent); useMessageEvent(MarketPlaceOffersEvent, onMarketPlaceOffersEvent);
useMessageEvent(MarketplaceBuyOfferResultEvent, onMarketplaceBuyOfferResultEvent); useMessageEvent(MarketplaceBuyOfferResultEvent, onMarketplaceBuyOfferResultEvent);

View File

@ -1,9 +1,9 @@
import { GetMarketplaceConfigurationMessageComposer, MakeOfferMessageComposer, MarketplaceConfigurationEvent } from '@nitrots/nitro-renderer'; import { GetMarketplaceConfigurationMessageComposer, MakeOfferMessageComposer, MarketplaceConfigurationEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { FurnitureItem, LocalizeText, NotificationUtilities, ProductTypeEnum, SendMessageComposer } from '../../../../../../api'; import { FurnitureItem, LocalizeText, ProductTypeEnum, SendMessageComposer } from '../../../../../../api';
import { Base, Button, Column, Grid, LayoutFurniImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../../common'; import { Base, Button, Column, Grid, LayoutFurniImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../../../common';
import { CatalogPostMarketplaceOfferEvent } from '../../../../../../events'; import { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
import { useCatalog, useMessageEvent, useUiEvent } from '../../../../../../hooks'; import { useCatalog, useMessageEvent, useNotification, useUiEvent } from '../../../../../../hooks';
export const MarketplacePostOfferView : FC<{}> = props => export const MarketplacePostOfferView : FC<{}> = props =>
{ {
@ -11,6 +11,7 @@ export const MarketplacePostOfferView : FC<{}> = props =>
const [ askingPrice, setAskingPrice ] = useState(0); const [ askingPrice, setAskingPrice ] = useState(0);
const { catalogOptions = null, setCatalogOptions = null } = useCatalog(); const { catalogOptions = null, setCatalogOptions = null } = useCatalog();
const { marketplaceConfiguration = null } = catalogOptions; const { marketplaceConfiguration = null } = catalogOptions;
const { showConfirm = null } = useNotification();
const onMarketplaceConfigurationEvent = useCallback((event: MarketplaceConfigurationEvent) => const onMarketplaceConfigurationEvent = useCallback((event: MarketplaceConfigurationEvent) =>
{ {
@ -58,7 +59,7 @@ export const MarketplacePostOfferView : FC<{}> = props =>
{ {
if(!item || (askingPrice <= marketplaceConfiguration.minimumPrice)) return; if(!item || (askingPrice <= marketplaceConfiguration.minimumPrice)) return;
NotificationUtilities.confirm(LocalizeText('inventory.marketplace.confirm_offer.info', [ 'furniname', 'price' ], [ getFurniTitle, askingPrice.toString() ]), () => showConfirm(LocalizeText('inventory.marketplace.confirm_offer.info', [ 'furniname', 'price' ], [ getFurniTitle, askingPrice.toString() ]), () =>
{ {
SendMessageComposer(new MakeOfferMessageComposer(askingPrice, item.isWallItem ? 2 : 1, item.id)); SendMessageComposer(new MakeOfferMessageComposer(askingPrice, item.isWallItem ? 2 : 1, item.id));
setItem(null); setItem(null);

View File

@ -1,8 +1,8 @@
import { SelectClubGiftComposer } from '@nitrots/nitro-renderer'; import { SelectClubGiftComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../../api'; import { LocalizeText, SendMessageComposer } from '../../../../../../api';
import { AutoGrid, Text } from '../../../../../../common'; import { AutoGrid, Text } from '../../../../../../common';
import { useCatalog, usePurse } from '../../../../../../hooks'; import { useCatalog, useNotification, usePurse } from '../../../../../../hooks';
import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutProps } from '../CatalogLayout.types';
import { VipGiftItem } from './VipGiftItemView'; import { VipGiftItem } from './VipGiftItemView';
@ -11,6 +11,7 @@ export const CatalogLayoutVipGiftsView: FC<CatalogLayoutProps> = props =>
const { purse = null } = usePurse(); const { purse = null } = usePurse();
const { catalogOptions = null, setCatalogOptions = null } = useCatalog(); const { catalogOptions = null, setCatalogOptions = null } = useCatalog();
const { clubGifts = null } = catalogOptions; const { clubGifts = null } = catalogOptions;
const { showConfirm = null } = useNotification();
const giftsAvailable = useCallback(() => const giftsAvailable = useCallback(() =>
{ {
@ -27,7 +28,7 @@ export const CatalogLayoutVipGiftsView: FC<CatalogLayoutProps> = props =>
const selectGift = useCallback((localizationId: string) => const selectGift = useCallback((localizationId: string) =>
{ {
NotificationUtilities.confirm(LocalizeText('catalog.club_gift.confirm'), () => showConfirm(LocalizeText('catalog.club_gift.confirm'), () =>
{ {
SendMessageComposer(new SelectClubGiftComposer(localizationId)); SendMessageComposer(new SelectClubGiftComposer(localizationId));
@ -38,7 +39,7 @@ export const CatalogLayoutVipGiftsView: FC<CatalogLayoutProps> = props =>
return { ...prevValue }; return { ...prevValue };
}); });
}, null); }, null);
}, [ setCatalogOptions ]); }, [ setCatalogOptions, showConfirm ]);
return ( return (
<> <>

View File

@ -1,7 +1,8 @@
import { GroupInformationParser, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer'; import { GroupInformationParser, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { CatalogPageName, CreateLinkEvent, GetGroupManager, GetGroupMembers, GetSessionDataManager, GroupMembershipType, GroupType, LocalizeText, NotificationUtilities, SendMessageComposer, TryJoinGroup, TryVisitRoom } from '../../../api'; import { CatalogPageName, CreateLinkEvent, GetGroupManager, GetGroupMembers, GetSessionDataManager, GroupMembershipType, GroupType, LocalizeText, SendMessageComposer, TryJoinGroup, TryVisitRoom } from '../../../api';
import { Button, Column, Flex, Grid, GridProps, LayoutBadgeImageView, Text } from '../../../common'; import { Button, Column, Flex, Grid, GridProps, LayoutBadgeImageView, Text } from '../../../common';
import { useNotification } from '../../../hooks';
const STATES: string[] = [ 'regular', 'exclusive', 'private' ]; const STATES: string[] = [ 'regular', 'exclusive', 'private' ];
@ -15,6 +16,7 @@ interface GroupInformationViewProps extends GridProps
export const GroupInformationView: FC<GroupInformationViewProps> = props => export const GroupInformationView: FC<GroupInformationViewProps> = props =>
{ {
const { groupInformation = null, onClose = null, overflow = 'hidden', ...rest } = props; const { groupInformation = null, onClose = null, overflow = 'hidden', ...rest } = props;
const { showConfirm = null } = useNotification();
const isRealOwner = (groupInformation && (groupInformation.ownerName === GetSessionDataManager().userName)); const isRealOwner = (groupInformation && (groupInformation.ownerName === GetSessionDataManager().userName));
@ -22,7 +24,7 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
const leaveGroup = () => const leaveGroup = () =>
{ {
NotificationUtilities.confirm(LocalizeText('group.leaveconfirm.desc'), () => showConfirm(LocalizeText('group.leaveconfirm.desc'), () =>
{ {
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId)); SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));

View File

@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { GroupAdminGiveComposer, GroupAdminTakeComposer, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembersParser, GroupRank, GroupRemoveMemberComposer, ILinkEventTracker } from '@nitrots/nitro-renderer'; import { GroupAdminGiveComposer, GroupAdminTakeComposer, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembersParser, GroupRank, GroupRemoveMemberComposer, ILinkEventTracker } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { AddEventLinkTracker, GetSessionDataManager, GetUserProfile, LocalizeText, NotificationUtilities, RemoveLinkEventTracker, SendMessageComposer } from '../../../api'; import { AddEventLinkTracker, GetSessionDataManager, GetUserProfile, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../../api';
import { Base, Button, Column, Flex, Grid, LayoutAvatarImageView, LayoutBadgeImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../common'; import { Base, Button, Column, Flex, Grid, LayoutAvatarImageView, LayoutBadgeImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../common';
import { useMessageEvent } from '../../../hooks'; import { useMessageEvent, useNotification } from '../../../hooks';
export const GroupMembersView: FC<{}> = props => export const GroupMembersView: FC<{}> = props =>
{ {
@ -14,6 +14,7 @@ export const GroupMembersView: FC<{}> = props =>
const [ totalPages, setTotalPages ] = useState<number>(0); const [ totalPages, setTotalPages ] = useState<number>(0);
const [ searchQuery, setSearchQuery ] = useState<string>(''); const [ searchQuery, setSearchQuery ] = useState<string>('');
const [ removingMemberName, setRemovingMemberName ] = useState<string>(null); const [ removingMemberName, setRemovingMemberName ] = useState<string>(null);
const { showConfirm = null } = useNotification();
const getRankDescription = (member: GroupMemberParser) => const getRankDescription = (member: GroupMemberParser) =>
{ {
@ -87,7 +88,7 @@ export const GroupMembersView: FC<{}> = props =>
{ {
const parser = event.getParser(); const parser = event.getParser();
NotificationUtilities.confirm(LocalizeText(((parser.furnitureCount > 0) ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc'), [ 'user', 'amount' ], [ removingMemberName, parser.furnitureCount.toString() ]), () => showConfirm(LocalizeText(((parser.furnitureCount > 0) ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc'), [ 'user', 'amount' ], [ removingMemberName, parser.furnitureCount.toString() ]), () =>
{ {
SendMessageComposer(new GroupRemoveMemberComposer(membersData.groupId, parser.userId)); SendMessageComposer(new GroupRemoveMemberComposer(membersData.groupId, parser.userId));
@ -95,7 +96,7 @@ export const GroupMembersView: FC<{}> = props =>
}, null); }, null);
setRemovingMemberName(null); setRemovingMemberName(null);
}, [ membersData, removingMemberName, refreshMembers ]); }, [ membersData, removingMemberName, refreshMembers, showConfirm ]);
useMessageEvent(GroupConfirmMemberRemoveEvent, onGroupConfirmMemberRemoveEvent); useMessageEvent(GroupConfirmMemberRemoveEvent, onGroupConfirmMemberRemoveEvent);

View File

@ -1,15 +1,16 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { DesktopViewEvent, GetGuestRoomResultEvent, GroupInformationComposer, GroupInformationEvent, GroupInformationParser, GroupRemoveMemberComposer, HabboGroupDeactivatedMessageEvent, RoomEntryInfoMessageEvent } from '@nitrots/nitro-renderer'; import { DesktopViewEvent, GetGuestRoomResultEvent, GroupInformationComposer, GroupInformationEvent, GroupInformationParser, GroupRemoveMemberComposer, HabboGroupDeactivatedMessageEvent, RoomEntryInfoMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { GetGroupInformation, GetGroupManager, GetSessionDataManager, GroupMembershipType, GroupType, LocalizeText, NotificationUtilities, SendMessageComposer, TryJoinGroup } from '../../../api'; import { GetGroupInformation, GetGroupManager, GetSessionDataManager, GroupMembershipType, GroupType, LocalizeText, SendMessageComposer, TryJoinGroup } from '../../../api';
import { Base, Button, Column, Flex, LayoutBadgeImageView, Text } from '../../../common'; import { Base, Button, Column, Flex, LayoutBadgeImageView, Text } from '../../../common';
import { useMessageEvent } from '../../../hooks'; import { useMessageEvent, useNotification } from '../../../hooks';
export const GroupRoomInformationView: FC<{}> = props => export const GroupRoomInformationView: FC<{}> = props =>
{ {
const [ expectedGroupId, setExpectedGroupId ] = useState<number>(0); const [ expectedGroupId, setExpectedGroupId ] = useState<number>(0);
const [ groupInformation, setGroupInformation ] = useState<GroupInformationParser>(null); const [ groupInformation, setGroupInformation ] = useState<GroupInformationParser>(null);
const [ isOpen, setIsOpen ] = useState<boolean>(true); const [ isOpen, setIsOpen ] = useState<boolean>(true);
const { showConfirm = null } = useNotification();
const onDesktopViewEvent = useCallback((event: DesktopViewEvent) => const onDesktopViewEvent = useCallback((event: DesktopViewEvent) =>
{ {
@ -72,7 +73,7 @@ export const GroupRoomInformationView: FC<{}> = props =>
const leaveGroup = () => const leaveGroup = () =>
{ {
NotificationUtilities.confirm(LocalizeText('group.leaveconfirm.desc'), () => showConfirm(LocalizeText('group.leaveconfirm.desc'), () =>
{ {
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId)); SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
}, null); }, null);

View File

@ -1,7 +1,8 @@
import { GroupDeleteComposer, GroupSaveInformationComposer } from '@nitrots/nitro-renderer'; import { GroupDeleteComposer, GroupSaveInformationComposer } from '@nitrots/nitro-renderer';
import { Dispatch, FC, SetStateAction, useCallback, useEffect, useState } from 'react'; import { Dispatch, FC, SetStateAction, useCallback, useEffect, useState } from 'react';
import { CreateLinkEvent, IGroupData, LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../api'; import { CreateLinkEvent, IGroupData, LocalizeText, SendMessageComposer } from '../../../../api';
import { Base, Button, Column, Flex, Text } from '../../../../common'; import { Base, Button, Column, Flex, Text } from '../../../../common';
import { useNotification } from '../../../../hooks';
interface GroupTabIdentityViewProps interface GroupTabIdentityViewProps
{ {
@ -19,12 +20,13 @@ export const GroupTabIdentityView: FC<GroupTabIdentityViewProps> = props =>
const [ groupName, setGroupName ] = useState<string>(''); const [ groupName, setGroupName ] = useState<string>('');
const [ groupDescription, setGroupDescription ] = useState<string>(''); const [ groupDescription, setGroupDescription ] = useState<string>('');
const [ groupHomeroomId, setGroupHomeroomId ] = useState<number>(-1); const [ groupHomeroomId, setGroupHomeroomId ] = useState<number>(-1);
const { showConfirm = null } = useNotification();
const deleteGroup = () => const deleteGroup = () =>
{ {
if(!groupData || (groupData.groupId <= 0)) return; if(!groupData || (groupData.groupId <= 0)) return;
NotificationUtilities.confirm(LocalizeText('group.deleteconfirm.desc'), () => showConfirm(LocalizeText('group.deleteconfirm.desc'), () =>
{ {
SendMessageComposer(new GroupDeleteComposer(groupData.groupId)); SendMessageComposer(new GroupDeleteComposer(groupData.groupId));

View File

@ -1,11 +1,13 @@
import { CallForHelpResultMessageEvent, GetPendingCallsForHelpMessageComposer, IssueCloseNotificationMessageEvent } from '@nitrots/nitro-renderer'; import { CallForHelpResultMessageEvent, GetPendingCallsForHelpMessageComposer, IssueCloseNotificationMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC } from 'react';
import { CallForHelpResult, GetCloseReasonKey, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../api'; import { CallForHelpResult, GetCloseReasonKey, LocalizeText, NotificationAlertType, SendMessageComposer } from '../../api';
import { useMessageEvent } from '../../hooks'; import { useMessageEvent, useNotification } from '../../hooks';
export const HelpMessageHandler: FC<{}> = props => export const HelpMessageHandler: FC<{}> = props =>
{ {
const onCallForHelpResultMessageEvent = useCallback((event: CallForHelpResultMessageEvent) => const { simpleAlert = null } = useNotification();
useMessageEvent<CallForHelpResultMessageEvent>(CallForHelpResultMessageEvent, event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -15,32 +17,29 @@ export const HelpMessageHandler: FC<{}> = props =>
{ {
case CallForHelpResult.TOO_MANY_PENDING_CALLS_CODE: case CallForHelpResult.TOO_MANY_PENDING_CALLS_CODE:
SendMessageComposer(new GetPendingCallsForHelpMessageComposer()); SendMessageComposer(new GetPendingCallsForHelpMessageComposer());
NotificationUtilities.simpleAlert(LocalizeText('help.cfh.error.pending'), NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.error.title')); simpleAlert(LocalizeText('help.cfh.error.pending'), NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.error.title'));
break; break;
case CallForHelpResult.HAS_ABUSIVE_CALL_CODE: case CallForHelpResult.HAS_ABUSIVE_CALL_CODE:
NotificationUtilities.simpleAlert(LocalizeText('help.cfh.error.abusive'), NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.error.title')); simpleAlert(LocalizeText('help.cfh.error.abusive'), NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.error.title'));
break; break;
default: default:
if(message.trim().length === 0) if(message.trim().length === 0)
{ {
message = LocalizeText('help.cfh.sent.text'); message = LocalizeText('help.cfh.sent.text');
} }
NotificationUtilities.simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.sent.title'));
simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.sent.title'));
} }
}, []); });
useMessageEvent(CallForHelpResultMessageEvent, onCallForHelpResultMessageEvent); useMessageEvent<IssueCloseNotificationMessageEvent>(IssueCloseNotificationMessageEvent, event =>
const onIssueCloseNotificationMessageEvent = useCallback((event: IssueCloseNotificationMessageEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
const message = parser.messageText.length === 0 ? LocalizeText('help.cfh.closed.' + GetCloseReasonKey(parser.closeReason)) : parser.messageText; const message = parser.messageText.length === 0 ? LocalizeText('help.cfh.closed.' + GetCloseReasonKey(parser.closeReason)) : parser.messageText;
NotificationUtilities.simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('mod.alert.title')); simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('mod.alert.title'));
}, []); });
useMessageEvent(IssueCloseNotificationMessageEvent, onIssueCloseNotificationMessageEvent);
return null; return null;
} }

View File

@ -1,6 +1,6 @@
import { GetPromoArticlesComposer, PromoArticleData, PromoArticlesMessageEvent } from '@nitrots/nitro-renderer'; import { GetPromoArticlesComposer, PromoArticleData, PromoArticlesMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../api'; import { LocalizeText, OpenUrl, SendMessageComposer } from '../../../../../api';
import { useMessageEvent } from '../../../../../hooks'; import { useMessageEvent } from '../../../../../hooks';
export const PromoArticleWidgetView: FC<{}> = props => export const PromoArticleWidgetView: FC<{}> = props =>
@ -40,7 +40,7 @@ export const PromoArticleWidgetView: FC<{}> = props =>
<div className="col-3 d-flex flex-column h-100"> <div className="col-3 d-flex flex-column h-100">
<h3 className="my-0">{ articles[index].title }</h3> <h3 className="my-0">{ articles[index].title }</h3>
<b>{ articles[index].bodyText }</b> <b>{ articles[index].bodyText }</b>
<button className="btn btn-sm mt-auto btn-gainsboro" onClick={ event => NotificationUtilities.openUrl(articles[index].linkContent) }>{ articles[index].buttonText }</button> <button className="btn btn-sm mt-auto btn-gainsboro" onClick={ event => OpenUrl(articles[index].linkContent) }>{ articles[index].buttonText }</button>
</div> </div>
</div> } </div> }
</div> </div>

View File

@ -1,5 +1,5 @@
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { GetConfigurationManager, LocalizeText, NotificationUtilities } from '../../../../../api'; import { GetConfigurationManager, LocalizeText, OpenUrl } from '../../../../../api';
export interface WidgetContainerViewProps export interface WidgetContainerViewProps
{ {
@ -31,7 +31,7 @@ export const WidgetContainerView: FC<WidgetContainerViewProps> = props =>
<div className="d-flex flex-column align-self-center"> <div className="d-flex flex-column align-self-center">
<h3 className="my-0">{ LocalizeText(`landing.view.${ getOption('texts') }.header`) }</h3> <h3 className="my-0">{ LocalizeText(`landing.view.${ getOption('texts') }.header`) }</h3>
<i>{ LocalizeText(`landing.view.${ getOption('texts') }.body`) }</i> <i>{ LocalizeText(`landing.view.${ getOption('texts') }.body`) }</i>
<button className="btn btn-sm btn-gainsboro align-self-start px-3 mt-auto" onClick={ event => NotificationUtilities.openUrl(getOption('btnLink')) }>{ LocalizeText(`landing.view.${ getOption('texts') }.button`) }</button> <button className="btn btn-sm btn-gainsboro align-self-start px-3 mt-auto" onClick={ event => OpenUrl(getOption('btnLink')) }>{ LocalizeText(`landing.view.${ getOption('texts') }.button`) }</button>
</div> </div>
</div> </div>
); );

View File

@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer'; import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { FurniCategory, getGuildFurniType, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../../api'; import { FurniCategory, getGuildFurniType, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, SendMessageComposer, TradeState } from '../../../../api';
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common'; import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
import { useInventoryTrade } from '../../../../hooks'; import { useInventoryTrade, useNotification } from '../../../../hooks';
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView'; import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
interface InventoryTradeViewProps interface InventoryTradeViewProps
@ -22,6 +22,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null); const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
const [ countdownTick, setCountdownTick ] = useState(3); const [ countdownTick, setCountdownTick ] = useState(3);
const { ownUser = null, otherUser = null, groupItems = [], tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useInventoryTrade(); const { ownUser = null, otherUser = null, groupItems = [], tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useInventoryTrade();
const { simpleAlert = null } = useNotification();
const canTradeItem = (isWallItem: boolean, spriteId: number, category: number, groupable: boolean, stuffData: IObjectData) => const canTradeItem = (isWallItem: boolean, spriteId: number, category: number, groupable: boolean, stuffData: IObjectData) =>
{ {
@ -105,7 +106,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
} }
else else
{ {
NotificationUtilities.simpleAlert(LocalizeText('trading.items.too_many_items.desc'), NotificationAlertType.DEFAULT, null, null, LocalizeText('trading.items.too_many_items.title')); simpleAlert(LocalizeText('trading.items.too_many_items.desc'), NotificationAlertType.DEFAULT, null, null, LocalizeText('trading.items.too_many_items.title'));
} }
} }

View File

@ -1,5 +1,4 @@
import { FC, useEffect } from 'react'; import { FC } from 'react';
import { NotificationUtilities } from '../../api';
import { Base, Column, LayoutProgressBar, Text } from '../../common'; import { Base, Column, LayoutProgressBar, Text } from '../../common';
interface LoadingViewProps interface LoadingViewProps
@ -13,13 +12,6 @@ export const LoadingView: FC<LoadingViewProps> = props =>
{ {
const { isError = false, message = '', percent = 0 } = props; const { isError = false, message = '', percent = 0 } = props;
useEffect(() =>
{
if(!isError) return;
NotificationUtilities.simpleAlert(message, null, null, null, 'Connection Error');
}, [ isError, message ]);
return ( return (
<Column fullHeight position="relative" className="nitro-loading"> <Column fullHeight position="relative" className="nitro-loading">
<Base fullHeight className="container h-100"> <Base fullHeight className="container h-100">

View File

@ -1,8 +1,8 @@
import { CfhSanctionMessageEvent, CfhTopicsInitEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ModeratorActionResultMessageEvent, ModeratorInitMessageEvent, ModeratorToolPreferencesEvent, RoomEngineEvent } from '@nitrots/nitro-renderer'; import { CfhSanctionMessageEvent, CfhTopicsInitEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ModeratorActionResultMessageEvent, ModeratorInitMessageEvent, ModeratorToolPreferencesEvent, RoomEngineEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { NotificationAlertType, NotificationUtilities, PlaySound, SoundNames } from '../../api'; import { NotificationAlertType, PlaySound, SoundNames } from '../../api';
import { ModToolsEvent, ModToolsOpenRoomChatlogEvent, ModToolsOpenRoomInfoEvent, ModToolsOpenUserChatlogEvent, ModToolsOpenUserInfoEvent } from '../../events'; import { ModToolsEvent, ModToolsOpenRoomChatlogEvent, ModToolsOpenRoomInfoEvent, ModToolsOpenUserChatlogEvent, ModToolsOpenUserInfoEvent } from '../../events';
import { useMessageEvent, useRoomEngineEvent, useUiEvent } from '../../hooks'; import { useMessageEvent, useNotification, useRoomEngineEvent, useUiEvent } from '../../hooks';
import { SetCfhCategories } from './common/GetCFHCategories'; import { SetCfhCategories } from './common/GetCFHCategories';
import { useModToolsContext } from './ModToolsContext'; import { useModToolsContext } from './ModToolsContext';
import { ModToolsActions } from './reducers/ModToolsReducer'; import { ModToolsActions } from './reducers/ModToolsReducer';
@ -11,6 +11,7 @@ export const ModToolsMessageHandler: FC<{}> = props =>
{ {
const { modToolsState = null, dispatchModToolsState = null } = useModToolsContext(); const { modToolsState = null, dispatchModToolsState = null } = useModToolsContext();
const { openRooms = null, openRoomChatlogs = null, openUserChatlogs = null, openUserInfo = null, tickets= null } = modToolsState; const { openRooms = null, openRoomChatlogs = null, openUserChatlogs = null, openUserInfo = null, tickets= null } = modToolsState;
const { simpleAlert = null } = useNotification();
const onModeratorInitMessageEvent = useCallback((event: ModeratorInitMessageEvent) => const onModeratorInitMessageEvent = useCallback((event: ModeratorInitMessageEvent) =>
{ {
@ -78,8 +79,8 @@ export const ModToolsMessageHandler: FC<{}> = props =>
if(!parser) return; if(!parser) return;
NotificationUtilities.simpleAlert('Failed to pick issue', NotificationAlertType.DEFAULT, null, null, 'Error') simpleAlert('Failed to pick issue', NotificationAlertType.DEFAULT, null, null, 'Error')
}, []); }, [ simpleAlert ]);
const onIssueDeletedMessageEvent = useCallback((event: IssueDeletedMessageEvent) => const onIssueDeletedMessageEvent = useCallback((event: IssueDeletedMessageEvent) =>
{ {
@ -110,13 +111,13 @@ export const ModToolsMessageHandler: FC<{}> = props =>
if(parser.success) if(parser.success)
{ {
NotificationUtilities.simpleAlert('Moderation action was successfull', NotificationAlertType.MODERATION, null, null, 'Success'); simpleAlert('Moderation action was successfull', NotificationAlertType.MODERATION, null, null, 'Success');
} }
else else
{ {
NotificationUtilities.simpleAlert('There was a problem applying tht moderation action', NotificationAlertType.MODERATION, null, null, 'Error'); simpleAlert('There was a problem applying tht moderation action', NotificationAlertType.MODERATION, null, null, 'Error');
} }
}, []); }, [ simpleAlert ]);
const onCfhTopicsInitEvent = useCallback((event: CfhTopicsInitEvent) => const onCfhTopicsInitEvent = useCallback((event: CfhTopicsInitEvent) =>
{ {

View File

@ -1,7 +1,8 @@
import { CallForHelpTopicData, DefaultSanctionMessageComposer, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModTradingLockMessageComposer } from '@nitrots/nitro-renderer'; import { CallForHelpTopicData, DefaultSanctionMessageComposer, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModTradingLockMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useMemo, useState } from 'react'; import { FC, useMemo, useState } from 'react';
import { LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../../../api'; import { LocalizeText, NotificationAlertType, SendMessageComposer } from '../../../../api';
import { Button, Column, DraggableWindowPosition, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common'; import { Button, Column, DraggableWindowPosition, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
import { useNotification } from '../../../../hooks';
import { ISelectedUser } from '../../common/ISelectedUser'; import { ISelectedUser } from '../../common/ISelectedUser';
import { ModActionDefinition } from '../../common/ModActionDefinition'; import { ModActionDefinition } from '../../common/ModActionDefinition';
import { useModToolsContext } from '../../ModToolsContext'; import { useModToolsContext } from '../../ModToolsContext';
@ -35,6 +36,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
const [ message, setMessage ] = useState<string>(''); const [ message, setMessage ] = useState<string>('');
const { modToolsState = null } = useModToolsContext(); const { modToolsState = null } = useModToolsContext();
const { cfhCategories = null, settings = null } = modToolsState; const { cfhCategories = null, settings = null } = modToolsState;
const { simpleAlert = null } = useNotification();
const topics = useMemo(() => const topics = useMemo(() =>
{ {
@ -53,7 +55,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
const sendAlert = (message: string) => const sendAlert = (message: string) =>
{ {
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, 'Error'); simpleAlert(message, NotificationAlertType.DEFAULT, null, null, 'Error');
} }
const sendDefaultSanction = () => const sendDefaultSanction = () =>

View File

@ -1,12 +1,13 @@
import { CanCreateRoomEventEvent, CantConnectMessageParser, DoorbellMessageEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, HabboWebTools, LegacyExternalInterface, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchEvent, RoomDataParser, RoomDoorbellAcceptedEvent, RoomEnterErrorEvent, RoomEntryInfoMessageEvent, RoomForwardEvent, RoomScoreEvent, RoomSettingsUpdatedEvent, SecurityLevel, UserEventCatsEvent, UserFlatCatsEvent, UserInfoEvent, UserPermissionsEvent } from '@nitrots/nitro-renderer'; import { CanCreateRoomEventEvent, CantConnectMessageParser, DoorbellMessageEvent, FlatAccessDeniedMessageEvent, FlatCreatedEvent, FollowFriendMessageComposer, GenericErrorEvent, GetGuestRoomMessageComposer, GetGuestRoomResultEvent, GetUserEventCatsMessageComposer, GetUserFlatCatsMessageComposer, HabboWebTools, LegacyExternalInterface, NavigatorHomeRoomEvent, NavigatorMetadataEvent, NavigatorOpenRoomCreatorEvent, NavigatorSearchEvent, RoomDataParser, RoomDoorbellAcceptedEvent, RoomEnterErrorEvent, RoomEntryInfoMessageEvent, RoomForwardEvent, RoomScoreEvent, RoomSettingsUpdatedEvent, SecurityLevel, UserEventCatsEvent, UserFlatCatsEvent, UserInfoEvent, UserPermissionsEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api'; import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api';
import { useMessageEvent } from '../../hooks'; import { useMessageEvent, useNotification } from '../../hooks';
import { useNavigatorContext } from './NavigatorContext'; import { useNavigatorContext } from './NavigatorContext';
export const NavigatorMessageHandler: FC<{}> = props => export const NavigatorMessageHandler: FC<{}> = props =>
{ {
const { setCategories = null, setEventCategories = null, setTopLevelContext = null, topLevelContexts = null, setTopLevelContexts = null, setNavigatorData = null, setDoorData = null, setSearchResult = null } = useNavigatorContext(); const { setCategories = null, setEventCategories = null, setTopLevelContext = null, topLevelContexts = null, setTopLevelContexts = null, setNavigatorData = null, setDoorData = null, setSearchResult = null } = useNavigatorContext();
const { simpleAlert = null } = useNotification();
const onRoomSettingsUpdatedEvent = useCallback((event: RoomSettingsUpdatedEvent) => const onRoomSettingsUpdatedEvent = useCallback((event: RoomSettingsUpdatedEvent) =>
{ {
@ -28,8 +29,8 @@ export const NavigatorMessageHandler: FC<{}> = props =>
return; return;
} }
NotificationUtilities.simpleAlert(LocalizeText(`navigator.cannotcreateevent.error.${ parser.errorCode }`), null, null, null, LocalizeText('navigator.cannotcreateevent.title')); simpleAlert(LocalizeText(`navigator.cannotcreateevent.error.${ parser.errorCode }`), null, null, null, LocalizeText('navigator.cannotcreateevent.title'));
}, []); }, [ simpleAlert ]);
useMessageEvent(CanCreateRoomEventEvent, onCanCreateRoomEventEvent); useMessageEvent(CanCreateRoomEventEvent, onCanCreateRoomEventEvent);
@ -249,23 +250,23 @@ export const NavigatorMessageHandler: FC<{}> = props =>
}); });
return; return;
case 4009: case 4009:
NotificationUtilities.simpleAlert(LocalizeText('navigator.alert.need.to.be.vip'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title')); simpleAlert(LocalizeText('navigator.alert.need.to.be.vip'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
return; return;
case 4010: case 4010:
NotificationUtilities.simpleAlert(LocalizeText('navigator.alert.invalid_room_name'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title')); simpleAlert(LocalizeText('navigator.alert.invalid_room_name'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
return; return;
case 4011: case 4011:
NotificationUtilities.simpleAlert(LocalizeText('navigator.alert.cannot_perm_ban'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title')); simpleAlert(LocalizeText('navigator.alert.cannot_perm_ban'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
return; return;
case 4013: case 4013:
NotificationUtilities.simpleAlert(LocalizeText('navigator.alert.room_in_maintenance'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title')); simpleAlert(LocalizeText('navigator.alert.room_in_maintenance'), NotificationAlertType.DEFAULT, null, null, LocalizeText('generic.alert.title'));
return; return;
} }
}, [ setDoorData ]); }, [ setDoorData, simpleAlert ]);
const onNavigatorMetadataEvent = useCallback((event: NavigatorMetadataEvent) => const onNavigatorMetadataEvent = useCallback((event: NavigatorMetadataEvent) =>
{ {
@ -397,25 +398,25 @@ export const NavigatorMessageHandler: FC<{}> = props =>
switch(parser.reason) switch(parser.reason)
{ {
case CantConnectMessageParser.REASON_FULL: case CantConnectMessageParser.REASON_FULL:
NotificationUtilities.simpleAlert(LocalizeText('navigator.guestroomfull.text'), NotificationAlertType.DEFAULT, null, null, LocalizeText('navigator.guestroomfull.title')); simpleAlert(LocalizeText('navigator.guestroomfull.text'), NotificationAlertType.DEFAULT, null, null, LocalizeText('navigator.guestroomfull.title'));
break; break;
case CantConnectMessageParser.REASON_QUEUE_ERROR: case CantConnectMessageParser.REASON_QUEUE_ERROR:
NotificationUtilities.simpleAlert(LocalizeText(`room.queue.error.${ parser.parameter }`), NotificationAlertType.DEFAULT, null, null, LocalizeText('room.queue.error.title')); simpleAlert(LocalizeText(`room.queue.error.${ parser.parameter }`), NotificationAlertType.DEFAULT, null, null, LocalizeText('room.queue.error.title'));
break; break;
case CantConnectMessageParser.REASON_BANNED: case CantConnectMessageParser.REASON_BANNED:
NotificationUtilities.simpleAlert(LocalizeText('navigator.banned.text'), NotificationAlertType.DEFAULT, null, null, LocalizeText('navigator.banned.title')); simpleAlert(LocalizeText('navigator.banned.text'), NotificationAlertType.DEFAULT, null, null, LocalizeText('navigator.banned.title'));
break; break;
default: default:
NotificationUtilities.simpleAlert(LocalizeText('room.queue.error.title'), NotificationAlertType.DEFAULT, null, null, LocalizeText('room.queue.error.title')); simpleAlert(LocalizeText('room.queue.error.title'), NotificationAlertType.DEFAULT, null, null, LocalizeText('room.queue.error.title'));
break; break;
} }
VisitDesktop(); VisitDesktop();
}, []); }, [ simpleAlert ]);
const onRoomCreatorEvent = useCallback((event: NavigatorOpenRoomCreatorEvent) => const onRoomCreatorEvent = useCallback((event: NavigatorOpenRoomCreatorEvent) =>
{ {

View File

@ -1,8 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { RoomDeleteComposer } from '@nitrots/nitro-renderer'; import { RoomDeleteComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { CreateLinkEvent, GetMaxVisitorsList, IRoomData, LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../api'; import { CreateLinkEvent, GetMaxVisitorsList, IRoomData, LocalizeText, SendMessageComposer } from '../../../../api';
import { Base, Column, Flex, Text } from '../../../../common'; import { Base, Column, Flex, Text } from '../../../../common';
import { useNotification } from '../../../../hooks';
import { useNavigatorContext } from '../../NavigatorContext'; import { useNavigatorContext } from '../../NavigatorContext';
const ROOM_NAME_MIN_LENGTH = 3; const ROOM_NAME_MIN_LENGTH = 3;
@ -22,11 +23,12 @@ export const NavigatorRoomSettingsBasicTabView: FC<NavigatorRoomSettingsTabViewP
const { roomData = null, handleChange = null, close = null } = props; const { roomData = null, handleChange = null, close = null } = props;
const [ roomName, setRoomName ] = useState<string>(''); const [ roomName, setRoomName ] = useState<string>('');
const [ roomDescription, setRoomDescription ] = useState<string>(''); const [ roomDescription, setRoomDescription ] = useState<string>('');
const { showConfirm = null } = useNotification();
const { categories = null } = useNavigatorContext(); const { categories = null } = useNavigatorContext();
const deleteRoom = () => const deleteRoom = () =>
{ {
NotificationUtilities.confirm(LocalizeText('navigator.roomsettings.deleteroom.confirm.message', [ 'room_name' ], [ roomData.roomName ] ), () => showConfirm(LocalizeText('navigator.roomsettings.deleteroom.confirm.message', [ 'room_name' ], [ roomData.roomName ] ), () =>
{ {
SendMessageComposer(new RoomDeleteComposer(roomData.roomId)); SendMessageComposer(new RoomDeleteComposer(roomData.roomId));

View File

@ -1,6 +1,6 @@
import { NitroLogger } from '@nitrots/nitro-renderer'; import { NitroLogger } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { AddEventLinkTracker, GetConfiguration, NotificationUtilities, RemoveLinkEventTracker } from '../../api'; import { AddEventLinkTracker, GetConfiguration, OpenUrl, RemoveLinkEventTracker } from '../../api';
import { Base, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common'; import { Base, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
const NEW_LINE_REGEX = /\n\r|\n|\r/mg; const NEW_LINE_REGEX = /\n\r|\n|\r/mg;
@ -80,7 +80,7 @@ export const NitropediaView: FC<{}> = props =>
if(!link || !link.length) return; if(!link || !link.length) return;
NotificationUtilities.openUrl(link); OpenUrl(link);
} }
document.addEventListener('click', handle); document.addEventListener('click', handle);

View File

@ -1,215 +0,0 @@
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 { GetConfiguration, GetRoomEngine, GetSessionDataManager, LocalizeBadgeName, LocalizeText, NotificationBubbleType, NotificationUtilities, ProductImageUtility } from '../../api';
import { useMessageEvent } from '../../hooks';
export const NotificationCenterMessageHandler: FC<{}> = props =>
{
const onRespectReceivedEvent = useCallback((event: RespectReceivedEvent) =>
{
const parser = event.getParser();
if(parser.userId !== GetSessionDataManager().userId) return;
const text1 = LocalizeText('notifications.text.respect.1');
const text2 = LocalizeText('notifications.text.respect.2', [ 'count' ], [ parser.respectsReceived.toString() ]);
NotificationUtilities.showSingleBubble(text1, NotificationBubbleType.RESPECT);
NotificationUtilities.showSingleBubble(text2, NotificationBubbleType.RESPECT);
}, []);
useMessageEvent(RespectReceivedEvent, onRespectReceivedEvent);
const onHabboBroadcastMessageEvent = useCallback((event: HabboBroadcastMessageEvent) =>
{
const parser = event.getParser();
NotificationUtilities.simpleAlert(parser.message.replace(/\\r/g, '\r'), null, null, LocalizeText('notifications.broadcast.title'));
}, []);
useMessageEvent(HabboBroadcastMessageEvent, onHabboBroadcastMessageEvent);
const onAchievementNotificationMessageEvent = useCallback((event: AchievementNotificationMessageEvent) =>
{
const parser = event.getParser();
const text1 = LocalizeText('achievements.levelup.desc');
const badgeName = LocalizeBadgeName(parser.data.badgeCode);
const badgeImage = GetSessionDataManager().getBadgeUrl(parser.data.badgeCode);
const internalLink = 'questengine/achievements/' + parser.data.category;
NotificationUtilities.showSingleBubble((text1 + ' ' + badgeName), NotificationBubbleType.ACHIEVEMENT, badgeImage, internalLink);
}, []);
useMessageEvent(AchievementNotificationMessageEvent, onAchievementNotificationMessageEvent);
const onClubGiftNotificationEvent = useCallback((event: ClubGiftNotificationEvent) =>
{
const parser = event.getParser();
NotificationUtilities.showClubGiftNotification(parser.numGifts);
}, []);
useMessageEvent(ClubGiftNotificationEvent, onClubGiftNotificationEvent);
const onModeratorMessageEvent = useCallback((event: ModeratorMessageEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleModeratorMessage(parser.message, parser.url);
}, []);
useMessageEvent(ModeratorMessageEvent, onModeratorMessageEvent);
const onActivityPointNotificationMessageEvent = useCallback((event: ActivityPointNotificationMessageEvent) =>
{
const parser = event.getParser();
if((parser.amountChanged <= 0) || (parser.type !== 5)) return;
const imageUrl = GetConfiguration<string>('currency.asset.icon.url', '').replace('%type%', parser.type.toString());
NotificationUtilities.showSingleBubble(LocalizeText('notifications.text.loyalty.received', [ 'AMOUNT' ], [ parser.amountChanged.toString() ]), NotificationBubbleType.INFO, imageUrl);
}, []);
useMessageEvent(ActivityPointNotificationMessageEvent, onActivityPointNotificationMessageEvent);
const onUserBannedMessageEvent = useCallback((event: UserBannedMessageEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleUserBannedMessage(parser.message);
}, []);
useMessageEvent(UserBannedMessageEvent, onUserBannedMessageEvent);
const onHotelClosesAndWillOpenAtEvent = useCallback((event: HotelClosesAndWillOpenAtEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleHotelClosedMessage(parser.openHour, parser.openMinute, parser.userThrowOutAtClose);
}, []);
useMessageEvent(HotelClosesAndWillOpenAtEvent, onHotelClosesAndWillOpenAtEvent);
const onPetReceivedMessageEvent = useCallback((event: PetReceivedMessageEvent) =>
{
const parser = event.getParser();
const text = LocalizeText('notifications.text.' + (parser.boughtAsGift ? 'petbought' : 'petreceived'));
let imageUrl: string = null;
const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.pet.typeId, parser.pet.paletteId, parseInt(parser.pet.color, 16), new Vector3d(45 * 3), 64, null, true);
if(imageResult) imageUrl = imageResult.getImage().src;
NotificationUtilities.showSingleBubble(text, NotificationBubbleType.PETLEVEL, imageUrl);
}, []);
useMessageEvent(PetReceivedMessageEvent, onPetReceivedMessageEvent);
const onRoomEnterEvent = useCallback((event: RoomEnterEvent) =>
{
const parser = event.getParser();
NotificationUtilities.showModerationDisclaimer();
}, []);
useMessageEvent(RoomEnterEvent, onRoomEnterEvent);
const onMOTDNotificationEvent = useCallback((event: MOTDNotificationEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleMOTD(parser.messages);
}, []);
useMessageEvent(MOTDNotificationEvent, onMOTDNotificationEvent);
const onPetLevelNotificationEvent = useCallback((event: PetLevelNotificationEvent) =>
{
const parser = event.getParser();
let imageUrl: string = null;
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);
}, []);
useMessageEvent(PetLevelNotificationEvent, onPetLevelNotificationEvent);
const onInfoFeedEnableMessageEvent = useCallback((event: InfoFeedEnableMessageEvent) =>
{
const parser = event.getParser();
NotificationUtilities.BUBBLES_DISABLED = !(parser.enabled);
}, []);
useMessageEvent(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))
}, []);
useMessageEvent(ClubGiftSelectedEvent, onClubGiftSelectedEvent);
const onMaintenanceStatusMessageEvent = useCallback((event: MaintenanceStatusMessageEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleHotelMaintenanceMessage(parser.minutesUntilMaintenance, parser.duration);
}, []);
useMessageEvent(MaintenanceStatusMessageEvent, onMaintenanceStatusMessageEvent);
const onModeratorCautionEvent = useCallback((event: ModeratorCautionEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleModeratorCaution(parser.message, parser.url);
}, []);
useMessageEvent(ModeratorCautionEvent, onModeratorCautionEvent);
const onNotificationDialogMessageEvent = useCallback((event: NotificationDialogMessageEvent) =>
{
const parser = event.getParser();
NotificationUtilities.showNotification(parser.type, parser.parameters);
}, []);
useMessageEvent(NotificationDialogMessageEvent, onNotificationDialogMessageEvent);
const onHotelWillCloseInMinutesEvent = useCallback((event: HotelWillCloseInMinutesEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleHotelClosingMessage(parser.openMinute);
}, []);
useMessageEvent(HotelWillCloseInMinutesEvent, onHotelWillCloseInMinutesEvent);
const onHotelClosedAndOpensEvent = useCallback((event: HotelClosedAndOpensEvent) =>
{
const parser = event.getParser();
NotificationUtilities.handleLoginFailedHotelClosedMessage(parser.openHour, parser.openMinute);
}, []);
useMessageEvent(HotelClosedAndOpensEvent, onHotelClosedAndOpensEvent);
return null;
}

View File

@ -1,84 +1,14 @@
import { FC, ReactNode, useCallback, useMemo, useState } from 'react'; import { FC, ReactNode, useMemo } from 'react';
import { NotificationAlertItem, NotificationBubbleItem, NotificationBubbleType, NotificationConfirmItem } from '../../api'; import { NotificationBubbleType } from '../../api';
import { Column } from '../../common'; import { Column } from '../../common';
import { NotificationAlertEvent, NotificationBubbleEvent, NotificationConfirmEvent } from '../../events'; import { useNotification } from '../../hooks';
import { useUiEvent } from '../../hooks';
import { NotificationCenterMessageHandler } from './NotificationCenterMessageHandler';
import { GetAlertLayout } from './views/alert-layouts/GetAlertLayout'; import { GetAlertLayout } from './views/alert-layouts/GetAlertLayout';
import { GetBubbleLayout } from './views/bubble-layouts/GetBubbleLayout'; import { GetBubbleLayout } from './views/bubble-layouts/GetBubbleLayout';
import { GetConfirmLayout } from './views/confirm-layouts/GetConfirmLayout'; import { GetConfirmLayout } from './views/confirm-layouts/GetConfirmLayout';
export const NotificationCenterView: FC<{}> = props => export const NotificationCenterView: FC<{}> = props =>
{ {
const [ alerts, setAlerts ] = useState<NotificationAlertItem[]>([]); const { alerts = [], bubbleAlerts = [], confirms = [], closeAlert = null, closeBubbleAlert = null, closeConfirm = null } = useNotification();
const [ bubbleAlerts, setBubbleAlerts ] = useState<NotificationBubbleItem[]>([]);
const [ confirms, setConfirms ] = useState<NotificationConfirmItem[]>([]);
const onNotificationAlertEvent = useCallback((event: NotificationAlertEvent) =>
{
const alertItem = new NotificationAlertItem(event.messages, event.alertType, event.clickUrl, event.clickUrlText, event.title, event.imageUrl);
setAlerts(prevValue => [ alertItem, ...prevValue ]);
}, []);
useUiEvent(NotificationAlertEvent.ALERT, onNotificationAlertEvent);
const onNotificationBubbleEvent = useCallback((event: NotificationBubbleEvent) =>
{
const notificationItem = new NotificationBubbleItem(event.message, event.notificationType, event.imageUrl, event.linkUrl);
setBubbleAlerts(prevValue => [ notificationItem, ...prevValue ]);
}, []);
useUiEvent(NotificationBubbleEvent.NEW_BUBBLE, onNotificationBubbleEvent);
const onNotificationConfirmEvent = useCallback((event: NotificationConfirmEvent) =>
{
const confirmItem = new NotificationConfirmItem(event.type, event.message, event.onConfirm, event.onCancel, event.confirmText, event.cancelText, event.title);
setConfirms(prevValue => [ confirmItem, ...prevValue ]);
}, []);
useUiEvent(NotificationConfirmEvent.CONFIRM, onNotificationConfirmEvent);
const closeAlert = useCallback((alert: NotificationAlertItem) =>
{
setAlerts(prevValue =>
{
const newAlerts = [ ...prevValue ];
const index = newAlerts.findIndex(value => (alert === value));
if(index >= 0) newAlerts.splice(index, 1);
return newAlerts;
});
}, []);
const closeBubbleAlert = useCallback((item: NotificationBubbleItem) =>
{
setBubbleAlerts(prevValue =>
{
const newAlerts = [ ...prevValue ];
const index = newAlerts.findIndex(value => (item === value));
if(index >= 0) newAlerts.splice(index, 1);
return newAlerts;
})
}, []);
const closeConfirm = useCallback((item: NotificationConfirmItem) =>
{
setConfirms(prevValue =>
{
const newConfirms = [ ...prevValue ];
const index = newConfirms.findIndex(value => (item === value));
if(index >= 0) newConfirms.splice(index, 1);
return newConfirms;
})
}, []);
const getAlerts = useMemo(() => const getAlerts = useMemo(() =>
{ {
@ -137,7 +67,6 @@ export const NotificationCenterView: FC<{}> = props =>
return ( return (
<> <>
<NotificationCenterMessageHandler />
<Column gap={ 1 }> <Column gap={ 1 }>
{ getBubbleAlerts } { getBubbleAlerts }
</Column> </Column>

View File

@ -1,5 +1,5 @@
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { LocalizeText, NotificationAlertItem, NotificationAlertType, NotificationUtilities } from '../../../../api'; import { LocalizeText, NotificationAlertItem, NotificationAlertType, OpenUrl } from '../../../../api';
import { Base, Button, Column, Flex, LayoutNotificationAlertView, LayoutNotificationAlertViewProps } from '../../../../common'; import { Base, Button, Column, Flex, LayoutNotificationAlertView, LayoutNotificationAlertViewProps } from '../../../../common';
interface NotificationDefaultAlertViewProps extends LayoutNotificationAlertViewProps interface NotificationDefaultAlertViewProps extends LayoutNotificationAlertViewProps
@ -15,7 +15,7 @@ export const NotificationDefaultAlertView: FC<NotificationDefaultAlertViewProps>
const visitUrl = useCallback(() => const visitUrl = useCallback(() =>
{ {
NotificationUtilities.openUrl(item.clickUrl); OpenUrl(item.clickUrl);
close(); close();
}, [ item, close ]); }, [ item, close ]);

View File

@ -1,5 +1,5 @@
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText, NotificationAlertItem, NotificationUtilities } from '../../../../api'; import { LocalizeText, NotificationAlertItem, OpenUrl } from '../../../../api';
import { AutoGrid, Button, Column, Flex, LayoutNotificationAlertView, LayoutNotificationAlertViewProps } from '../../../../common'; import { AutoGrid, Button, Column, Flex, LayoutNotificationAlertView, LayoutNotificationAlertViewProps } from '../../../../common';
interface NotificationDefaultAlertViewProps extends LayoutNotificationAlertViewProps interface NotificationDefaultAlertViewProps extends LayoutNotificationAlertViewProps
@ -16,7 +16,7 @@ export const NotificationSeachAlertView: FC<NotificationDefaultAlertViewProps> =
const visitUrl = useCallback(() => const visitUrl = useCallback(() =>
{ {
NotificationUtilities.openUrl(item.clickUrl); OpenUrl(item.clickUrl);
close(); close();
}, [ item, close ]); }, [ item, close ]);

View File

@ -1,5 +1,5 @@
import { FC } from 'react'; import { FC } from 'react';
import { LocalizeText, NotificationBubbleItem, NotificationUtilities } from '../../../../api'; import { LocalizeText, NotificationBubbleItem, OpenUrl } from '../../../../api';
import { LayoutCurrencyIcon, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps } from '../../../../common'; import { LayoutCurrencyIcon, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps } from '../../../../common';
export interface NotificationClubGiftBubbleViewProps extends LayoutNotificationBubbleViewProps export interface NotificationClubGiftBubbleViewProps extends LayoutNotificationBubbleViewProps
@ -18,7 +18,7 @@ export const NotificationClubGiftBubbleView: FC<NotificationClubGiftBubbleViewPr
<span className="ms-1">{ LocalizeText('notifications.text.club_gift') }</span> <span className="ms-1">{ LocalizeText('notifications.text.club_gift') }</span>
</div> </div>
<div className="d-flex align-items-center justify-content-end gap-2"> <div className="d-flex align-items-center justify-content-end gap-2">
<button type="button" className="btn btn-success w-100 btn-sm" onClick={ () => NotificationUtilities.openUrl(item.linkUrl) }>{ LocalizeText('notifications.button.show_gift_list') }</button> <button type="button" className="btn btn-success w-100 btn-sm" onClick={ () => OpenUrl(item.linkUrl) }>{ LocalizeText('notifications.button.show_gift_list') }</button>
<span className="text-decoration-underline cursor-pointer text-nowrap" onClick={ close }>{ LocalizeText('notifications.button.later') }</span> <span className="text-decoration-underline cursor-pointer text-nowrap" onClick={ close }>{ LocalizeText('notifications.button.later') }</span>
</div> </div>
</LayoutNotificationBubbleView> </LayoutNotificationBubbleView>

View File

@ -1,5 +1,5 @@
import { FC } from 'react'; import { FC } from 'react';
import { NotificationBubbleItem, NotificationUtilities } from '../../../../api'; import { NotificationBubbleItem, OpenUrl } from '../../../../api';
import { Flex, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps, Text } from '../../../../common'; import { Flex, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps, Text } from '../../../../common';
export interface NotificationDefaultBubbleViewProps extends LayoutNotificationBubbleViewProps export interface NotificationDefaultBubbleViewProps extends LayoutNotificationBubbleViewProps
@ -14,7 +14,7 @@ export const NotificationDefaultBubbleView: FC<NotificationDefaultBubbleViewProp
const htmlText = item.message.replace(/\r\n|\r|\n/g, '<br />'); const htmlText = item.message.replace(/\r\n|\r|\n/g, '<br />');
return ( return (
<LayoutNotificationBubbleView close={ close } gap={ 2 } alignItems="center" onClick={ event => (item.linkUrl && item.linkUrl.length && NotificationUtilities.openUrl(item.linkUrl)) } { ...rest }> <LayoutNotificationBubbleView close={ close } gap={ 2 } alignItems="center" onClick={ event => (item.linkUrl && item.linkUrl.length && OpenUrl(item.linkUrl)) } { ...rest }>
<Flex center className="bubble-image-container"> <Flex center className="bubble-image-container">
{ (item.iconUrl && item.iconUrl.length) && { (item.iconUrl && item.iconUrl.length) &&
<img className="no-select" src={ item.iconUrl } alt="" /> } <img className="no-select" src={ item.iconUrl } alt="" /> }

View File

@ -1,7 +1,7 @@
import { RoomEngineObjectEvent, RoomEngineRoomAdEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomId, RoomSessionErrorMessageEvent, RoomZoomEvent } from '@nitrots/nitro-renderer'; import { RoomEngineObjectEvent, RoomEngineRoomAdEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomId, RoomSessionErrorMessageEvent, RoomZoomEvent } from '@nitrots/nitro-renderer';
import { FC } from 'react'; import { FC } from 'react';
import { DispatchUiEvent, GetRoomEngine, LocalizeText, NotificationAlertType, NotificationUtilities, RoomWidgetUpdateRoomObjectEvent } from '../../../api'; import { DispatchUiEvent, GetRoomEngine, LocalizeText, NotificationAlertType, RoomWidgetUpdateRoomObjectEvent } from '../../../api';
import { useRoom, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../../hooks'; import { useNotification, useRoom, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../../hooks';
import { AvatarInfoWidgetView } from './avatar-info/AvatarInfoWidgetView'; import { AvatarInfoWidgetView } from './avatar-info/AvatarInfoWidgetView';
import { ChatInputView } from './chat-input/ChatInputView'; import { ChatInputView } from './chat-input/ChatInputView';
import { ChatWidgetView } from './chat/ChatWidgetView'; import { ChatWidgetView } from './chat/ChatWidgetView';
@ -17,6 +17,7 @@ import { WordQuizWidgetView } from './word-quiz/WordQuizWidgetView';
export const RoomWidgetsView: FC<{}> = props => export const RoomWidgetsView: FC<{}> = props =>
{ {
const { roomSession = null } = useRoom(); const { roomSession = null } = useRoom();
const { simpleAlert = null } = useNotification();
useRoomEngineEvent<RoomZoomEvent>(RoomZoomEvent.ROOM_ZOOM, event => GetRoomEngine().setRoomInstanceRenderingCanvasScale(event.roomId, 1, event.level, null, null, false, event.asDelta)); useRoomEngineEvent<RoomZoomEvent>(RoomZoomEvent.ROOM_ZOOM, event => GetRoomEngine().setRoomInstanceRenderingCanvasScale(event.roomId, 1, event.level, null, null, false, event.asDelta));
@ -146,7 +147,7 @@ export const RoomWidgetsView: FC<{}> = props =>
return; return;
} }
NotificationUtilities.simpleAlert(errorMessage, NotificationAlertType.DEFAULT, null, null, errorTitle); simpleAlert(errorMessage, NotificationAlertType.DEFAULT, null, null, errorTitle);
}); });
return ( return (

View File

@ -1,9 +1,10 @@
import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer'; import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useBetween } from 'use-between'; import { useBetween } from 'use-between';
import { BuilderFurniPlaceableStatus, CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, CreateLinkEvent, DispatchUiEvent, FurniCategory, GetFurnitureData, GetNitroInstance, GetProductDataForLocalization, GetRoomEngine, GetRoomSession, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, NotificationUtilities, Offer, PageLocalization, PlacedObjectPurchaseData, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api'; import { BuilderFurniPlaceableStatus, CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, CreateLinkEvent, DispatchUiEvent, FurniCategory, GetFurnitureData, GetNitroInstance, GetProductDataForLocalization, GetRoomEngine, GetRoomSession, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, Offer, PageLocalization, PlacedObjectPurchaseData, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api';
import { CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent, InventoryFurniAddedEvent } from '../../events'; import { CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent, InventoryFurniAddedEvent } from '../../events';
import { useMessageEvent, useRoomEngineEvent, useUiEvent } from '../events'; import { useMessageEvent, useRoomEngineEvent, useUiEvent } from '../events';
import { useNotification } from '../notification';
import { useCatalogPlaceMultipleItems } from './useCatalogPlaceMultipleItems'; import { useCatalogPlaceMultipleItems } from './useCatalogPlaceMultipleItems';
import { useCatalogSkipPurchaseConfirmation } from './useCatalogSkipPurchaseConfirmation'; import { useCatalogSkipPurchaseConfirmation } from './useCatalogSkipPurchaseConfirmation';
@ -39,6 +40,7 @@ const useCatalogState = () =>
const [ secondsLeft, setSecondsLeft ] = useState(0); const [ secondsLeft, setSecondsLeft ] = useState(0);
const [ updateTime, setUpdateTime ] = useState(0); const [ updateTime, setUpdateTime ] = useState(0);
const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0); const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0);
const { simpleAlert = null } = useNotification();
const requestedPage = useRef(new RequestedPage()); const requestedPage = useRef(new RequestedPage());
const resetState = useCallback(() => const resetState = useCallback(() =>
@ -657,8 +659,8 @@ const useCatalogState = () =>
const message = LocalizeText(`inventory.marketplace.result.${ parser.result }`); const message = LocalizeText(`inventory.marketplace.result.${ parser.result }`);
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, title); simpleAlert(message, NotificationAlertType.DEFAULT, null, null, title);
}, []); }, [ simpleAlert ]);
useMessageEvent(MarketplaceMakeOfferResult, onMarketplaceMakeOfferResult); useMessageEvent(MarketplaceMakeOfferResult, onMarketplaceMakeOfferResult);
@ -682,8 +684,8 @@ const useCatalogState = () =>
resetState(); resetState();
if(wasVisible) NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.published.description'), NotificationAlertType.ALERT, null, null, LocalizeText('catalog.alert.published.title')); if(wasVisible) simpleAlert(LocalizeText('catalog.alert.published.description'), NotificationAlertType.ALERT, null, null, LocalizeText('catalog.alert.published.title'));
}, [ isVisible, resetState ]); }, [ isVisible, resetState, simpleAlert ]);
useMessageEvent(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent); useMessageEvent(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent);

View File

@ -1,8 +1,9 @@
import { NewConsoleMessageEvent, RoomInviteErrorEvent, RoomInviteEvent, SendMessageComposer as SendMessageComposerPacket } from '@nitrots/nitro-renderer'; import { NewConsoleMessageEvent, RoomInviteErrorEvent, RoomInviteEvent, SendMessageComposer as SendMessageComposerPacket } from '@nitrots/nitro-renderer';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { useBetween } from 'use-between'; import { useBetween } from 'use-between';
import { CloneObject, GetSessionDataManager, LocalizeText, MessengerIconState, MessengerThread, MessengerThreadChat, NotificationAlertType, NotificationUtilities, PlaySound, SendMessageComposer, SoundNames } from '../../api'; import { CloneObject, GetSessionDataManager, LocalizeText, MessengerIconState, MessengerThread, MessengerThreadChat, NotificationAlertType, PlaySound, SendMessageComposer, SoundNames } from '../../api';
import { useMessageEvent } from '../events'; import { useMessageEvent } from '../events';
import { useNotification } from '../notification';
import { useFriends } from './useFriends'; import { useFriends } from './useFriends';
const useMessengerState = () => const useMessengerState = () =>
@ -12,6 +13,7 @@ const useMessengerState = () =>
const [ hiddenThreadIds, setHiddenThreadIds ] = useState<number[]>([]); const [ hiddenThreadIds, setHiddenThreadIds ] = useState<number[]>([]);
const [ iconState, setIconState ] = useState<number>(MessengerIconState.HIDDEN); const [ iconState, setIconState ] = useState<number>(MessengerIconState.HIDDEN);
const { getFriend = null } = useFriends(); const { getFriend = null } = useFriends();
const { simpleAlert = null } = useNotification();
const visibleThreads = useMemo(() => messageThreads.filter(thread => (hiddenThreadIds.indexOf(thread.threadId) === -1)), [ messageThreads, hiddenThreadIds ]); const visibleThreads = useMemo(() => messageThreads.filter(thread => (hiddenThreadIds.indexOf(thread.threadId) === -1)), [ messageThreads, hiddenThreadIds ]);
const activeThread = useMemo(() => ((activeThreadId > 0) && visibleThreads.find(thread => (thread.threadId === activeThreadId) || null)), [ activeThreadId, visibleThreads ]); const activeThread = useMemo(() => ((activeThreadId > 0) && visibleThreads.find(thread => (thread.threadId === activeThreadId) || null)), [ activeThreadId, visibleThreads ]);
@ -94,7 +96,7 @@ const useMessengerState = () =>
}); });
} }
const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) => useMessageEvent<NewConsoleMessageEvent>(NewConsoleMessageEvent, event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -131,11 +133,9 @@ const useMessengerState = () =>
return newValue; return newValue;
}); });
}, [ activeThreadId, getFriend ]); });
useMessageEvent(NewConsoleMessageEvent, onNewConsoleMessageEvent); useMessageEvent<RoomInviteEvent>(RoomInviteEvent, event =>
const onRoomInviteEvent = useCallback((event: RoomInviteEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -172,19 +172,15 @@ const useMessengerState = () =>
return newValue; return newValue;
}); });
}, [ activeThreadId, getFriend ]); });
useMessageEvent(RoomInviteEvent, onRoomInviteEvent); useMessageEvent<RoomInviteErrorEvent>(RoomInviteErrorEvent, event =>
const onRoomInviteErrorEvent = useCallback((event: RoomInviteErrorEvent) =>
{ {
const parser = event.getParser(); const parser = event.getParser();
const message = ((('Received room invite error: errorCode: ' + parser.errorCode) + ', recipients: ') + parser.failedRecipients); const message = ((('Received room invite error: errorCode: ' + parser.errorCode) + ', recipients: ') + parser.failedRecipients);
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title')); simpleAlert(message, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title'));
}, []); });
useMessageEvent(RoomInviteErrorEvent, onRoomInviteErrorEvent);
useEffect(() => useEffect(() =>
{ {

View File

@ -9,6 +9,7 @@ export * from './friends';
export * from './groups'; export * from './groups';
export * from './inventory'; export * from './inventory';
export * from './navigator'; export * from './navigator';
export * from './notification';
export * from './purse'; export * from './purse';
export * from './rooms'; export * from './rooms';
export * from './session'; export * from './session';

View File

@ -1,8 +1,9 @@
import { AdvancedMap, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCloseParser, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListItemEvent, TradingListItemRemoveComposer, TradingNotOpenEvent, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent } from '@nitrots/nitro-renderer'; import { AdvancedMap, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCloseParser, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListItemEvent, TradingListItemRemoveComposer, TradingNotOpenEvent, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent } from '@nitrots/nitro-renderer';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useBetween } from 'use-between'; import { useBetween } from 'use-between';
import { CloneObject, GetRoomSession, GetSessionDataManager, GroupItem, LocalizeText, NotificationUtilities, parseTradeItems, SendMessageComposer, TradeState, TradeUserData, TradingNotificationMessage, TradingNotificationType } from '../../api'; import { CloneObject, GetRoomSession, GetSessionDataManager, GroupItem, LocalizeText, parseTradeItems, SendMessageComposer, TradeState, TradeUserData, TradingNotificationType } from '../../api';
import { useMessageEvent } from '../events'; import { useMessageEvent } from '../events';
import { useNotification } from '../notification';
import { useInventoryFurni } from './useInventoryFurni'; import { useInventoryFurni } from './useInventoryFurni';
const useInventoryTradeState = () => const useInventoryTradeState = () =>
@ -11,6 +12,7 @@ const useInventoryTradeState = () =>
const [ otherUser, setOtherUser ] = useState<TradeUserData>(null); const [ otherUser, setOtherUser ] = useState<TradeUserData>(null);
const [ tradeState, setTradeState ] = useState(TradeState.TRADING_STATE_READY); const [ tradeState, setTradeState ] = useState(TradeState.TRADING_STATE_READY);
const { groupItems = [], setGroupItems = null, activate = null, deactivate = null } = useInventoryFurni(); const { groupItems = [], setGroupItems = null, activate = null, deactivate = null } = useInventoryFurni();
const { simpleAlert = null, showTradeAlert = null } = useNotification();
const isTrading = (tradeState >= TradeState.TRADING_STATE_RUNNING); const isTrading = (tradeState >= TradeState.TRADING_STATE_RUNNING);
const progressTrade = () => const progressTrade = () =>
@ -20,7 +22,7 @@ const useInventoryTradeState = () =>
case TradeState.TRADING_STATE_RUNNING: case TradeState.TRADING_STATE_RUNNING:
if(!otherUser.itemCount && !ownUser.accepts) if(!otherUser.itemCount && !ownUser.accepts)
{ {
NotificationUtilities.simpleAlert(LocalizeText('inventory.trading.warning.other_not_offering'), null, null, null); simpleAlert(LocalizeText('inventory.trading.warning.other_not_offering'), null, null, null);
} }
if(ownUser.accepts) if(ownUser.accepts)
@ -101,13 +103,13 @@ const useInventoryTradeState = () =>
if(parser.reason === TradingCloseParser.ERROR_WHILE_COMMIT) if(parser.reason === TradingCloseParser.ERROR_WHILE_COMMIT)
{ {
TradingNotificationMessage(TradingNotificationType.ERROR_WHILE_COMMIT); showTradeAlert(TradingNotificationType.ERROR_WHILE_COMMIT);
} }
else else
{ {
if(ownUser && (parser.userID !== ownUser.userId)) if(ownUser && (parser.userID !== ownUser.userId))
{ {
TradingNotificationMessage(TradingNotificationType.THEY_CANCELLED); showTradeAlert(TradingNotificationType.THEY_CANCELLED);
} }
} }
@ -254,21 +256,21 @@ const useInventoryTradeState = () =>
{ {
const parser = event.getParser(); const parser = event.getParser();
TradingNotificationMessage(parser.reason, parser.otherUserName); showTradeAlert(parser.reason, parser.otherUserName);
}); });
useMessageEvent<TradingOtherNotAllowedEvent>(TradingOtherNotAllowedEvent, event => useMessageEvent<TradingOtherNotAllowedEvent>(TradingOtherNotAllowedEvent, event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
TradingNotificationMessage(TradingNotificationType.THEY_NOT_ALLOWED); showTradeAlert(TradingNotificationType.THEY_NOT_ALLOWED);
}); });
useMessageEvent<TradingYouAreNotAllowedEvent>(TradingYouAreNotAllowedEvent, event => useMessageEvent<TradingYouAreNotAllowedEvent>(TradingYouAreNotAllowedEvent, event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
TradingNotificationMessage(TradingNotificationType.YOU_NOT_ALLOWED); showTradeAlert(TradingNotificationType.YOU_NOT_ALLOWED);
}); });
useEffect(() => useEffect(() =>

View File

@ -0,0 +1 @@
export * from './useNotification';

View File

@ -0,0 +1,386 @@
import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, HabboBroadcastMessageEvent, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelWillCloseInMinutesEvent, InfoFeedEnableMessageEvent, MaintenanceStatusMessageEvent, ModeratorCautionEvent, ModeratorMessageEvent, MOTDNotificationEvent, NotificationDialogMessageEvent, PetLevelNotificationEvent, PetReceivedMessageEvent, RespectReceivedEvent, RoomEnterEffect, RoomEnterEvent, UserBannedMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
import { useCallback, useState } from 'react';
import { useBetween } from 'use-between';
import { GetConfiguration, GetNitroInstance, GetRoomEngine, GetSessionDataManager, LocalizeBadgeName, LocalizeText, NotificationAlertItem, NotificationAlertType, NotificationBubbleItem, NotificationBubbleType, NotificationConfirmItem, PlaySound, ProductImageUtility, TradingNotificationType } from '../../api';
import { useMessageEvent } from '../events';
const cleanText = (text: string) => text.replace(/\\r/g, '\r');
const getTimeZeroPadded = (time: number) =>
{
const text = ('0' + time);
return text.substr((text.length - 2), text.length);
}
let modDisclaimerTimeout: ReturnType<typeof setTimeout> = null;
const useNotificationState = () =>
{
const [ alerts, setAlerts ] = useState<NotificationAlertItem[]>([]);
const [ bubbleAlerts, setBubbleAlerts ] = useState<NotificationBubbleItem[]>([]);
const [ confirms, setConfirms ] = useState<NotificationConfirmItem[]>([]);
const [ bubblesDisabled, setBubblesDisabled ] = useState(false);
const [ modDisclaimerShown, setModDisclaimerShown ] = useState(false);
const getMainNotificationConfig = () => GetConfiguration<{ [key: string]: { delivery?: string, display?: string; title?: string; image?: string }}>('notification', {});
const getNotificationConfig = (key: string) =>
{
const mainConfig = getMainNotificationConfig();
if(!mainConfig) return null;
return mainConfig[key];
}
const getNotificationPart = (options: Map<string, string>, type: string, key: string, localize: boolean) =>
{
if(options.has(key)) return options.get(key);
const localizeKey = [ 'notification', type, key ].join('.');
if(GetNitroInstance().localization.hasValue(localizeKey) || localize) return LocalizeText(localizeKey, Array.from(options.keys()), Array.from(options.values()));
return null;
}
const getNotificationImageUrl = (options: Map<string, string>, type: string) =>
{
let imageUrl = options.get('image');
if(!imageUrl) imageUrl = GetConfiguration<string>('image.library.notifications.url', '').replace('%image%', type.replace(/\./g, '_'));
return LocalizeText(imageUrl);
}
const simpleAlert = useCallback((message: string, type: string = null, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null) =>
{
if(!title || !title.length) title = LocalizeText('notifications.broadcast.title');
if(!type || !type.length) type = NotificationAlertType.DEFAULT;
const alertItem = new NotificationAlertItem([ cleanText(message) ], type, clickUrl, clickUrlText, title, imageUrl);
setAlerts(prevValue => [ alertItem, ...prevValue ]);
}, []);
const showNitroAlert = useCallback(() => simpleAlert(null, NotificationAlertType.NITRO), [ simpleAlert ]);
const showSingleBubble = useCallback((message: string, type: string, imageUrl: string = null, internalLink: string = null) =>
{
if(bubblesDisabled) return;
const notificationItem = new NotificationBubbleItem(message, type, imageUrl, internalLink);
setBubbleAlerts(prevValue => [ notificationItem, ...prevValue ]);
}, [ bubblesDisabled ]);
const showNotification = (type: string, options: Map<string, string> = null) =>
{
if(!options) options = new Map();
const configuration = getNotificationConfig(('notification.' + type));
if(configuration) for(const key in configuration) options.set(key, configuration[key]);
const title = getNotificationPart(options, type, 'title', true);
const message = getNotificationPart(options, type, 'message', true).replace(/\\r/g, '\r');
const linkTitle = getNotificationPart(options, type, 'linkTitle', false);
const linkUrl = getNotificationPart(options, type, 'linkUrl', false);
const image = getNotificationImageUrl(options, type);
if(options.get('display') === 'BUBBLE')
{
showSingleBubble(LocalizeText(message), NotificationBubbleType.INFO, image, linkUrl);
}
else
{
simpleAlert(message, type, linkUrl, linkTitle, title, image);
}
if(options.get('sound')) PlaySound(options.get('sound'));
}
const showConfirm = useCallback((message: string, onConfirm: () => void, onCancel: () => void, confirmText: string = null, cancelText: string = null, title: string = null, type: string = null) =>
{
if(!confirmText || !confirmText.length) confirmText = LocalizeText('generic.confirm');
if(!cancelText || !cancelText.length) cancelText = LocalizeText('generic.cancel');
if(!title || !title.length) title = LocalizeText('notifications.broadcast.title');
const confirmItem = new NotificationConfirmItem(type, message, onConfirm, onCancel, confirmText, cancelText, title);
setConfirms(prevValue => [ confirmItem, ...prevValue ]);
}, []);
const showModeratorMessage = (message: string, url: string = null, showHabboWay: boolean = true) =>
{
simpleAlert(message, NotificationAlertType.DEFAULT, url, LocalizeText('mod.alert.link'), LocalizeText('mod.alert.title'));
}
const showTradeAlert = useCallback((type: number, otherUsername: string = '') =>
{
switch(type)
{
case TradingNotificationType.ALERT_SCAM:
simpleAlert(LocalizeText('inventory.trading.warning.other_not_offering'), null, null, null, LocalizeText('inventory.trading.notification.title'));
return;
case TradingNotificationType.HOTEL_TRADING_DISABLED:
case TradingNotificationType.YOU_NOT_ALLOWED:
case TradingNotificationType.THEY_NOT_ALLOWED:
case TradingNotificationType.ROOM_DISABLED:
case TradingNotificationType.YOU_OPEN:
case TradingNotificationType.THEY_OPEN:
simpleAlert(LocalizeText(`inventory.trading.openfail.${ type }`, [ 'otherusername' ], [ otherUsername ]), null, null, null, LocalizeText('inventory.trading.openfail.title'));
return;
case TradingNotificationType.ERROR_WHILE_COMMIT:
simpleAlert(`${ LocalizeText('inventory.trading.notification.caption') }, ${ LocalizeText('inventory.trading.notification.commiterror.info') }`, null, null, null, LocalizeText('inventory.trading.notification.title'));
return;
case TradingNotificationType.THEY_CANCELLED:
simpleAlert(LocalizeText('inventory.trading.info.closed'), null, null, null, LocalizeText('inventory.trading.notification.title'));
return;
}
}, [ simpleAlert ]);
const closeAlert = useCallback((alert: NotificationAlertItem) =>
{
setAlerts(prevValue =>
{
const newAlerts = [ ...prevValue ];
const index = newAlerts.findIndex(value => (alert === value));
if(index >= 0) newAlerts.splice(index, 1);
return newAlerts;
});
}, []);
const closeBubbleAlert = useCallback((item: NotificationBubbleItem) =>
{
setBubbleAlerts(prevValue =>
{
const newAlerts = [ ...prevValue ];
const index = newAlerts.findIndex(value => (item === value));
if(index >= 0) newAlerts.splice(index, 1);
return newAlerts;
})
}, []);
const closeConfirm = useCallback((item: NotificationConfirmItem) =>
{
setConfirms(prevValue =>
{
const newConfirms = [ ...prevValue ];
const index = newConfirms.findIndex(value => (item === value));
if(index >= 0) newConfirms.splice(index, 1);
return newConfirms;
})
}, []);
useMessageEvent<RespectReceivedEvent>(RespectReceivedEvent, event =>
{
const parser = event.getParser();
if(parser.userId !== GetSessionDataManager().userId) return;
const text1 = LocalizeText('notifications.text.respect.1');
const text2 = LocalizeText('notifications.text.respect.2', [ 'count' ], [ parser.respectsReceived.toString() ]);
showSingleBubble(text1, NotificationBubbleType.RESPECT);
showSingleBubble(text2, NotificationBubbleType.RESPECT);
});
useMessageEvent<HabboBroadcastMessageEvent>(HabboBroadcastMessageEvent, event =>
{
const parser = event.getParser();
simpleAlert(parser.message.replace(/\\r/g, '\r'), null, null, LocalizeText('notifications.broadcast.title'));
});
useMessageEvent<AchievementNotificationMessageEvent>(AchievementNotificationMessageEvent, event =>
{
const parser = event.getParser();
const text1 = LocalizeText('achievements.levelup.desc');
const badgeName = LocalizeBadgeName(parser.data.badgeCode);
const badgeImage = GetSessionDataManager().getBadgeUrl(parser.data.badgeCode);
const internalLink = 'questengine/achievements/' + parser.data.category;
showSingleBubble((text1 + ' ' + badgeName), NotificationBubbleType.ACHIEVEMENT, badgeImage, internalLink);
});
useMessageEvent<ClubGiftNotificationEvent>(ClubGiftNotificationEvent, event =>
{
const parser = event.getParser();
if(parser.numGifts <= 0) return;
showSingleBubble(parser.numGifts.toString(), NotificationBubbleType.CLUBGIFT, null, ('catalog/open/' + GetConfiguration('catalog.links')['hc.hc_gifts']));
});
useMessageEvent<ModeratorMessageEvent>(ModeratorMessageEvent, event =>
{
const parser = event.getParser();
showModeratorMessage(parser.message, parser.url, false);
});
useMessageEvent<ActivityPointNotificationMessageEvent>(ActivityPointNotificationMessageEvent, event =>
{
const parser = event.getParser();
if((parser.amountChanged <= 0) || (parser.type !== 5)) return;
const imageUrl = GetConfiguration<string>('currency.asset.icon.url', '').replace('%type%', parser.type.toString());
showSingleBubble(LocalizeText('notifications.text.loyalty.received', [ 'AMOUNT' ], [ parser.amountChanged.toString() ]), NotificationBubbleType.INFO, imageUrl);
});
useMessageEvent<UserBannedMessageEvent>(UserBannedMessageEvent, event =>
{
const parser = event.getParser();
showModeratorMessage(parser.message);
});
useMessageEvent<HotelClosesAndWillOpenAtEvent>(HotelClosesAndWillOpenAtEvent, event =>
{
const parser = event.getParser();
simpleAlert( LocalizeText(('opening.hours.' + (parser.userThrowOutAtClose ? 'disconnected' : 'closed')), [ 'h', 'm' ], [ getTimeZeroPadded(parser.openHour), getTimeZeroPadded(parser.openMinute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
});
useMessageEvent<PetReceivedMessageEvent>(PetReceivedMessageEvent, event =>
{
const parser = event.getParser();
const text = LocalizeText('notifications.text.' + (parser.boughtAsGift ? 'petbought' : 'petreceived'));
let imageUrl: string = null;
const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.pet.typeId, parser.pet.paletteId, parseInt(parser.pet.color, 16), new Vector3d(45 * 3), 64, null, true);
if(imageResult) imageUrl = imageResult.getImage().src;
showSingleBubble(text, NotificationBubbleType.PETLEVEL, imageUrl);
});
useMessageEvent<MOTDNotificationEvent>(MOTDNotificationEvent, event =>
{
const parser = event.getParser();
const messages = parser.messages.map(message => cleanText(message));
const alertItem = new NotificationAlertItem(messages, NotificationAlertType.MOTD, null, null, LocalizeText('notifications.motd.title'));
setAlerts(prevValue => [ alertItem, ...prevValue ]);
});
useMessageEvent<PetLevelNotificationEvent>(PetLevelNotificationEvent, event =>
{
const parser = event.getParser();
let imageUrl: string = null;
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;
showSingleBubble(LocalizeText('notifications.text.petlevel', [ 'pet_name', 'level' ], [ parser.petName, parser.level.toString() ]), NotificationBubbleType.PETLEVEL, imageUrl);
});
useMessageEvent<InfoFeedEnableMessageEvent>(InfoFeedEnableMessageEvent, event =>
{
const parser = event.getParser();
setBubblesDisabled(!parser.enabled);
});
useMessageEvent<ClubGiftSelectedEvent>(ClubGiftSelectedEvent, event =>
{
const parser = event.getParser();
if(!parser.products || !parser.products.length) return;
const productData = parser.products[0];
if(!productData) return;
showSingleBubble(LocalizeText('notifications.text.club_gift.selected'), NotificationBubbleType.INFO, ProductImageUtility.getProductImageUrl(productData.productType, productData.furniClassId, productData.extraParam));
});
useMessageEvent<MaintenanceStatusMessageEvent>(MaintenanceStatusMessageEvent, event =>
{
const parser = event.getParser();
simpleAlert(LocalizeText('maintenance.shutdown', [ 'm', 'd' ], [ parser.minutesUntilMaintenance.toString(), parser.duration.toString() ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
});
useMessageEvent<ModeratorCautionEvent>(ModeratorCautionEvent, event =>
{
const parser = event.getParser();
showModeratorMessage(parser.message, parser.url);
});
useMessageEvent<NotificationDialogMessageEvent>(NotificationDialogMessageEvent, event =>
{
const parser = event.getParser();
showNotification(parser.type, parser.parameters);
});
useMessageEvent<HotelWillCloseInMinutesEvent>(HotelWillCloseInMinutesEvent, event =>
{
const parser = event.getParser();
simpleAlert(LocalizeText('opening.hours.shutdown', [ 'm' ], [ parser.openMinute.toString() ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
});
useMessageEvent<HotelClosedAndOpensEvent>(HotelClosedAndOpensEvent, event =>
{
const parser = event.getParser();
simpleAlert(LocalizeText('opening.hours.disconnected', [ 'h', 'm' ], [ parser.openHour.toString(), parser.openMinute.toString() ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
});
const onRoomEnterEvent = useCallback(() =>
{
if(modDisclaimerShown) return;
if(RoomEnterEffect.isRunning())
{
if(modDisclaimerTimeout) return;
modDisclaimerTimeout = setTimeout(() =>
{
onRoomEnterEvent();
}, (RoomEnterEffect.totalRunningTime + 5000));
}
else
{
if(modDisclaimerTimeout)
{
clearTimeout(modDisclaimerTimeout);
modDisclaimerTimeout = null;
}
showSingleBubble(LocalizeText('mod.chatdisclaimer'), NotificationBubbleType.INFO);
setModDisclaimerShown(true);
}
}, [ modDisclaimerShown, showSingleBubble ]);
useMessageEvent<RoomEnterEvent>(RoomEnterEvent, onRoomEnterEvent);
return { alerts, bubbleAlerts, confirms, simpleAlert, showNitroAlert, showTradeAlert, showConfirm, closeAlert, closeBubbleAlert, closeConfirm };
}
export const useNotification = () => useBetween(useNotificationState);

View File

@ -1,7 +1,8 @@
import { RoomEngineTriggerWidgetEvent, RoomObjectVariable, StringDataType } from '@nitrots/nitro-renderer'; import { RoomEngineTriggerWidgetEvent, RoomObjectVariable, StringDataType } from '@nitrots/nitro-renderer';
import { useState } from 'react'; import { useState } from 'react';
import { GetRoomEngine, GetSessionDataManager, LocalizeBadgeDescription, LocalizeBadgeName, LocalizeText, NotificationUtilities } from '../../../../api'; import { GetRoomEngine, GetSessionDataManager, LocalizeBadgeDescription, LocalizeBadgeName, LocalizeText } from '../../../../api';
import { useRoomEngineEvent } from '../../../events'; import { useRoomEngineEvent } from '../../../events';
import { useNotification } from '../../../notification';
import { useFurniRemovedEvent } from '../../engine'; import { useFurniRemovedEvent } from '../../engine';
const useFurnitureBadgeDisplayWidgetState = () => const useFurnitureBadgeDisplayWidgetState = () =>
@ -13,6 +14,7 @@ const useFurnitureBadgeDisplayWidgetState = () =>
const [ badgeDesc, setBadgeDesc ] = useState(''); const [ badgeDesc, setBadgeDesc ] = useState('');
const [ date, setDate ] = useState(''); const [ date, setDate ] = useState('');
const [ senderName, setSenderName ] = useState(''); const [ senderName, setSenderName ] = useState('');
const { simpleAlert = null } = useNotification();
const close = () => const close = () =>
{ {
@ -57,7 +59,7 @@ const useFurnitureBadgeDisplayWidgetState = () =>
if(ownerId !== GetSessionDataManager().userId) return; if(ownerId !== GetSessionDataManager().userId) return;
NotificationUtilities.simpleAlert(`${ LocalizeText('resolution.failed.subtitle') } ${ LocalizeText('resolution.failed.text') }`, null, null, null, LocalizeText('resolution.failed.title')); simpleAlert(`${ LocalizeText('resolution.failed.subtitle') } ${ LocalizeText('resolution.failed.text') }`, null, null, null, LocalizeText('resolution.failed.title'));
}); });
useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event => useFurniRemovedEvent(((objectId !== -1) && (category !== -1)), event =>

View File

@ -1,7 +1,8 @@
import { AvatarExpressionEnum, HabboClubLevelEnum, RoomControllerLevel, RoomEngineObjectEvent, RoomObjectCategory, RoomRotatingEffect, RoomSessionChatEvent, RoomSettingsComposer, RoomShakingEffect, RoomZoomEvent, TextureUtils } from '@nitrots/nitro-renderer'; import { AvatarExpressionEnum, HabboClubLevelEnum, RoomControllerLevel, RoomEngineObjectEvent, RoomObjectCategory, RoomRotatingEffect, RoomSessionChatEvent, RoomSettingsComposer, RoomShakingEffect, RoomZoomEvent, TextureUtils } from '@nitrots/nitro-renderer';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { ChatMessageTypeEnum, CreateLinkEvent, GetClubMemberLevel, GetConfiguration, GetNitroInstance, GetRoomEngine, GetSessionDataManager, LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../api'; import { ChatMessageTypeEnum, CreateLinkEvent, GetClubMemberLevel, GetConfiguration, GetNitroInstance, GetRoomEngine, GetSessionDataManager, LocalizeText, SendMessageComposer } from '../../../api';
import { useRoomEngineEvent, useRoomSessionManagerEvent } from '../../events'; import { useRoomEngineEvent, useRoomSessionManagerEvent } from '../../events';
import { useNotification } from '../../notification';
import { useObjectSelectedEvent } from '../engine'; import { useObjectSelectedEvent } from '../engine';
import { useRoom } from '../useRoom'; import { useRoom } from '../useRoom';
@ -13,6 +14,7 @@ const useChatInputWidgetState = () =>
const [ isIdle, setIsIdle ] = useState(false); const [ isIdle, setIsIdle ] = useState(false);
const [ floodBlocked, setFloodBlocked ] = useState(false); const [ floodBlocked, setFloodBlocked ] = useState(false);
const [ floodBlockedSeconds, setFloodBlockedSeconds ] = useState(0); const [ floodBlockedSeconds, setFloodBlockedSeconds ] = useState(0);
const { showNitroAlert = null, showConfirm = null } = useNotification();
const { roomSession = null } = useRoom(); const { roomSession = null } = useRoom();
const sendChat = (text: string, chatType: number, recipientName: string = '', styleId: number = 0) => const sendChat = (text: string, chatType: number, recipientName: string = '', styleId: number = 0) =>
@ -122,7 +124,7 @@ const useChatInputWidgetState = () =>
case ':pickall': case ':pickall':
if(roomSession.isRoomOwner || GetSessionDataManager().isModerator) if(roomSession.isRoomOwner || GetSessionDataManager().isModerator)
{ {
NotificationUtilities.confirm(LocalizeText('room.confirm.pick_all'), () => showConfirm(LocalizeText('room.confirm.pick_all'), () =>
{ {
GetSessionDataManager().sendSpecialCommandMessage(':pickall'); GetSessionDataManager().sendSpecialCommandMessage(':pickall');
}, },
@ -150,7 +152,7 @@ const useChatInputWidgetState = () =>
case ':client': case ':client':
case ':nitro': case ':nitro':
case ':billsonnn': case ':billsonnn':
NotificationUtilities.showNitroAlert(); showNitroAlert();
return null; return null;
case ':settings': case ':settings':
if(roomSession.isRoomOwner || GetSessionDataManager().isModerator) if(roomSession.isRoomOwner || GetSessionDataManager().isModerator)

View File

@ -1,9 +1,10 @@
import { ConditionDefinition, Triggerable, TriggerDefinition, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateTriggerMessageComposer, WiredActionDefinition, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredSaveSuccessEvent } from '@nitrots/nitro-renderer'; import { ConditionDefinition, Triggerable, TriggerDefinition, UpdateActionMessageComposer, UpdateConditionMessageComposer, UpdateTriggerMessageComposer, WiredActionDefinition, WiredFurniActionEvent, WiredFurniConditionEvent, WiredFurniTriggerEvent, WiredSaveSuccessEvent } from '@nitrots/nitro-renderer';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useBetween } from 'use-between'; import { useBetween } from 'use-between';
import { IsOwnerOfFloorFurniture, LocalizeText, NotificationUtilities, SendMessageComposer, WiredSelectionVisualizer } from '../../api'; import { IsOwnerOfFloorFurniture, LocalizeText, SendMessageComposer, WiredSelectionVisualizer } from '../../api';
import { WiredSelectObjectEvent } from '../../events'; import { WiredSelectObjectEvent } from '../../events';
import { useMessageEvent, useUiEvent } from '../events'; import { useMessageEvent, useUiEvent } from '../events';
import { useNotification } from '../notification';
const useWiredState = () => const useWiredState = () =>
{ {
@ -12,6 +13,7 @@ const useWiredState = () =>
const [ stringParam, setStringParam ] = useState<string>(''); const [ stringParam, setStringParam ] = useState<string>('');
const [ furniIds, setFurniIds ] = useState<number[]>([]); const [ furniIds, setFurniIds ] = useState<number[]>([]);
const [ actionDelay, setActionDelay ] = useState<number>(0); const [ actionDelay, setActionDelay ] = useState<number>(0);
const { showConfirm = null } = useNotification();
const saveWired = () => const saveWired = () =>
{ {
@ -37,7 +39,7 @@ const useWiredState = () =>
if(!IsOwnerOfFloorFurniture(trigger.id)) if(!IsOwnerOfFloorFurniture(trigger.id))
{ {
NotificationUtilities.confirm(LocalizeText('wiredfurni.nonowner.change.confirm.body'), () => showConfirm(LocalizeText('wiredfurni.nonowner.change.confirm.body'), () =>
{ {
save(trigger) save(trigger)
}, null, null, null, LocalizeText('wiredfurni.nonowner.change.confirm.title')); }, null, null, null, LocalizeText('wiredfurni.nonowner.change.confirm.title'));