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 './TradeState';
export * from './TradeUserData';
export * from './TradingNotificationMessage';
export * from './TradingNotificationType';
export * from './TradingUtilities';
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 './GetNitroInstance';
export * from './GetTicker';
export * from './OpenUrl';
export * from './RemoveLinkEventTracker';
export * from './RemoveWorkerEventTracker';
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 './NotificationConfirmItem';
export * from './NotificationConfirmType';
export * from './NotificationUtilities';

View File

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

View File

@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { RedeemVoucherMessageComposer, VoucherRedeemErrorMessageEvent, VoucherRedeemOkMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../api';
import { LocalizeText, SendMessageComposer } from '../../../../../api';
import { Button, Flex } from '../../../../../common';
import { useMessageEvent } from '../../../../../hooks';
import { useMessageEvent, useNotification } from '../../../../../hooks';
export interface CatalogRedeemVoucherViewProps
{
@ -15,6 +15,7 @@ export const CatalogRedeemVoucherView: FC<CatalogRedeemVoucherViewProps> = props
const { text = null } = props;
const [ voucher, setVoucher ] = useState<string>('');
const [ isWaiting, setIsWaiting ] = useState(false);
const { simpleAlert = null } = useNotification();
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 ]);
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);
setVoucher('');
}, []);
}, [ simpleAlert ]);
useMessageEvent(VoucherRedeemOkMessageEvent, onVoucherRedeemOkMessageEvent);
@ -45,10 +46,10 @@ export const CatalogRedeemVoucherView: FC<CatalogRedeemVoucherViewProps> = props
{
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);
}, []);
}, [ simpleAlert ]);
useMessageEvent(VoucherRedeemErrorMessageEvent, onVoucherRedeemErrorMessageEvent);

View File

@ -1,8 +1,8 @@
import { CancelMarketplaceOfferMessageComposer, GetMarketplaceOwnOffersMessageComposer, MarketplaceCancelOfferResultEvent, MarketplaceOwnOffersEvent, RedeemMarketplaceOfferCreditsMessageComposer } from '@nitrots/nitro-renderer';
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 { useMessageEvent } from '../../../../../../hooks';
import { useMessageEvent, useNotification } from '../../../../../../hooks';
import { CatalogLayoutProps } from '../CatalogLayout.types';
import { CatalogLayoutMarketplaceItemView, OWN_OFFER } from './CatalogLayoutMarketplaceItemView';
import { MarketplaceOfferData } from './common/MarketplaceOfferData';
@ -12,6 +12,7 @@ export const CatalogLayoutMarketplaceOwnItemsView: FC<CatalogLayoutProps> = prop
{
const [ creditsWaiting, setCreditsWaiting ] = useState(0);
const [ offers, setOffers ] = useState<MarketplaceOfferData[]>([]);
const { simpleAlert = null } = useNotification();
const onMarketPlaceOwnOffersEvent = useCallback((event: MarketplaceOwnOffersEvent) =>
{
@ -42,13 +43,13 @@ export const CatalogLayoutMarketplaceOwnItemsView: FC<CatalogLayoutProps> = prop
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;
}
setOffers(prevValue => prevValue.filter(value => (value.offerId !== parser.offerId)));
}, []);
}, [ simpleAlert ]);
useMessageEvent(MarketplaceCancelOfferResultEvent, onMarketplaceCancelOfferResultEvent);

View File

