mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 06:40:50 +01:00
Merge remote-tracking branch 'origin/@features/notification-center' into dev
This commit is contained in:
commit
1bd4c94680
@ -0,0 +1,19 @@
|
|||||||
|
import { NitroNotification } from '../../views/notification-center/utils/Notification';
|
||||||
|
import { NotificationCenterEvent } from './NotificationCenterEvent';
|
||||||
|
|
||||||
|
export class NotificationCenterAddNotificationEvent extends NotificationCenterEvent
|
||||||
|
{
|
||||||
|
private _notification: NitroNotification;
|
||||||
|
|
||||||
|
constructor(notification: NitroNotification)
|
||||||
|
{
|
||||||
|
super(NotificationCenterEvent.ADD_NOTIFICATION);
|
||||||
|
|
||||||
|
this._notification = notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get notification(): NitroNotification
|
||||||
|
{
|
||||||
|
return this._notification;
|
||||||
|
}
|
||||||
|
}
|
@ -5,4 +5,5 @@ export class NotificationCenterEvent extends NitroEvent
|
|||||||
public static SHOW_NOTIFICATION_CENTER: string = 'NCE_SHOW_NOTIFICATION_CENTER';
|
public static SHOW_NOTIFICATION_CENTER: string = 'NCE_SHOW_NOTIFICATION_CENTER';
|
||||||
public static HIDE_NOTIFICATION_CENTER: string = 'NCE_HIDE_NOTIFICATION_CENTER';
|
public static HIDE_NOTIFICATION_CENTER: string = 'NCE_HIDE_NOTIFICATION_CENTER';
|
||||||
public static TOGGLE_NOTIFICATION_CENTER: string = 'NCE_TOGGLE_NOTIFICATION_CENTER';
|
public static TOGGLE_NOTIFICATION_CENTER: string = 'NCE_TOGGLE_NOTIFICATION_CENTER';
|
||||||
|
public static ADD_NOTIFICATION: string = 'NCE_ADD_NOTIFICATION';
|
||||||
}
|
}
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
export * from './NotificationCenterAddNotificationEvent';
|
||||||
export * from './NotificationCenterEvent';
|
export * from './NotificationCenterEvent';
|
||||||
|
@ -2,6 +2,26 @@
|
|||||||
text-shadow: 2px 2px 0px rgba(0, 0, 0, .2)
|
text-shadow: 2px 2px 0px rgba(0, 0, 0, .2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nitro-close {
|
||||||
|
right: 5px;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
box-shadow: inset 0 0 0 1.5px #921911, inset 0 2px rgba($white, .2);
|
||||||
|
border: 1px solid $white;
|
||||||
|
background: rgb(245,80,65);
|
||||||
|
background: linear-gradient(180deg, rgba(245,80,65,1) 0%, rgba(245,80,65,1) 50%, rgba(194,48,39,1) 50%, rgba(194,48,39,1) 100%);
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 4px 6px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@import './card/NitroCardView';
|
@import './card/NitroCardView';
|
||||||
@import './draggable-window/DraggableWindow';
|
@import './draggable-window/DraggableWindow';
|
||||||
@import './loading-spinner/LoadingSpinnerView';
|
@import './loading-spinner/LoadingSpinnerView';
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
import { HabboBroadcastMessageEvent, HotelWillShutdownEvent, ModeratorMessageEvent, MOTDNotificationEvent, NotificationDialogMessageEvent } from 'nitro-renderer';
|
||||||
|
import { FC, useCallback } from 'react';
|
||||||
|
import { CreateMessageHook } from '../../hooks/messages';
|
||||||
|
import { useNotificationCenterContext } from './context/NotificationCenterContext';
|
||||||
|
import { INotificationCenterMessageHandlerProps } from './NotificationCenterMessageHandler.types';
|
||||||
|
import { NotificationCenterActions } from './reducers/NotificationCenterReducer';
|
||||||
|
import { BroadcastMessageNotification } from './utils/BroadcastMessageNotification';
|
||||||
|
import { DialogMessageNotification } from './utils/DialogMessageNotification';
|
||||||
|
import { HotelWillShutdownNotification } from './utils/HotelWillShutdownNotification';
|
||||||
|
import { ModeratorMessageNotification } from './utils/ModeratorMessageNotification';
|
||||||
|
import { MOTDNotification } from './utils/MOTDNotification';
|
||||||
|
|
||||||
|
export const NotificationCenterMessageHandler: FC<INotificationCenterMessageHandlerProps> = props =>
|
||||||
|
{
|
||||||
|
const { dispatchNotificationCenterState = null } = useNotificationCenterContext();
|
||||||
|
|
||||||
|
const onHabboBroadcastMessageEvent = useCallback((event: HabboBroadcastMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.ADD_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
notification: new BroadcastMessageNotification(parser.message)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [ dispatchNotificationCenterState ]);
|
||||||
|
|
||||||
|
const onNotificationDialogMessageEvent = useCallback((event: NotificationDialogMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.ADD_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
notification: new DialogMessageNotification(parser.type, parser.parameters)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [ dispatchNotificationCenterState ]);
|
||||||
|
|
||||||
|
const onModeratorMessageEvent = useCallback((event: ModeratorMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.ADD_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
notification: new ModeratorMessageNotification(parser.message, parser.link)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [ dispatchNotificationCenterState ]);
|
||||||
|
|
||||||
|
const onMOTDNotificationEvent = useCallback((event: MOTDNotificationEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.ADD_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
notification: new MOTDNotification(parser.messages)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [ dispatchNotificationCenterState ]);
|
||||||
|
|
||||||
|
const onHotelWillShutdownEvent = useCallback((event: HotelWillShutdownEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.ADD_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
notification: new HotelWillShutdownNotification(parser.minutes)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [ dispatchNotificationCenterState ]);
|
||||||
|
|
||||||
|
CreateMessageHook(HabboBroadcastMessageEvent, onHabboBroadcastMessageEvent);
|
||||||
|
CreateMessageHook(NotificationDialogMessageEvent, onNotificationDialogMessageEvent);
|
||||||
|
CreateMessageHook(ModeratorMessageEvent, onModeratorMessageEvent);
|
||||||
|
CreateMessageHook(MOTDNotificationEvent, onMOTDNotificationEvent);
|
||||||
|
CreateMessageHook(HotelWillShutdownEvent, onHotelWillShutdownEvent);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
export interface INotificationCenterMessageHandlerProps
|
||||||
|
{}
|
@ -13,3 +13,12 @@
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nitro-notification {
|
||||||
|
width: 350px;
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useReducer, useState } from 'react';
|
||||||
import { NotificationCenterEvent } from '../../events';
|
import { NotificationCenterAddNotificationEvent, NotificationCenterEvent } from '../../events';
|
||||||
import { useUiEvent } from '../../hooks/events';
|
import { useUiEvent } from '../../hooks/events';
|
||||||
import { TransitionAnimation } from '../../layout/transitions/TransitionAnimation';
|
import { TransitionAnimation } from '../../layout/transitions/TransitionAnimation';
|
||||||
import { TransitionAnimationTypes } from '../../layout/transitions/TransitionAnimation.types';
|
import { TransitionAnimationTypes } from '../../layout/transitions/TransitionAnimation.types';
|
||||||
|
import { NotificationCenterContextProvider } from './context/NotificationCenterContext';
|
||||||
|
import { NotificationCenterMessageHandler } from './NotificationCenterMessageHandler';
|
||||||
import { NotificationCenterViewProps } from './NotificationCenterView.types';
|
import { NotificationCenterViewProps } from './NotificationCenterView.types';
|
||||||
|
import { initialNotificationCenter, NotificationCenterActions, NotificationCenterReducer } from './reducers/NotificationCenterReducer';
|
||||||
|
import { BroadcastMessageNotification } from './utils/BroadcastMessageNotification';
|
||||||
|
import { HotelWillShutdownNotification } from './utils/HotelWillShutdownNotification';
|
||||||
|
import { ModeratorMessageNotification } from './utils/ModeratorMessageNotification';
|
||||||
|
import { MOTDNotification } from './utils/MOTDNotification';
|
||||||
|
import { NitroNotification } from './utils/Notification';
|
||||||
|
import { BroadcastMessageView } from './views/broadcast-message/BroadcastMessageView';
|
||||||
|
import { HotelWillShutdownView } from './views/hotel-will-shutdown/HotelWillShutdownView';
|
||||||
|
import { ModeratorMessageView } from './views/moderator-message/ModeratorMessageView';
|
||||||
|
import { MOTDView } from './views/motd/MOTDView';
|
||||||
|
|
||||||
export const NotificationCenterView: FC<NotificationCenterViewProps> = props =>
|
export const NotificationCenterView: FC<NotificationCenterViewProps> = props =>
|
||||||
{
|
{
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
|
||||||
|
const [ notificationCenterState, dispatchNotificationCenterState ] = useReducer(NotificationCenterReducer, initialNotificationCenter);
|
||||||
|
const { notifications = null } = notificationCenterState;
|
||||||
|
|
||||||
const onNotificationCenterEvent = useCallback((event: NotificationCenterEvent) =>
|
const onNotificationCenterEvent = useCallback((event: NotificationCenterEvent) =>
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
@ -22,19 +37,80 @@ export const NotificationCenterView: FC<NotificationCenterViewProps> = props =>
|
|||||||
case NotificationCenterEvent.TOGGLE_NOTIFICATION_CENTER:
|
case NotificationCenterEvent.TOGGLE_NOTIFICATION_CENTER:
|
||||||
setIsVisible(value => !value);
|
setIsVisible(value => !value);
|
||||||
return;
|
return;
|
||||||
|
case NotificationCenterEvent.ADD_NOTIFICATION: {
|
||||||
|
const castedEvent = (event as NotificationCenterAddNotificationEvent);
|
||||||
|
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.ADD_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
notification: castedEvent.notification
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useUiEvent(NotificationCenterEvent.SHOW_NOTIFICATION_CENTER, onNotificationCenterEvent);
|
useUiEvent(NotificationCenterEvent.SHOW_NOTIFICATION_CENTER, onNotificationCenterEvent);
|
||||||
useUiEvent(NotificationCenterEvent.HIDE_NOTIFICATION_CENTER, onNotificationCenterEvent);
|
useUiEvent(NotificationCenterEvent.HIDE_NOTIFICATION_CENTER, onNotificationCenterEvent);
|
||||||
useUiEvent(NotificationCenterEvent.TOGGLE_NOTIFICATION_CENTER, onNotificationCenterEvent);
|
useUiEvent(NotificationCenterEvent.TOGGLE_NOTIFICATION_CENTER, onNotificationCenterEvent);
|
||||||
|
useUiEvent(NotificationCenterEvent.ADD_NOTIFICATION, onNotificationCenterEvent);
|
||||||
|
|
||||||
|
const handleButtonClick = useCallback((action: string, value: number) =>
|
||||||
|
{
|
||||||
|
if(!action) return;
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
{
|
||||||
|
case 'dismiss_notification':
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.DISMISS_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
id: value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
case 'remove_notification':
|
||||||
|
dispatchNotificationCenterState({
|
||||||
|
type: NotificationCenterActions.REMOVE_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
id: value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [ notificationCenterState, dispatchNotificationCenterState ]);
|
||||||
|
|
||||||
|
const mapNotifications = useCallback((notifications: NitroNotification[], inTray: boolean) =>
|
||||||
|
{
|
||||||
|
if(!notifications) return null;
|
||||||
|
|
||||||
|
return notifications.map(notification =>
|
||||||
|
{
|
||||||
|
if(!inTray && notification.dismissed) return null;
|
||||||
|
|
||||||
|
if(notification instanceof BroadcastMessageNotification)
|
||||||
|
return <BroadcastMessageView key={ notification.id } inTray={ inTray } notification={ notification as BroadcastMessageNotification } onButtonClick={ (action) => handleButtonClick(action, notification.id) } />
|
||||||
|
if(notification instanceof MOTDNotification)
|
||||||
|
return <MOTDView key={ notification.id } inTray={ inTray } notification={ notification as MOTDNotification } onButtonClick={ (action) => handleButtonClick(action, notification.id) } />
|
||||||
|
if(notification instanceof ModeratorMessageNotification)
|
||||||
|
return <ModeratorMessageView key={ notification.id } inTray={ inTray } notification={ notification as ModeratorMessageNotification } onButtonClick={ (action) => handleButtonClick(action, notification.id) } />
|
||||||
|
if(notification instanceof HotelWillShutdownNotification)
|
||||||
|
return <HotelWillShutdownView key={ notification.id } inTray={ inTray } notification={ notification as HotelWillShutdownNotification } onButtonClick={ (action) => handleButtonClick(action, notification.id) } />
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}, [ handleButtonClick ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TransitionAnimation className="nitro-notification-center-container" type={ TransitionAnimationTypes.SLIDE_RIGHT } inProp={ isVisible } timeout={ 300 }>
|
<NotificationCenterContextProvider value={ { notificationCenterState, dispatchNotificationCenterState } }>
|
||||||
<div className="nitro-notification-center">
|
<NotificationCenterMessageHandler />
|
||||||
test
|
<TransitionAnimation className="nitro-notification-center-container" type={ TransitionAnimationTypes.SLIDE_RIGHT } inProp={ isVisible } timeout={ 300 }>
|
||||||
</div>
|
<div className="nitro-notification-center pt-5 px-2">
|
||||||
</TransitionAnimation>
|
{ mapNotifications(notifications, true) }
|
||||||
|
</div>
|
||||||
|
</TransitionAnimation>
|
||||||
|
{ mapNotifications(notifications, false) }
|
||||||
|
</NotificationCenterContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,3 +2,9 @@ export interface NotificationCenterViewProps
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NotificationViewProps
|
||||||
|
{
|
||||||
|
inTray?: boolean = false;
|
||||||
|
onButtonClick: (action: string) => void;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import { createContext, FC, useContext } from 'react';
|
||||||
|
import { INotificationCenterContext, NotificationCenterContextProps } from './NotificationCenterContext.types';
|
||||||
|
|
||||||
|
const NotificationCenterContext = createContext<INotificationCenterContext>({
|
||||||
|
notificationCenterState: null,
|
||||||
|
dispatchNotificationCenterState: null
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NotificationCenterContextProvider: FC<NotificationCenterContextProps> = props =>
|
||||||
|
{
|
||||||
|
return <NotificationCenterContext.Provider value={ props.value }>{ props.children }</NotificationCenterContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useNotificationCenterContext = () => useContext(NotificationCenterContext);
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Dispatch, ProviderProps } from 'react';
|
||||||
|
import { INotificationCenterAction, INotificationCenterState } from '../reducers/NotificationCenterReducer';
|
||||||
|
|
||||||
|
export interface INotificationCenterContext
|
||||||
|
{
|
||||||
|
notificationCenterState: INotificationCenterState;
|
||||||
|
dispatchNotificationCenterState: Dispatch<INotificationCenterAction>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationCenterContextProps extends ProviderProps<INotificationCenterContext>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
import { Reducer } from 'react';
|
||||||
|
import { NitroNotification } from '../utils/Notification';
|
||||||
|
|
||||||
|
export interface INotificationCenterState
|
||||||
|
{
|
||||||
|
notifications: NitroNotification[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INotificationCenterAction
|
||||||
|
{
|
||||||
|
type: string;
|
||||||
|
payload: {
|
||||||
|
id?: number;
|
||||||
|
notification?: NitroNotification;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotificationCenterActions
|
||||||
|
{
|
||||||
|
public static ADD_NOTIFICATION: string = 'NCA_ADD_NOTIFICATION';
|
||||||
|
public static REMOVE_NOTIFICATION: string = 'NCA_REMOVE_NOTIFICATION';
|
||||||
|
public static DISMISS_NOTIFICATION: string = 'NCA_DISMISS_NOTIFICATION';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialNotificationCenter: INotificationCenterState = {
|
||||||
|
notifications: null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NotificationCenterReducer: Reducer<INotificationCenterState, INotificationCenterAction> = (state, action) =>
|
||||||
|
{
|
||||||
|
switch(action.type)
|
||||||
|
{
|
||||||
|
case NotificationCenterActions.ADD_NOTIFICATION: {
|
||||||
|
const notification = (action.payload.notification || null);
|
||||||
|
|
||||||
|
if(!notification) return state;
|
||||||
|
|
||||||
|
if(state.notifications) return {...state, notifications: [notification, ...state.notifications]};
|
||||||
|
|
||||||
|
return {...state, notifications: [notification]};
|
||||||
|
}
|
||||||
|
case NotificationCenterActions.REMOVE_NOTIFICATION: {
|
||||||
|
const id = (action.payload.id || null);
|
||||||
|
|
||||||
|
if(!id) return state;
|
||||||
|
|
||||||
|
if(!state.notifications) return state;
|
||||||
|
|
||||||
|
const notifications = Array.from(state.notifications);
|
||||||
|
const notificationIndex = notifications.findIndex(notification => notification.id === id);
|
||||||
|
|
||||||
|
if(notificationIndex === -1) return state;
|
||||||
|
|
||||||
|
notifications.splice(notificationIndex, 1);
|
||||||
|
|
||||||
|
return {...state, notifications};
|
||||||
|
}
|
||||||
|
case NotificationCenterActions.DISMISS_NOTIFICATION: {
|
||||||
|
const id = (action.payload.id || null);
|
||||||
|
|
||||||
|
if(!id) return state;
|
||||||
|
|
||||||
|
if(!state.notifications) return state;
|
||||||
|
|
||||||
|
const notifications = Array.from(state.notifications);
|
||||||
|
const notificationIndex = notifications.findIndex(notification => notification.id === id);
|
||||||
|
|
||||||
|
if(notificationIndex === -1) return state;
|
||||||
|
|
||||||
|
notifications[notificationIndex].dismiss();
|
||||||
|
|
||||||
|
return {...state, notifications};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
import { NitroNotification } from './Notification';
|
||||||
|
|
||||||
|
export class BroadcastMessageNotification extends NitroNotification
|
||||||
|
{}
|
@ -0,0 +1,24 @@
|
|||||||
|
import { NitroNotification } from './Notification';
|
||||||
|
|
||||||
|
export class DialogMessageNotification extends NitroNotification
|
||||||
|
{
|
||||||
|
private _type: string;
|
||||||
|
private _parameters: Map<string, string>;
|
||||||
|
|
||||||
|
constructor(type: string, parameters: Map<string, string>)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this._type = type;
|
||||||
|
this._parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): string
|
||||||
|
{
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get parameters(): Map<string, string>
|
||||||
|
{
|
||||||
|
return this._parameters;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { NitroNotification } from './Notification';
|
||||||
|
|
||||||
|
export class HotelWillShutdownNotification extends NitroNotification
|
||||||
|
{
|
||||||
|
private _minutes: number;
|
||||||
|
|
||||||
|
constructor(minutes: number)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this._minutes = minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get minutes(): number
|
||||||
|
{
|
||||||
|
return this._minutes;
|
||||||
|
}
|
||||||
|
}
|
19
src/views/notification-center/utils/MOTDNotification.ts
Normal file
19
src/views/notification-center/utils/MOTDNotification.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { NitroNotification } from './Notification';
|
||||||
|
|
||||||
|
export class MOTDNotification extends NitroNotification
|
||||||
|
{
|
||||||
|
private _messages: string[];
|
||||||
|
|
||||||
|
constructor(messages: string[])
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this._messages = [];
|
||||||
|
|
||||||
|
for(const message of messages) this._messages.push(message.replace(/\r\n|\r|\n/g, '<br />'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public get messages(): string[]
|
||||||
|
{
|
||||||
|
return this._messages;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { NitroNotification } from './Notification';
|
||||||
|
|
||||||
|
export class ModeratorMessageNotification extends NitroNotification
|
||||||
|
{
|
||||||
|
private _link: string;
|
||||||
|
|
||||||
|
constructor(message: string, link: string)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
this._link = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get link(): string
|
||||||
|
{
|
||||||
|
return this._link;
|
||||||
|
}
|
||||||
|
}
|
49
src/views/notification-center/utils/Notification.ts
Normal file
49
src/views/notification-center/utils/Notification.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
export class NitroNotification
|
||||||
|
{
|
||||||
|
public static CURRENT_ID: number = 0;
|
||||||
|
|
||||||
|
private _id: number;
|
||||||
|
private _title: string;
|
||||||
|
private _message: string;
|
||||||
|
private _dismissed: boolean = false;
|
||||||
|
private _timestamp: number;
|
||||||
|
|
||||||
|
constructor(message: string = null, title: string = null)
|
||||||
|
{
|
||||||
|
this._id = ++NitroNotification.CURRENT_ID;
|
||||||
|
this._title = title;
|
||||||
|
this._timestamp = Date.now();
|
||||||
|
|
||||||
|
if(message) this._message = message.replace(/\r\n|\r|\n/g, '<br />');
|
||||||
|
}
|
||||||
|
|
||||||
|
public dismiss(): void
|
||||||
|
{
|
||||||
|
this._dismissed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id(): number
|
||||||
|
{
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get title(): string
|
||||||
|
{
|
||||||
|
return this._title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get message(): string
|
||||||
|
{
|
||||||
|
return this._message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get dismissed(): boolean
|
||||||
|
{
|
||||||
|
return this._dismissed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get timestamp(): number
|
||||||
|
{
|
||||||
|
return this._timestamp;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { NitroCardContentView, NitroCardView } from '../../../../layout';
|
||||||
|
import { NitroCardSimpleHeaderView } from '../../../../layout/card/simple-header';
|
||||||
|
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||||
|
import { NotificationTrayItemView } from '../tray-item/NotificationTrayItemView';
|
||||||
|
import { BroadcastMessageViewProps } from './BroadcastMessageView.types';
|
||||||
|
|
||||||
|
export const BroadcastMessageView: FC<BroadcastMessageViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { notification = null, inTray = null, onButtonClick = null } = props;
|
||||||
|
|
||||||
|
if(!notification) return null;
|
||||||
|
|
||||||
|
const content = <div dangerouslySetInnerHTML={ {__html: notification.message } } />;
|
||||||
|
|
||||||
|
if(inTray)
|
||||||
|
return (
|
||||||
|
<NotificationTrayItemView title={ LocalizeText('mod.alert.title') } content={ content } timestamp={ notification.timestamp } onCloseClick={ () => onButtonClick('remove_notification') } />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardView className="nitro-notification">
|
||||||
|
<NitroCardSimpleHeaderView headerText={ LocalizeText('mod.alert.title') } onCloseClick={ () => onButtonClick('dismiss_notification') } />
|
||||||
|
<NitroCardContentView className="text-black">
|
||||||
|
{ content }
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import { NotificationViewProps } from '../../NotificationCenterView.types';
|
||||||
|
import { BroadcastMessageNotification } from './../../utils/BroadcastMessageNotification';
|
||||||
|
|
||||||
|
export class BroadcastMessageViewProps extends NotificationViewProps
|
||||||
|
{
|
||||||
|
notification: BroadcastMessageNotification;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { NitroCardContentView, NitroCardView } from '../../../../layout';
|
||||||
|
import { NitroCardSimpleHeaderView } from '../../../../layout/card/simple-header';
|
||||||
|
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||||
|
import { NotificationTrayItemView } from '../tray-item/NotificationTrayItemView';
|
||||||
|
import { HotelWillShutdownViewProps } from './HotelWillShutdownView.types';
|
||||||
|
|
||||||
|
export const HotelWillShutdownView: FC<HotelWillShutdownViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { notification = null, inTray = null, onButtonClick = null } = props;
|
||||||
|
|
||||||
|
if(!notification) return null;
|
||||||
|
|
||||||
|
const content = <>{ LocalizeText('opening.hours.shutdown', ['m'], [notification.minutes.toString()]) }</>;
|
||||||
|
|
||||||
|
if(inTray)
|
||||||
|
return (
|
||||||
|
<NotificationTrayItemView title={ LocalizeText('mod.alert.title') } content={ content } timestamp={ notification.timestamp } onCloseClick={ () => onButtonClick('remove_notification') } />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardView className="nitro-notification">
|
||||||
|
<NitroCardSimpleHeaderView headerText={ LocalizeText('mod.alert.title') } onCloseClick={ () => onButtonClick('dismiss_notification') } />
|
||||||
|
<NitroCardContentView className="text-black">
|
||||||
|
{ content }
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import { NotificationViewProps } from '../../NotificationCenterView.types';
|
||||||
|
import { HotelWillShutdownNotification } from './../../utils/HotelWillShutdownNotification';
|
||||||
|
|
||||||
|
export class HotelWillShutdownViewProps extends NotificationViewProps
|
||||||
|
{
|
||||||
|
notification: HotelWillShutdownNotification;
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { NitroCardContentView, NitroCardView } from '../../../../layout';
|
||||||
|
import { NitroCardSimpleHeaderView } from '../../../../layout/card/simple-header';
|
||||||
|
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||||
|
import { NotificationTrayItemView } from '../tray-item/NotificationTrayItemView';
|
||||||
|
import { ModeratorMessageViewProps } from './ModeratorMessageView.types';
|
||||||
|
|
||||||
|
export const ModeratorMessageView: FC<ModeratorMessageViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { notification = null, inTray = null, onButtonClick = null } = props;
|
||||||
|
|
||||||
|
if(!notification) return null;
|
||||||
|
|
||||||
|
const content = <>
|
||||||
|
<div dangerouslySetInnerHTML={ {__html: notification.message } } />
|
||||||
|
<div className="fw-bold text-center">
|
||||||
|
<a href={ notification.link } rel="noreferrer" target="_blank" onClick={ () => onButtonClick('dismiss_notification') }>{ LocalizeText('mod.alert.link') }</a>
|
||||||
|
</div>
|
||||||
|
</>;
|
||||||
|
|
||||||
|
if(inTray)
|
||||||
|
return (
|
||||||
|
<NotificationTrayItemView title={ LocalizeText('mod.alert.title') } content={ content } timestamp={ notification.timestamp } onCloseClick={ () => onButtonClick('remove_notification') } />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardView className="nitro-notification">
|
||||||
|
<NitroCardSimpleHeaderView headerText={ LocalizeText('mod.alert.title') } onCloseClick={ () => onButtonClick('dismiss_notification') } />
|
||||||
|
<NitroCardContentView className="text-black">
|
||||||
|
{ content }
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import { NotificationViewProps } from '../../NotificationCenterView.types';
|
||||||
|
import { ModeratorMessageNotification } from './../../utils/ModeratorMessageNotification';
|
||||||
|
|
||||||
|
export class ModeratorMessageViewProps extends NotificationViewProps
|
||||||
|
{
|
||||||
|
notification: ModeratorMessageNotification;
|
||||||
|
}
|
32
src/views/notification-center/views/motd/MOTDView.tsx
Normal file
32
src/views/notification-center/views/motd/MOTDView.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { NitroCardContentView, NitroCardView } from '../../../../layout';
|
||||||
|
import { NitroCardSimpleHeaderView } from '../../../../layout/card/simple-header';
|
||||||
|
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||||
|
import { NotificationTrayItemView } from '../tray-item/NotificationTrayItemView';
|
||||||
|
import { MOTDViewProps } from './MOTDView.types';
|
||||||
|
|
||||||
|
export const MOTDView: FC<MOTDViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { notification = null, inTray = null, onButtonClick = null } = props;
|
||||||
|
|
||||||
|
if(!notification) return null;
|
||||||
|
|
||||||
|
const content = notification.messages.map((message, index) =>
|
||||||
|
{
|
||||||
|
return <div key={ index } dangerouslySetInnerHTML={ {__html: message } } />
|
||||||
|
});
|
||||||
|
|
||||||
|
if(inTray)
|
||||||
|
return (
|
||||||
|
<NotificationTrayItemView title={ LocalizeText('mod.alert.title') } content={ content } timestamp={ notification.timestamp } onCloseClick={ () => onButtonClick('remove_notification') } />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardView className="nitro-notification">
|
||||||
|
<NitroCardSimpleHeaderView headerText={ LocalizeText('mod.alert.title') } onCloseClick={ () => onButtonClick('dismiss_notification') } />
|
||||||
|
<NitroCardContentView className="text-black">
|
||||||
|
{ content }
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import { NotificationViewProps } from '../../NotificationCenterView.types';
|
||||||
|
import { MOTDNotification } from './../../utils/MOTDNotification';
|
||||||
|
|
||||||
|
export class MOTDViewProps extends NotificationViewProps
|
||||||
|
{
|
||||||
|
notification: MOTDNotification;
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { NotificationTrayItemViewProps } from './NotificationTrayItemView.types';
|
||||||
|
|
||||||
|
export const NotificationTrayItemView: FC<NotificationTrayItemViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { title = null, content = null, timestamp = null, onCloseClick = null } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="rounded bg-muted mb-2 text-black">
|
||||||
|
<div className="py-1 px-2 fw-bold d-flex justify-content-between align-items-center">
|
||||||
|
<div className="me-2">{ title }</div>
|
||||||
|
<i className="fas fa-times cursor-pointer" onClick={ onCloseClick }></i>
|
||||||
|
</div>
|
||||||
|
<div className="py-1 px-2">
|
||||||
|
{ content }
|
||||||
|
</div>
|
||||||
|
<div className="py-1 px-2">
|
||||||
|
<i className="far fa-clock"></i> { timestamp }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
export class NotificationTrayItemViewProps
|
||||||
|
{
|
||||||
|
title: string;
|
||||||
|
content: any;
|
||||||
|
timestamp: number;
|
||||||
|
onCloseClick: () => void;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
.nitro-camera-capture {
|
.nitro-camera-capture {
|
||||||
.header-close {
|
.nitro-close {
|
||||||
top: 7px;
|
top: 7px;
|
||||||
right: 9px;
|
right: 9px;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { NitroRectangle } from 'nitro-renderer';
|
import { NitroRectangle } from 'nitro-renderer';
|
||||||
import { FC, useCallback, useRef } from 'react';
|
import { FC, useCallback, useRef } from 'react';
|
||||||
import { GetRoomEngine } from '../../../../../../api/nitro/room/GetRoomEngine';
|
import { GetRoomEngine, GetRoomSession } from '../../../../../../api';
|
||||||
import { GetRoomSession } from '../../../../../../api/nitro/session/GetRoomSession';
|
|
||||||
import { DraggableWindow } from '../../../../../../layout/draggable-window/DraggableWindow';
|
import { DraggableWindow } from '../../../../../../layout/draggable-window/DraggableWindow';
|
||||||
import { LocalizeText } from '../../../../../../utils/LocalizeText';
|
import { LocalizeText } from '../../../../../../utils/LocalizeText';
|
||||||
import { useCameraWidgetContext } from '../../context/CameraWidgetContext';
|
import { useCameraWidgetContext } from '../../context/CameraWidgetContext';
|
||||||
@ -46,7 +45,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
|
|||||||
}
|
}
|
||||||
|
|
||||||
cameraWidgetContext.setCameraRoll([ ...remainingRoll, image ]);
|
cameraWidgetContext.setCameraRoll([ ...remainingRoll, image ]);
|
||||||
}, [ cameraWidgetContext.cameraRoll, cameraWidgetContext.selectedPictureIndex ]);
|
}, [ cameraWidgetContext ]);
|
||||||
|
|
||||||
const processAction = useCallback((type: string, value: string | number = null) =>
|
const processAction = useCallback((type: string, value: string | number = null) =>
|
||||||
{
|
{
|
||||||
@ -73,7 +72,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
|
|||||||
onCloseClick();
|
onCloseClick();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [ cameraWidgetContext.selectedPictureIndex, cameraWidgetContext.cameraRoll, onEditClick, onCloseClick ]);
|
}, [ takePicture, cameraWidgetContext, onEditClick, onCloseClick ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DraggableWindow handle=".nitro-camera-capture">
|
<DraggableWindow handle=".nitro-camera-capture">
|
||||||
|
Loading…
Reference in New Issue
Block a user