From 83068abf0cf231d64ade6229ecd59a3a1e9e1e7c Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 4 Jan 2022 02:33:18 -0500 Subject: [PATCH] Add confirm dialog --- src/App.tsx | 1 + .../handlers/RoomWidgetChatInputHandler.ts | 12 ++-- .../NotificationConfirmEvent.ts | 62 +++++++++++++++++ src/events/notification-center/index.ts | 1 + .../NotificationCenterView.tsx | 44 +++++++++++- .../common/NotificationConfirmItem.ts | 67 +++++++++++++++++++ .../common/NotificationConfirmType.ts | 4 ++ .../common/NotificationUtilities.ts | 13 +++- .../confirm-layouts/GetConfirmLayout.tsx | 15 +++++ .../NotificationConfirmLayoutView.types.ts | 7 ++ .../NotificationDefaultConfirmView.tsx | 38 +++++++++++ 11 files changed, 257 insertions(+), 7 deletions(-) create mode 100644 src/events/notification-center/NotificationConfirmEvent.ts create mode 100644 src/views/notification-center/common/NotificationConfirmItem.ts create mode 100644 src/views/notification-center/common/NotificationConfirmType.ts create mode 100644 src/views/notification-center/views/confirm-layouts/GetConfirmLayout.tsx create mode 100644 src/views/notification-center/views/confirm-layouts/NotificationConfirmLayoutView.types.ts create mode 100644 src/views/notification-center/views/confirm-layouts/default/NotificationDefaultConfirmView.tsx diff --git a/src/App.tsx b/src/App.tsx index b6106abb..59094326 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -127,6 +127,7 @@ export const App: FC<{}> = props => return (
+
{ (!isReady || isError) && } diff --git a/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts b/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts index 9e6f234b..b286dd1a 100644 --- a/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts +++ b/src/api/nitro/room/widgets/handlers/RoomWidgetChatInputHandler.ts @@ -1,9 +1,10 @@ import { AvatarExpressionEnum, HabboClubLevelEnum, NitroEvent, RoomControllerLevel, RoomSessionChatEvent, RoomSettingsComposer, RoomWidgetEnum, RoomZoomEvent, TextureUtils } from '@nitrots/nitro-renderer'; import { GetConfiguration, GetNitroInstance } from '../../..'; -import { GetRoomEngine, GetSessionDataManager } from '../../../..'; +import { GetRoomEngine, GetSessionDataManager, LocalizeText } from '../../../..'; import { FloorplanEditorEvent } from '../../../../../events/floorplan-editor/FloorplanEditorEvent'; import { dispatchUiEvent } from '../../../../../hooks'; import { SendMessageHook } from '../../../../../hooks/messages'; +import { NotificationUtilities } from '../../../../../views/notification-center/common/NotificationUtilities'; import { RoomWidgetFloodControlEvent, RoomWidgetUpdateEvent } from '../events'; import { RoomWidgetChatMessage, RoomWidgetChatSelectAvatarMessage, RoomWidgetChatTypingMessage, RoomWidgetMessage, RoomWidgetRequestWidgetMessage } from '../messages'; import { RoomWidgetHandler } from './RoomWidgetHandler'; @@ -127,10 +128,11 @@ export class RoomWidgetChatInputHandler extends RoomWidgetHandler newWindow.document.write(image.outerHTML); return null; case ':pickall': - // this.container.notificationService.alertWithConfirm('${room.confirm.pick_all}', '${generic.alert.title}', () => - // { - // GetSessionDataManager().sendSpecialCommandMessage(':pickall'); - // }); + NotificationUtilities.confirm(LocalizeText('room.confirm.pick_all'), () => + { + GetSessionDataManager().sendSpecialCommandMessage(':pickall'); + }, + null, null, null, LocalizeText('generic.alert.title')); return null; case ':furni': diff --git a/src/events/notification-center/NotificationConfirmEvent.ts b/src/events/notification-center/NotificationConfirmEvent.ts new file mode 100644 index 00000000..6dc1638b --- /dev/null +++ b/src/events/notification-center/NotificationConfirmEvent.ts @@ -0,0 +1,62 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; + +export class NotificationConfirmEvent extends NitroEvent +{ + public static CONFIRM: string = 'NCE_CONFIRM'; + + private _confirmType: string; + private _message: string; + private _onConfirm: Function; + private _onCancel: Function; + private _confirmText: string; + private _cancelText: string; + private _title: string; + + constructor(confirmType: string, message: string, onConfirm: Function, onCancel: Function, confirmText: string, cancelText: string, title: string) + { + super(NotificationConfirmEvent.CONFIRM); + + this._confirmType = confirmType; + this._message = message; + this._onConfirm = onConfirm; + this._onCancel = onCancel; + this._confirmText = confirmText; + this._cancelText = cancelText; + this._title = title; + } + + public get confirmType(): string + { + return this._confirmType; + } + + public get message(): string + { + return this._message; + } + + public get onConfirm(): Function + { + return this._onConfirm; + } + + public get onCancel(): Function + { + return this._onCancel; + } + + public get confirmText(): string + { + return this._confirmText; + } + + public get cancelText(): string + { + return this._cancelText; + } + + public get title(): string + { + return this._title; + } +} diff --git a/src/events/notification-center/index.ts b/src/events/notification-center/index.ts index cac7d708..7eaa0ab2 100644 --- a/src/events/notification-center/index.ts +++ b/src/events/notification-center/index.ts @@ -2,3 +2,4 @@ export * from './NotificationAlertEvent'; export * from './NotificationBubbleEvent'; export * from './NotificationCenterAlertEvent'; export * from './NotificationCenterEvent'; +export * from './NotificationConfirmEvent'; diff --git a/src/views/notification-center/NotificationCenterView.tsx b/src/views/notification-center/NotificationCenterView.tsx index 0367b604..8f74f251 100644 --- a/src/views/notification-center/NotificationCenterView.tsx +++ b/src/views/notification-center/NotificationCenterView.tsx @@ -1,20 +1,23 @@ import { FC, ReactNode, useCallback, useMemo, useState } from 'react'; import { createPortal } from 'react-dom'; -import { NotificationAlertEvent } from '../../events'; +import { NotificationAlertEvent, NotificationConfirmEvent } from '../../events'; import { NotificationBubbleEvent } from '../../events/notification-center/NotificationBubbleEvent'; import { useUiEvent } from '../../hooks/events'; import { NotificationAlertItem } from './common/NotificationAlertItem'; import { NotificationBubbleItem } from './common/NotificationBubbleItem'; import { NotificationBubbleType } from './common/NotificationBubbleType'; +import { NotificationConfirmItem } from './common/NotificationConfirmItem'; import { NotificationCenterMessageHandler } from './NotificationCenterMessageHandler'; import { NotificationCenterViewProps } from './NotificationCenterView.types'; 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([]); const [ bubbleAlerts, setBubbleAlerts ] = useState([]); + const [ confirms, setConfirms ] = useState([]); const onNotificationAlertEvent = useCallback((event: NotificationAlertEvent) => { @@ -36,6 +39,15 @@ export const NotificationCenterView: FC = props => 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 => @@ -62,6 +74,19 @@ export const NotificationCenterView: FC = props => }) }, []); + const closeConfirm = useCallback((item: NotificationConfirmItem) => + { + setConfirms(prevValue => + { + const newConfirms = [ ...prevValue ]; + const index = newConfirms.findIndex(value => (item === value)); + + if(index >= 0) newConfirms.splice(index, 1); + + return newConfirms; + }) + }, []); + const getAlerts = useMemo(() => { if(!alerts || !alerts.length) return null; @@ -101,6 +126,22 @@ export const NotificationCenterView: FC = props => return elements; }, [ bubbleAlerts, closeBubbleAlert ]); + const getConfirms = useMemo(() => + { + if(!confirms || !confirms.length) return null; + + const elements: ReactNode[] = []; + + for(const confirm of confirms) + { + const element = GetConfirmLayout(confirm, () => closeConfirm(confirm)); + + elements.push(element); + } + + return elements; + }, [ confirms, closeConfirm ]); + return ( <> @@ -108,6 +149,7 @@ export const NotificationCenterView: FC = props => { getBubbleAlerts }
{ createPortal(getAlerts, document.getElementById('nitro-alerts-container')) } + { createPortal(getConfirms, document.getElementById('nitro-confirms-container')) } ); } diff --git a/src/views/notification-center/common/NotificationConfirmItem.ts b/src/views/notification-center/common/NotificationConfirmItem.ts new file mode 100644 index 00000000..04556626 --- /dev/null +++ b/src/views/notification-center/common/NotificationConfirmItem.ts @@ -0,0 +1,67 @@ +export class NotificationConfirmItem +{ + private static ITEM_ID: number = -1; + + private _id: number; + private _confirmType: string; + private _message: string; + private _onConfirm: Function; + private _onCancel: Function; + private _confirmText: string; + private _cancelText: string; + private _title: string; + + constructor(confirmType: string, message: string, onConfirm: Function, onCancel: Function, confirmText: string, cancelText: string, title: string) + { + NotificationConfirmItem.ITEM_ID += 1; + + this._id = NotificationConfirmItem.ITEM_ID; + this._confirmType = confirmType; + this._message = message; + this._onConfirm = onConfirm; + this._onCancel = onCancel; + this._confirmText = confirmText; + this._cancelText = cancelText; + this._title = title; + } + + public get id(): number + { + return this._id; + } + + public get confirmType(): string + { + return this._confirmType; + } + + public get message(): string + { + return this._message; + } + + public get onConfirm(): Function + { + return this._onConfirm; + } + + public get onCancel(): Function + { + return this._onCancel; + } + + public get confirmText(): string + { + return this._confirmText; + } + + public get cancelText(): string + { + return this._cancelText; + } + + public get title(): string + { + return this._title; + } +} diff --git a/src/views/notification-center/common/NotificationConfirmType.ts b/src/views/notification-center/common/NotificationConfirmType.ts new file mode 100644 index 00000000..533ca053 --- /dev/null +++ b/src/views/notification-center/common/NotificationConfirmType.ts @@ -0,0 +1,4 @@ +export class NotificationConfirmType +{ + public static DEFAULT: string = 'default'; +} diff --git a/src/views/notification-center/common/NotificationUtilities.ts b/src/views/notification-center/common/NotificationUtilities.ts index c4dd1bd9..ca72d308 100644 --- a/src/views/notification-center/common/NotificationUtilities.ts +++ b/src/views/notification-center/common/NotificationUtilities.ts @@ -1,6 +1,6 @@ import { HabboWebTools, RoomEnterEffect } from '@nitrots/nitro-renderer'; import { CreateLinkEvent, GetConfiguration, GetNitroInstance, LocalizeText } from '../../../api'; -import { NotificationAlertEvent } from '../../../events'; +import { NotificationAlertEvent, NotificationConfirmEvent } from '../../../events'; import { NotificationBubbleEvent } from '../../../events/notification-center/NotificationBubbleEvent'; import { dispatchUiEvent } from '../../../hooks'; import { CatalogPageName } from '../../catalog/common/CatalogPageName'; @@ -112,6 +112,17 @@ export class NotificationUtilities 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, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null): void { if(!title || !title.length) title = LocalizeText('notifications.broadcast.title'); diff --git a/src/views/notification-center/views/confirm-layouts/GetConfirmLayout.tsx b/src/views/notification-center/views/confirm-layouts/GetConfirmLayout.tsx new file mode 100644 index 00000000..5a34a2db --- /dev/null +++ b/src/views/notification-center/views/confirm-layouts/GetConfirmLayout.tsx @@ -0,0 +1,15 @@ +import { NotificationConfirmItem } from '../../common/NotificationConfirmItem'; +import { NotificationDefaultConfirmView } from './default/NotificationDefaultConfirmView'; + +export const GetConfirmLayout = (item: NotificationConfirmItem, close: () => void) => +{ + if(!item) return null; + + const props = { key: item.id, item, close }; + + switch(item.confirmType) + { + default: + return + } +} diff --git a/src/views/notification-center/views/confirm-layouts/NotificationConfirmLayoutView.types.ts b/src/views/notification-center/views/confirm-layouts/NotificationConfirmLayoutView.types.ts new file mode 100644 index 00000000..fbddeb27 --- /dev/null +++ b/src/views/notification-center/views/confirm-layouts/NotificationConfirmLayoutView.types.ts @@ -0,0 +1,7 @@ +import { NotificationConfirmItem } from '../../common/NotificationConfirmItem'; + +export interface NotificationConfirmLayoutViewProps +{ + item: NotificationConfirmItem; + close: () => void; +} diff --git a/src/views/notification-center/views/confirm-layouts/default/NotificationDefaultConfirmView.tsx b/src/views/notification-center/views/confirm-layouts/default/NotificationDefaultConfirmView.tsx new file mode 100644 index 00000000..8446562d --- /dev/null +++ b/src/views/notification-center/views/confirm-layouts/default/NotificationDefaultConfirmView.tsx @@ -0,0 +1,38 @@ +import { DetailsHTMLAttributes, FC } from 'react'; +import { NotificationAlertView } from '../../../../../layout'; +import { NotificationConfirmLayoutViewProps } from '../NotificationConfirmLayoutView.types'; + +export interface NotificationDefaultConfirmViewProps extends NotificationConfirmLayoutViewProps, DetailsHTMLAttributes +{ + +} + +export const NotificationDefaultConfirmView: FC = props => +{ + const { item = null, close = null, ...rest } = props; + const { message = null, onConfirm = null, onCancel = null, confirmText = null, cancelText = null, title = null } = item; + + const confirm = () => + { + if(onConfirm) onConfirm(); + + close(); + } + + const cancel = () => + { + if(onCancel) onCancel(); + + close(); + } + + return ( + + { message } +
+ + +
+
+ ); +}