@ -1,8 +1,8 @@
import { BuyMarketplaceOfferMessageComposer, GetMarketplaceOffersMessageComposer, MarketplaceBuyOfferResultEvent, MarketPlaceOffersEvent } from '@nitrots/nitro-renderer';
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 { useMessageEvent, usePurse } from '../../../../../../hooks';
import { useMessageEvent, useNotification, usePurse } from '../../../../../../hooks';
import { CatalogLayoutProps } from '../CatalogLayout.types';
import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView';
import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView';
@ -25,6 +25,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
const [ offers, setOffers ] = useState(new Map<number, MarketplaceOfferData>());
const [ lastSearch, setLastSearch ] = useState<IMarketplaceSearchOptions>({ minPrice: -1, maxPrice: -1, query: '', type: 3 });
const { getCurrencyAmount = null } = usePurse();
const { simpleAlert = null, showConfirm = null } = useNotification();
const requestOffers = useCallback((options: IMarketplaceSearchOptions) =>
{
@ -50,18 +51,18 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
{
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;
}
const offerId = offerData.offerId;
NotificationUtilities.confirm(LocalizeText('catalog.marketplace.confirm_header'), () =>
showConfirm(LocalizeText('catalog.marketplace.confirm_header'), () =>
{
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(offerId));
},
null, null, null, LocalizeText('catalog.marketplace.confirm_title'));
}, [ getCurrencyAmount ]);
}, [ getCurrencyAmount, simpleAlert, showConfirm ]);
const onMarketPlaceOffersEvent = useCallback( (event: MarketPlaceOffersEvent) =>
{
@ -99,7 +100,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
newVal.delete(parser.requestedOfferId);
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;
case 3:
// our shit was updated
@ -121,7 +122,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
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() ]), () =>
{
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(parser.offerId));
@ -129,10 +130,10 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
null, null, null, LocalizeText('catalog.marketplace.confirm_higher_title'));
break;
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;
}
}, [ lastSearch, requestOffers ]);
}, [ lastSearch, requestOffers, simpleAlert, showConfirm ]);
useMessageEvent(MarketPlaceOffersEvent, onMarketPlaceOffersEvent);
useMessageEvent(MarketplaceBuyOfferResultEvent, onMarketplaceBuyOfferResultEvent);

View File

@ -1,9 +1,9 @@
import { GetMarketplaceConfigurationMessageComposer, MakeOfferMessageComposer, MarketplaceConfigurationEvent } from '@nitrots/nitro-renderer';
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 { CatalogPostMarketplaceOfferEvent } from '../../../../../../events';
import { useCatalog, useMessageEvent, useUiEvent } from '../../../../../../hooks';
import { useCatalog, useMessageEvent, useNotification, useUiEvent } from '../../../../../../hooks';
export const MarketplacePostOfferView : FC<{}> = props =>
{
@ -11,6 +11,7 @@ export const MarketplacePostOfferView : FC<{}> = props =>
const [ askingPrice, setAskingPrice ] = useState(0);
const { catalogOptions = null, setCatalogOptions = null } = useCatalog();
const { marketplaceConfiguration = null } = catalogOptions;
const { showConfirm = null } = useNotification();
const onMarketplaceConfigurationEvent = useCallback((event: MarketplaceConfigurationEvent) =>
{
@ -58,7 +59,7 @@ export const MarketplacePostOfferView : FC<{}> = props =>
{
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));
setItem(null);

View File

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

View File

@ -1,7 +1,8 @@
import { GroupInformationParser, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
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 { useNotification } from '../../../hooks';
const STATES: string[] = [ 'regular', 'exclusive', 'private' ];
@ -15,6 +16,7 @@ interface GroupInformationViewProps extends GridProps
export const GroupInformationView: FC<GroupInformationViewProps> = props =>
{
const { groupInformation = null, onClose = null, overflow = 'hidden', ...rest } = props;
const { showConfirm = null } = useNotification();
const isRealOwner = (groupInformation && (groupInformation.ownerName === GetSessionDataManager().userName));
@ -22,7 +24,7 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
const leaveGroup = () =>
{
NotificationUtilities.confirm(LocalizeText('group.leaveconfirm.desc'), () =>
showConfirm(LocalizeText('group.leaveconfirm.desc'), () =>
{
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));

View File

@ -1,9 +1,9 @@
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 { 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 { useMessageEvent } from '../../../hooks';
import { useMessageEvent, useNotification } from '../../../hooks';
export const GroupMembersView: FC<{}> = props =>
{
@ -14,6 +14,7 @@ export const GroupMembersView: FC<{}> = props =>
const [ totalPages, setTotalPages ] = useState<number>(0);
const [ searchQuery, setSearchQuery ] = useState<string>('');
const [ removingMemberName, setRemovingMemberName ] = useState<string>(null);
const { showConfirm = null } = useNotification();
const getRankDescription = (member: GroupMemberParser) =>
{
@ -87,7 +88,7 @@ export const GroupMembersView: FC<{}> = props =>
{
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));
@ -95,7 +96,7 @@ export const GroupMembersView: FC<{}> = props =>
}, null);
setRemovingMemberName(null);
}, [ membersData, removingMemberName, refreshMembers ]);
}, [ membersData, removingMemberName, refreshMembers, showConfirm ]);
useMessageEvent(GroupConfirmMemberRemoveEvent, onGroupConfirmMemberRemoveEvent);

View File

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

View File

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

View File

@ -1,11 +1,13 @@
import { CallForHelpResultMessageEvent, GetPendingCallsForHelpMessageComposer, IssueCloseNotificationMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
import { CallForHelpResult, GetCloseReasonKey, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../api';
import { useMessageEvent } from '../../hooks';
import { FC } from 'react';
import { CallForHelpResult, GetCloseReasonKey, LocalizeText, NotificationAlertType, SendMessageComposer } from '../../api';
import { useMessageEvent, useNotification } from '../../hooks';
export const HelpMessageHandler: FC<{}> = props =>
{
const onCallForHelpResultMessageEvent = useCallback((event: CallForHelpResultMessageEvent) =>
const { simpleAlert = null } = useNotification();
useMessageEvent<CallForHelpResultMessageEvent>(CallForHelpResultMessageEvent, event =>
{
const parser = event.getParser();
@ -15,32 +17,29 @@ export const HelpMessageHandler: FC<{}> = props =>
{
case CallForHelpResult.TOO_MANY_PENDING_CALLS_CODE:
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;
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;
default:
if(message.trim().length === 0)
{
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);
const onIssueCloseNotificationMessageEvent = useCallback((event: IssueCloseNotificationMessageEvent) =>
useMessageEvent<IssueCloseNotificationMessageEvent>(IssueCloseNotificationMessageEvent, event =>
{
const parser = event.getParser();
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'));
}, []);
useMessageEvent(IssueCloseNotificationMessageEvent, onIssueCloseNotificationMessageEvent);
simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('mod.alert.title'));
});
return null;
}

View File

@ -1,6 +1,6 @@
import { GetPromoArticlesComposer, PromoArticleData, PromoArticlesMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../api';
import { LocalizeText, OpenUrl, SendMessageComposer } from '../../../../../api';
import { useMessageEvent } from '../../../../../hooks';
export const PromoArticleWidgetView: FC<{}> = props =>
@ -40,7 +40,7 @@ export const PromoArticleWidgetView: FC<{}> = props =>
<div className="col-3 d-flex flex-column h-100">
<h3 className="my-0">{ articles[index].title }</h3>
<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>

View File

@ -1,5 +1,5 @@
import { FC, useCallback } from 'react';
import { GetConfigurationManager, LocalizeText, NotificationUtilities } from '../../../../../api';
import { GetConfigurationManager, LocalizeText, OpenUrl } from '../../../../../api';
export interface WidgetContainerViewProps
{
@ -31,7 +31,7 @@ export const WidgetContainerView: FC<WidgetContainerViewProps> = props =>
<div className="d-flex flex-column align-self-center">
<h3 className="my-0">{ LocalizeText(`landing.view.${ getOption('texts') }.header`) }</h3>
<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>
);

View File

@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
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 { useInventoryTrade } from '../../../../hooks';
import { useInventoryTrade, useNotification } from '../../../../hooks';
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
interface InventoryTradeViewProps
@ -22,6 +22,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
const [ countdownTick, setCountdownTick ] = useState(3);
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) =>
{
@ -105,7 +106,7 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
}
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 { NotificationUtilities } from '../../api';
import { FC } from 'react';
import { Base, Column, LayoutProgressBar, Text } from '../../common';
interface LoadingViewProps
@ -12,13 +11,6 @@ interface LoadingViewProps
export const LoadingView: FC<LoadingViewProps> = props =>
{
const { isError = false, message = '', percent = 0 } = props;
useEffect(() =>
{
if(!isError) return;
NotificationUtilities.simpleAlert(message, null, null, null, 'Connection Error');
}, [ isError, message ]);
return (
<Column fullHeight position="relative" className="nitro-loading">

View File

@ -1,8 +1,8 @@
import { CfhSanctionMessageEvent, CfhTopicsInitEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ModeratorActionResultMessageEvent, ModeratorInitMessageEvent, ModeratorToolPreferencesEvent, RoomEngineEvent } from '@nitrots/nitro-renderer';
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 { useMessageEvent, useRoomEngineEvent, useUiEvent } from '../../hooks';
import { useMessageEvent, useNotification, useRoomEngineEvent, useUiEvent } from '../../hooks';
import { SetCfhCategories } from './common/GetCFHCategories';
import { useModToolsContext } from './ModToolsContext';
import { ModToolsActions } from './reducers/ModToolsReducer';
@ -11,6 +11,7 @@ export const ModToolsMessageHandler: FC<{}> = props =>
{
const { modToolsState = null, dispatchModToolsState = null } = useModToolsContext();
const { openRooms = null, openRoomChatlogs = null, openUserChatlogs = null, openUserInfo = null, tickets= null } = modToolsState;
const { simpleAlert = null } = useNotification();
const onModeratorInitMessageEvent = useCallback((event: ModeratorInitMessageEvent) =>
{
@ -78,8 +79,8 @@ export const ModToolsMessageHandler: FC<{}> = props =>
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) =>
{
@ -110,13 +111,13 @@ export const ModToolsMessageHandler: FC<{}> = props =>
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
{
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) =>
{

View File

@ -1,7 +1,8 @@
import { CallForHelpTopicData, DefaultSanctionMessageComposer, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModTradingLockMessageComposer } from '@nitrots/nitro-renderer';
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 { useNotification } from '../../../../hooks';
import { ISelectedUser } from '../../common/ISelectedUser';
import { ModActionDefinition } from '../../common/ModActionDefinition';
import { useModToolsContext } from '../../ModToolsContext';
@ -35,6 +36,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
const [ message, setMessage ] = useState<string>('');
const { modToolsState = null } = useModToolsContext();
const { cfhCategories = null, settings = null } = modToolsState;
const { simpleAlert = null } = useNotification();
const topics = useMemo(() =>
{
@ -53,7 +55,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
const sendAlert = (message: string) =>
{
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, 'Error');
simpleAlert(message, NotificationAlertType.DEFAULT, null, null, 'Error');
}
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 { FC, useCallback } from 'react';
import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api';
import { useMessageEvent } from '../../hooks';
import { CreateLinkEvent, CreateRoomSession, DoorStateType, GetConfiguration, GetSessionDataManager, LocalizeText, NotificationAlertType, SendMessageComposer, TryVisitRoom, VisitDesktop } from '../../api';
import { useMessageEvent, useNotification } from '../../hooks';
import { useNavigatorContext } from './NavigatorContext';
export const NavigatorMessageHandler: FC<{}> = props =>
{
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) =>
{
@ -28,8 +29,8 @@ export const NavigatorMessageHandler: FC<{}> = props =>
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);
@ -249,23 +250,23 @@ export const NavigatorMessageHandler: FC<{}> = props =>
});
return;
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;
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;
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;
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;
}
}, [ setDoorData ]);
}, [ setDoorData, simpleAlert ]);
const onNavigatorMetadataEvent = useCallback((event: NavigatorMetadataEvent) =>
{
@ -397,25 +398,25 @@ export const NavigatorMessageHandler: FC<{}> = props =>
switch(parser.reason)
{
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;
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;
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;
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;
}
VisitDesktop();
}, []);
}, [ simpleAlert ]);
const onRoomCreatorEvent = useCallback((event: NavigatorOpenRoomCreatorEvent) =>
{

View File

@ -1,8 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { RoomDeleteComposer } from '@nitrots/nitro-renderer';
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 { useNotification } from '../../../../hooks';
import { useNavigatorContext } from '../../NavigatorContext';
const ROOM_NAME_MIN_LENGTH = 3;
@ -22,11 +23,12 @@ export const NavigatorRoomSettingsBasicTabView: FC<NavigatorRoomSettingsTabViewP
const { roomData = null, handleChange = null, close = null } = props;
const [ roomName, setRoomName ] = useState<string>('');
const [ roomDescription, setRoomDescription ] = useState<string>('');
const { showConfirm = null } = useNotification();
const { categories = null } = useNavigatorContext();
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));

View File

@ -1,6 +1,6 @@
import { NitroLogger } from '@nitrots/nitro-renderer';
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';
const NEW_LINE_REGEX = /\n\r|\n|\r/mg;
@ -80,7 +80,7 @@ export const NitropediaView: FC<{}> = props =>
if(!link || !link.length) return;
NotificationUtilities.openUrl(link);
OpenUrl(link);
}
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 { NotificationAlertItem, NotificationBubbleItem, NotificationBubbleType, NotificationConfirmItem } from '../../api';
import { FC, ReactNode, useMemo } from 'react';
import { NotificationBubbleType } from '../../api';
import { Column } from '../../common';
import { NotificationAlertEvent, NotificationBubbleEvent, NotificationConfirmEvent } from '../../events';
import { useUiEvent } from '../../hooks';
import { NotificationCenterMessageHandler } from './NotificationCenterMessageHandler';
import { useNotification } from '../../hooks';
import { GetAlertLayout } from './views/alert-layouts/GetAlertLayout';
import { GetBubbleLayout } from './views/bubble-layouts/GetBubbleLayout';
import { GetConfirmLayout } from './views/confirm-layouts/GetConfirmLayout';
export const NotificationCenterView: FC<{}> = props =>
{
const [ alerts, setAlerts ] = useState<NotificationAlertItem[]>([]);
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 { alerts = [], bubbleAlerts = [], confirms = [], closeAlert = null, closeBubbleAlert = null, closeConfirm = null } = useNotification();
const getAlerts = useMemo(() =>
{
@ -137,7 +67,6 @@ export const NotificationCenterView: FC<{}> = props =>
return (
<>
<NotificationCenterMessageHandler />
<Column gap={ 1 }>
{ getBubbleAlerts }
</Column>

View File

@ -1,5 +1,5 @@
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';
interface NotificationDefaultAlertViewProps extends LayoutNotificationAlertViewProps
@ -15,7 +15,7 @@ export const NotificationDefaultAlertView: FC<NotificationDefaultAlertViewProps>
const visitUrl = useCallback(() =>
{
NotificationUtilities.openUrl(item.clickUrl);
OpenUrl(item.clickUrl);
close();
}, [ item, close ]);

View File

@ -1,5 +1,5 @@
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';
interface NotificationDefaultAlertViewProps extends LayoutNotificationAlertViewProps
@ -16,7 +16,7 @@ export const NotificationSeachAlertView: FC<NotificationDefaultAlertViewProps> =
const visitUrl = useCallback(() =>
{
NotificationUtilities.openUrl(item.clickUrl);
OpenUrl(item.clickUrl);
close();
}, [ item, close ]);

View File

@ -1,5 +1,5 @@
import { FC } from 'react';
import { LocalizeText, NotificationBubbleItem, NotificationUtilities } from '../../../../api';
import { LocalizeText, NotificationBubbleItem, OpenUrl } from '../../../../api';
import { LayoutCurrencyIcon, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps } from '../../../../common';
export interface NotificationClubGiftBubbleViewProps extends LayoutNotificationBubbleViewProps
@ -18,7 +18,7 @@ export const NotificationClubGiftBubbleView: FC<NotificationClubGiftBubbleViewPr
<span className="ms-1">{ LocalizeText('notifications.text.club_gift') }</span>
</div>
<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>
</div>
</LayoutNotificationBubbleView>

View File

@ -1,5 +1,5 @@
import { FC } from 'react';
import { NotificationBubbleItem, NotificationUtilities } from '../../../../api';
import { NotificationBubbleItem, OpenUrl } from '../../../../api';
import { Flex, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps, Text } from '../../../../common';
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 />');
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">
{ (item.iconUrl && item.iconUrl.length) &&
<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 { FC } from 'react';
import { DispatchUiEvent, GetRoomEngine, LocalizeText, NotificationAlertType, NotificationUtilities, RoomWidgetUpdateRoomObjectEvent } from '../../../api';
import { useRoom, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../../hooks';
import { DispatchUiEvent, GetRoomEngine, LocalizeText, NotificationAlertType, RoomWidgetUpdateRoomObjectEvent } from '../../../api';
import { useNotification, useRoom, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../../hooks';
import { AvatarInfoWidgetView } from './avatar-info/AvatarInfoWidgetView';
import { ChatInputView } from './chat-input/ChatInputView';
import { ChatWidgetView } from './chat/ChatWidgetView';
@ -17,6 +17,7 @@ import { WordQuizWidgetView } from './word-quiz/WordQuizWidgetView';
export const RoomWidgetsView: FC<{}> = props =>
{
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));
@ -146,7 +147,7 @@ export const RoomWidgetsView: FC<{}> = props =>
return;
}
NotificationUtilities.simpleAlert(errorMessage, NotificationAlertType.DEFAULT, null, null, errorTitle);
simpleAlert(errorMessage, NotificationAlertType.DEFAULT, null, null, errorTitle);
});
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 { useCallback, useEffect, useRef, useState } from 'react';
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 { useMessageEvent, useRoomEngineEvent, useUiEvent } from '../events';
import { useNotification } from '../notification';
import { useCatalogPlaceMultipleItems } from './useCatalogPlaceMultipleItems';
import { useCatalogSkipPurchaseConfirmation } from './useCatalogSkipPurchaseConfirmation';
@ -39,6 +40,7 @@ const useCatalogState = () =>
const [ secondsLeft, setSecondsLeft ] = useState(0);
const [ updateTime, setUpdateTime ] = useState(0);
const [ secondsLeftWithGrace, setSecondsLeftWithGrace ] = useState(0);
const { simpleAlert = null } = useNotification();
const requestedPage = useRef(new RequestedPage());
const resetState = useCallback(() =>
@ -657,8 +659,8 @@ const useCatalogState = () =>
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);
@ -682,8 +684,8 @@ const useCatalogState = () =>
resetState();
if(wasVisible) NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.published.description'), NotificationAlertType.ALERT, null, null, LocalizeText('catalog.alert.published.title'));
}, [ isVisible, resetState ]);
if(wasVisible) simpleAlert(LocalizeText('catalog.alert.published.description'), NotificationAlertType.ALERT, null, null, LocalizeText('catalog.alert.published.title'));
}, [ isVisible, resetState, simpleAlert ]);
useMessageEvent(CatalogPublishedMessageEvent, onCatalogPublishedMessageEvent);

View File

@ -1,8 +1,9 @@
import { NewConsoleMessageEvent, RoomInviteErrorEvent, RoomInviteEvent, SendMessageComposer as SendMessageComposerPacket } from '@nitrots/nitro-renderer';
import { useCallback, useEffect, useMemo, useState } from 'react';
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 { useNotification } from '../notification';
import { useFriends } from './useFriends';
const useMessengerState = () =>
@ -12,6 +13,7 @@ const useMessengerState = () =>
const [ hiddenThreadIds, setHiddenThreadIds ] = useState<number[]>([]);
const [ iconState, setIconState ] = useState<number>(MessengerIconState.HIDDEN);
const { getFriend = null } = useFriends();
const { simpleAlert = null } = useNotification();
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 ]);
@ -94,7 +96,7 @@ const useMessengerState = () =>
});
}
const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) =>
useMessageEvent<NewConsoleMessageEvent>(NewConsoleMessageEvent, event =>
{
const parser = event.getParser();
@ -131,11 +133,9 @@ const useMessengerState = () =>
return newValue;
});
}, [ activeThreadId, getFriend ]);
});
useMessageEvent(NewConsoleMessageEvent, onNewConsoleMessageEvent);
const onRoomInviteEvent = useCallback((event: RoomInviteEvent) =>
useMessageEvent<RoomInviteEvent>(RoomInviteEvent, event =>
{
const parser = event.getParser();
@ -172,19 +172,15 @@ const useMessengerState = () =>
return newValue;
});
}, [ activeThreadId, getFriend ]);
});
useMessageEvent(RoomInviteEvent, onRoomInviteEvent);
const onRoomInviteErrorEvent = useCallback((event: RoomInviteErrorEvent) =>
useMessageEvent<RoomInviteErrorEvent>(RoomInviteErrorEvent, event =>
{
const parser = event.getParser();
const message = ((('Received room invite error: errorCode: ' + parser.errorCode) + ', recipients: ') + parser.failedRecipients);
NotificationUtilities.simpleAlert(message, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title'));
}, []);
useMessageEvent(RoomInviteErrorEvent, onRoomInviteErrorEvent);
simpleAlert(message, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title'));
});
useEffect(() =>
{

View File

@ -9,6 +9,7 @@ export * from './friends';
export * from './groups';
export * from './inventory';
export * from './navigator';
export * from './notification';
export * from './purse';
export * from './rooms';
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 { useEffect, useState } from 'react';
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 { useNotification } from '../notification';
import { useInventoryFurni } from './useInventoryFurni';
const useInventoryTradeState = () =>
@ -11,6 +12,7 @@ const useInventoryTradeState = () =>
const [ otherUser, setOtherUser ] = useState<TradeUserData>(null);
const [ tradeState, setTradeState ] = useState(TradeState.TRADING_STATE_READY);
const { groupItems = [], setGroupItems = null, activate = null, deactivate = null } = useInventoryFurni();
const { simpleAlert = null, showTradeAlert = null } = useNotification();
const isTrading = (tradeState >= TradeState.TRADING_STATE_RUNNING);
const progressTrade = () =>
@ -20,7 +22,7 @@ const useInventoryTradeState = () =>
case TradeState.TRADING_STATE_RUNNING:
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)
@ -101,13 +103,13 @@ const useInventoryTradeState = () =>
if(parser.reason === TradingCloseParser.ERROR_WHILE_COMMIT)
{
TradingNotificationMessage(TradingNotificationType.ERROR_WHILE_COMMIT);
showTradeAlert(TradingNotificationType.ERROR_WHILE_COMMIT);
}
else
{
if(ownUser && (parser.userID !== ownUser.userId))
{
TradingNotificationMessage(TradingNotificationType.THEY_CANCELLED);
showTradeAlert(TradingNotificationType.THEY_CANCELLED);
}
}
@ -254,21 +256,21 @@ const useInventoryTradeState = () =>
{
const parser = event.getParser();
TradingNotificationMessage(parser.reason, parser.otherUserName);
showTradeAlert(parser.reason, parser.otherUserName);
});
useMessageEvent<TradingOtherNotAllowedEvent>(TradingOtherNotAllowedEvent, event =>
{
const parser = event.getParser();
TradingNotificationMessage(TradingNotificationType.THEY_NOT_ALLOWED);
showTradeAlert(TradingNotificationType.THEY_NOT_ALLOWED);
});
useMessageEvent<TradingYouAreNotAllowedEvent>(TradingYouAreNotAllowedEvent, event =>
{
const parser = event.getParser();
TradingNotificationMessage(TradingNotificationType.YOU_NOT_ALLOWED);
showTradeAlert(TradingNotificationType.YOU_NOT_ALLOWED);
});
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 { 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 { useNotification } from '../../../notification';
import { useFurniRemovedEvent } from '../../engine';
const useFurnitureBadgeDisplayWidgetState = () =>
@ -13,6 +14,7 @@ const useFurnitureBadgeDisplayWidgetState = () =>
const [ badgeDesc, setBadgeDesc ] = useState('');
const [ date, setDate ] = useState('');
const [ senderName, setSenderName ] = useState('');
const { simpleAlert = null } = useNotification();
const close = () =>
{
@ -57,7 +59,7 @@ const useFurnitureBadgeDisplayWidgetState = () =>
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 =>

View File

@ -1,7 +1,8 @@
import { AvatarExpressionEnum, HabboClubLevelEnum, RoomControllerLevel, RoomEngineObjectEvent, RoomObjectCategory, RoomRotatingEffect, RoomSessionChatEvent, RoomSettingsComposer, RoomShakingEffect, RoomZoomEvent, TextureUtils } from '@nitrots/nitro-renderer';
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 { useNotification } from '../../notification';
import { useObjectSelectedEvent } from '../engine';
import { useRoom } from '../useRoom';
@ -13,6 +14,7 @@ const useChatInputWidgetState = () =>
const [ isIdle, setIsIdle ] = useState(false);
const [ floodBlocked, setFloodBlocked ] = useState(false);
const [ floodBlockedSeconds, setFloodBlockedSeconds ] = useState(0);
const { showNitroAlert = null, showConfirm = null } = useNotification();
const { roomSession = null } = useRoom();
const sendChat = (text: string, chatType: number, recipientName: string = '', styleId: number = 0) =>
@ -122,7 +124,7 @@ const useChatInputWidgetState = () =>
case ':pickall':
if(roomSession.isRoomOwner || GetSessionDataManager().isModerator)
{
NotificationUtilities.confirm(LocalizeText('room.confirm.pick_all'), () =>
showConfirm(LocalizeText('room.confirm.pick_all'), () =>
{
GetSessionDataManager().sendSpecialCommandMessage(':pickall');
},
@ -150,7 +152,7 @@ const useChatInputWidgetState = () =>
case ':client':
case ':nitro':
case ':billsonnn':
NotificationUtilities.showNitroAlert();
showNitroAlert();
return null;
case ':settings':
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 { useEffect, useState } from 'react';
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 { useMessageEvent, useUiEvent } from '../events';
import { useNotification } from '../notification';
const useWiredState = () =>
{
@ -12,6 +13,7 @@ const useWiredState = () =>
const [ stringParam, setStringParam ] = useState<string>('');
const [ furniIds, setFurniIds ] = useState<number[]>([]);
const [ actionDelay, setActionDelay ] = useState<number>(0);
const { showConfirm = null } = useNotification();
const saveWired = () =>
{
@ -37,7 +39,7 @@ const useWiredState = () =>
if(!IsOwnerOfFloorFurniture(trigger.id))
{
NotificationUtilities.confirm(LocalizeText('wiredfurni.nonowner.change.confirm.body'), () =>
showConfirm(LocalizeText('wiredfurni.nonowner.change.confirm.body'), () =>
{
save(trigger)
}, null, null, null, LocalizeText('wiredfurni.nonowner.change.confirm.title'));