From 63bc890fd6109f771d57772eee9bdbcf1a5d672b Mon Sep 17 00:00:00 2001 From: Bill Date: Fri, 2 Jul 2021 02:50:17 -0400 Subject: [PATCH] Update chat --- src/views/room/RoomView.tsx | 3 +- .../events/RoomWidgetFloodControlEvent.ts | 20 ++ src/views/room/events/index.ts | 1 + src/views/room/handlers/IRoomWidgetHandler.ts | 6 +- .../handlers/IRoomWidgetHandlerManager.ts | 3 +- .../handlers/RoomWidgetAvatarInfoHandler.ts | 6 +- .../handlers/RoomWidgetChatInputHandler.ts | 198 ++++++++++++++++++ src/views/room/handlers/RoomWidgetHandler.ts | 24 +-- .../room/handlers/RoomWidgetHandlerManager.ts | 3 +- .../handlers/RoomWidgetInfostandHandler.ts | 94 ++++----- src/views/room/handlers/index.ts | 1 + .../room/messages/RoomWidgetChatMessage.ts | 44 ++++ .../RoomWidgetChatSelectAvatarMessage.ts | 34 +++ .../messages/RoomWidgetChatTypingMessage.ts | 20 ++ .../RoomWidgetRequestWidgetMessage.ts | 10 + src/views/room/messages/index.ts | 4 + .../widgets/chat-input/ChatInputView.scss | 108 +++++----- .../room/widgets/chat-input/ChatInputView.tsx | 190 ++++++++++------- .../widgets/chat-input/ChatInputView.types.ts | 7 - .../ChatInputStyleSelectorView.scss | 61 ++++++ .../ChatInputStyleSelectorView.tsx | 20 ++ .../ChatInputStyleSelectorView.types.ts | 4 + 22 files changed, 643 insertions(+), 218 deletions(-) create mode 100644 src/views/room/events/RoomWidgetFloodControlEvent.ts create mode 100644 src/views/room/handlers/RoomWidgetChatInputHandler.ts create mode 100644 src/views/room/messages/RoomWidgetChatMessage.ts create mode 100644 src/views/room/messages/RoomWidgetChatSelectAvatarMessage.ts create mode 100644 src/views/room/messages/RoomWidgetChatTypingMessage.ts create mode 100644 src/views/room/messages/RoomWidgetRequestWidgetMessage.ts create mode 100644 src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.scss create mode 100644 src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.tsx create mode 100644 src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.types.ts diff --git a/src/views/room/RoomView.tsx b/src/views/room/RoomView.tsx index f0afb252..f4ea630f 100644 --- a/src/views/room/RoomView.tsx +++ b/src/views/room/RoomView.tsx @@ -9,7 +9,7 @@ import { GetRoomEngine } from '../../api/nitro/room/GetRoomEngine'; import { useRoomEngineEvent } from '../../hooks/events'; import { RoomContextProvider } from './context/RoomContext'; import { RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent } from './events'; -import { IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers'; +import { IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers'; import { RoomViewProps } from './RoomView.types'; import { RoomWidgetsView } from './widgets/RoomWidgetsView'; @@ -35,6 +35,7 @@ export const RoomView: FC = props => widgetHandlerManager.registerHandler(new RoomWidgetAvatarInfoHandler()); widgetHandlerManager.registerHandler(new RoomWidgetInfostandHandler()); + widgetHandlerManager.registerHandler(new RoomWidgetChatInputHandler()); setWidgetHandler(widgetHandlerManager); diff --git a/src/views/room/events/RoomWidgetFloodControlEvent.ts b/src/views/room/events/RoomWidgetFloodControlEvent.ts new file mode 100644 index 00000000..4c07a560 --- /dev/null +++ b/src/views/room/events/RoomWidgetFloodControlEvent.ts @@ -0,0 +1,20 @@ +import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent'; + +export class RoomWidgetFloodControlEvent extends RoomWidgetUpdateEvent +{ + public static FLOOD_CONTROL: string = 'RWFCE_FLOOD_CONTROL'; + + private _seconds: number = 0; + + constructor(k: number) + { + super(RoomWidgetFloodControlEvent.FLOOD_CONTROL); + + this._seconds = k; + } + + public get seconds(): number + { + return this._seconds; + } +} diff --git a/src/views/room/events/index.ts b/src/views/room/events/index.ts index e4aa2a07..004231d7 100644 --- a/src/views/room/events/index.ts +++ b/src/views/room/events/index.ts @@ -1,4 +1,5 @@ export * from './RoomWidgetAvatarInfoEvent'; +export * from './RoomWidgetFloodControlEvent'; export * from './RoomWidgetObjectNameEvent'; export * from './RoomWidgetRoomEngineUpdateEvent'; export * from './RoomWidgetRoomObjectUpdateEvent'; diff --git a/src/views/room/handlers/IRoomWidgetHandler.ts b/src/views/room/handlers/IRoomWidgetHandler.ts index 2043192e..82cea5a6 100644 --- a/src/views/room/handlers/IRoomWidgetHandler.ts +++ b/src/views/room/handlers/IRoomWidgetHandler.ts @@ -1,13 +1,13 @@ -import { IEventDispatcher, IRoomSession, NitroEvent } from 'nitro-renderer'; +import { NitroEvent } from 'nitro-renderer'; import { RoomWidgetUpdateEvent } from '../events'; import { RoomWidgetMessage } from '../messages'; +import { IRoomWidgetHandlerManager } from './IRoomWidgetHandlerManager'; export interface IRoomWidgetHandler { processEvent: (event: NitroEvent) => void; processWidgetMessage: (message: RoomWidgetMessage) => RoomWidgetUpdateEvent; - roomSession: IRoomSession; - eventDispatcher: IEventDispatcher; + container: IRoomWidgetHandlerManager; eventTypes: string[]; messageTypes: string[]; } diff --git a/src/views/room/handlers/IRoomWidgetHandlerManager.ts b/src/views/room/handlers/IRoomWidgetHandlerManager.ts index 654c34e3..784a5b95 100644 --- a/src/views/room/handlers/IRoomWidgetHandlerManager.ts +++ b/src/views/room/handlers/IRoomWidgetHandlerManager.ts @@ -1,4 +1,4 @@ -import { IEventDispatcher, NitroEvent } from 'nitro-renderer'; +import { IEventDispatcher, IRoomSession, NitroEvent } from 'nitro-renderer'; import { RoomWidgetUpdateEvent } from '../events'; import { RoomWidgetMessage } from '../messages'; import { IRoomWidgetHandler } from './IRoomWidgetHandler'; @@ -8,5 +8,6 @@ export interface IRoomWidgetHandlerManager registerHandler(handler: IRoomWidgetHandler): void; processEvent(event: NitroEvent): void; processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent; + roomSession: IRoomSession; eventDispatcher: IEventDispatcher; } diff --git a/src/views/room/handlers/RoomWidgetAvatarInfoHandler.ts b/src/views/room/handlers/RoomWidgetAvatarInfoHandler.ts index 207a37d4..4ff95da1 100644 --- a/src/views/room/handlers/RoomWidgetAvatarInfoHandler.ts +++ b/src/views/room/handlers/RoomWidgetAvatarInfoHandler.ts @@ -11,7 +11,7 @@ export class RoomWidgetAvatarInfoHandler extends RoomWidgetHandler switch(event.type) { case RoomSessionUserDataUpdateEvent.USER_DATA_UPDATED: - this.eventDispatcher.dispatchEvent(new RoomWidgetUserDataUpdateEvent()); + this.container.eventDispatcher.dispatchEvent(new RoomWidgetUserDataUpdateEvent()); return; case RoomSessionDanceEvent.RSDE_DANCE: const danceEvent = (event as RoomSessionDanceEvent); @@ -22,7 +22,7 @@ export class RoomWidgetAvatarInfoHandler extends RoomWidgetHandler if(userData && (userData.roomIndex === danceEvent.roomIndex)) isDancing = (danceEvent.danceId !== 0); - this.eventDispatcher.dispatchEvent(new RoomWidgetUpdateDanceStatusEvent(isDancing)); + this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateDanceStatusEvent(isDancing)); return; } } @@ -68,7 +68,7 @@ export class RoomWidgetAvatarInfoHandler extends RoomWidgetHandler const allowNameChange = GetSessionDataManager().canChangeName; const userData = GetRoomSession().userDataManager.getUserData(userId); - if(userData) this.eventDispatcher.dispatchEvent(new RoomWidgetAvatarInfoEvent(userId, userName, userData.type, userData.roomIndex, allowNameChange)); + if(userData) this.container.eventDispatcher.dispatchEvent(new RoomWidgetAvatarInfoEvent(userId, userName, userData.type, userData.roomIndex, allowNameChange)); } public get eventTypes(): string[] diff --git a/src/views/room/handlers/RoomWidgetChatInputHandler.ts b/src/views/room/handlers/RoomWidgetChatInputHandler.ts new file mode 100644 index 00000000..d726fc57 --- /dev/null +++ b/src/views/room/handlers/RoomWidgetChatInputHandler.ts @@ -0,0 +1,198 @@ +import { AvatarExpressionEnum, HabboClubLevelEnum, NitroEvent, RoomControllerLevel, RoomSessionChatEvent, RoomSettingsComposer, RoomZoomEvent } from 'nitro-renderer'; +import { GetConnection, GetRoomEngine, GetSessionDataManager, SendChatTypingMessage } from '../../../api'; +import { RoomWidgetFloodControlEvent, RoomWidgetUpdateEvent } from '../events'; +import { RoomWidgetChatMessage, RoomWidgetChatSelectAvatarMessage, RoomWidgetChatTypingMessage, RoomWidgetMessage, RoomWidgetRequestWidgetMessage } from '../messages'; +import { RoomWidgetHandler } from './RoomWidgetHandler'; + +export class RoomWidgetChatInputHandler extends RoomWidgetHandler +{ + public processEvent(event: NitroEvent): void + { + switch(event.type) + { + case RoomSessionChatEvent.FLOOD_EVENT: { + const floodEvent = (event as RoomSessionChatEvent); + + this.container.eventDispatcher.dispatchEvent(new RoomWidgetFloodControlEvent(parseInt(floodEvent.message))); + } + } + } + + public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent + { + switch(message.type) + { + case RoomWidgetChatTypingMessage.TYPING_STATUS: { + const typingMessage = (message as RoomWidgetChatTypingMessage); + + SendChatTypingMessage(typingMessage.isTyping); + break; + } + case RoomWidgetChatMessage.MESSAGE_CHAT: { + const chatMessage = (message as RoomWidgetChatMessage); + + if(chatMessage.text === '') return null; + + let text = chatMessage.text; + const parts = text.split(' '); + + if(parts.length > 0) + { + const firstPart = parts[0]; + let secondPart = ''; + + if(parts.length > 1) secondPart = parts[1]; + + if((firstPart.charAt(0) === ':') && (secondPart === 'x')) + { + const selectedAvatarId = GetRoomEngine().selectedAvatarId; + + if(selectedAvatarId > -1) + { + const userData = this.container.roomSession.userDataManager.getUserDataByIndex(selectedAvatarId); + + if(userData) + { + secondPart = userData.name; + text = chatMessage.text.replace(' x', (' ' + userData.name)); + } + } + } + + switch(firstPart.toLowerCase()) + { + case ':d': + case ';d': + if(GetSessionDataManager().clubLevel === HabboClubLevelEnum.VIP) + { + this.container.roomSession.sendExpressionMessage(AvatarExpressionEnum.LAUGH.ordinal); + } + + break; + case 'o/': + case '_o/': + this.container.roomSession.sendExpressionMessage(AvatarExpressionEnum.WAVE.ordinal); + + return null; + case ':kiss': + if(GetSessionDataManager().clubLevel === HabboClubLevelEnum.VIP) + { + this.container.roomSession.sendExpressionMessage(AvatarExpressionEnum.BLOW.ordinal); + + return null; + } + + break; + case ':jump': + if(GetSessionDataManager().clubLevel === HabboClubLevelEnum.VIP) + { + this.container.roomSession.sendExpressionMessage(AvatarExpressionEnum.JUMP.ordinal); + + return null; + } + + break; + case ':idle': + this.container.roomSession.sendExpressionMessage(AvatarExpressionEnum.IDLE.ordinal); + + return null; + case '_b': + this.container.roomSession.sendExpressionMessage(AvatarExpressionEnum.RESPECT.ordinal); + + return null; + case ':sign': + this.container.roomSession.sendSignMessage(parseInt(secondPart)); + + return null; + case ':iddqd': + GetRoomEngine().events.dispatchEvent(new RoomZoomEvent(this.container.roomSession.roomId, -1, true)); + + return null; + case ':zoom': + GetRoomEngine().events.dispatchEvent(new RoomZoomEvent(this.container.roomSession.roomId, parseInt(secondPart), false)); + + return null; + case ':screenshot': + GetRoomEngine().createRoomScreenshot(this.container.roomSession.roomId, 1); + + return null; + case ':pickall': + // this.container.notificationService.alertWithConfirm('${room.confirm.pick_all}', '${generic.alert.title}', () => + // { + // GetSessionDataManager().sendSpecialCommandMessage(':pickall'); + // }); + + return null; + case ':furni': + this.container.processWidgetMessage(new RoomWidgetRequestWidgetMessage(RoomWidgetRequestWidgetMessage.FURNI_CHOOSER)); + + return null; + case ':chooser': + this.container.processWidgetMessage(new RoomWidgetRequestWidgetMessage(RoomWidgetRequestWidgetMessage.USER_CHOOSER)); + + return null; + case ':floor': + case ':bcfloor': + if(this.container.roomSession.controllerLevel >= RoomControllerLevel.ROOM_OWNER) + { + this.container.processWidgetMessage(new RoomWidgetRequestWidgetMessage(RoomWidgetRequestWidgetMessage.FLOOR_EDITOR)); + } + + return null; + case ':client': + case ':nitro': + case ':billsonnn': + // this.container.notificationService.alertWithScrollableMessages([ + // '
Version: ' + Nitro.RELEASE_VERSION + '
This client is powered by Nitro HTML5


'], 'Nitro HTML5'); + return null; + case ':settings': + if(this.container.roomSession.isRoomOwner || GetSessionDataManager().isModerator) + { + GetConnection().send(new RoomSettingsComposer(this.container.roomSession.roomId)); + } + + return null; + } + } + + const styleId = chatMessage.styleId; + + if(this.container && this.container.roomSession) + { + switch(chatMessage.chatType) + { + case RoomWidgetChatMessage.CHAT_DEFAULT: + this.container.roomSession.sendChatMessage(text, styleId); + break; + case RoomWidgetChatMessage.CHAT_SHOUT: + this.container.roomSession.sendShoutMessage(text, styleId); + break; + case RoomWidgetChatMessage.CHAT_WHISPER: + this.container.roomSession.sendWhisperMessage(chatMessage.recipientName, text, styleId); + break; + } + } + + break; + } + } + + return null; + } + + public get eventTypes(): string[] + { + return [ + RoomSessionChatEvent.FLOOD_EVENT + ]; + } + + public get messageTypes(): string[] + { + return [ + RoomWidgetChatTypingMessage.TYPING_STATUS, + RoomWidgetChatMessage.MESSAGE_CHAT, + RoomWidgetChatSelectAvatarMessage.MESSAGE_SELECT_AVATAR + ]; + } +} diff --git a/src/views/room/handlers/RoomWidgetHandler.ts b/src/views/room/handlers/RoomWidgetHandler.ts index 29e73af0..747ed477 100644 --- a/src/views/room/handlers/RoomWidgetHandler.ts +++ b/src/views/room/handlers/RoomWidgetHandler.ts @@ -1,35 +1,25 @@ -import { IEventDispatcher, IRoomSession, NitroEvent } from 'nitro-renderer'; +import { NitroEvent } from 'nitro-renderer'; import { RoomWidgetUpdateEvent } from '../events'; import { RoomWidgetMessage } from '../messages'; import { IRoomWidgetHandler } from './IRoomWidgetHandler'; +import { IRoomWidgetHandlerManager } from './IRoomWidgetHandlerManager'; export abstract class RoomWidgetHandler implements IRoomWidgetHandler { - private _roomSession: IRoomSession = null; - private _eventDispatcher: IEventDispatcher = null; + private _container: IRoomWidgetHandlerManager = null; public abstract processEvent(event: NitroEvent): void; public abstract processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent; - public get roomSession(): IRoomSession + public get container(): IRoomWidgetHandlerManager { - return this._roomSession; + return this._container; } - public set roomSession(roomSession: IRoomSession) + public set container(container: IRoomWidgetHandlerManager) { - this._roomSession = roomSession; - } - - public get eventDispatcher(): IEventDispatcher - { - return this._eventDispatcher; - } - - public set eventDispatcher(eventDispatcher: IEventDispatcher) - { - this._eventDispatcher = eventDispatcher; + this._container = container; } public abstract get eventTypes(): string[]; diff --git a/src/views/room/handlers/RoomWidgetHandlerManager.ts b/src/views/room/handlers/RoomWidgetHandlerManager.ts index 4d83be33..7eae5591 100644 --- a/src/views/room/handlers/RoomWidgetHandlerManager.ts +++ b/src/views/room/handlers/RoomWidgetHandlerManager.ts @@ -62,8 +62,7 @@ export class RoomWidgetHandlerManager implements IRoomWidgetHandlerManager } } - handler.roomSession = this._roomSession; - handler.eventDispatcher = this._eventDispatcher; + handler.container = this; this._handlers.push(handler); } diff --git a/src/views/room/handlers/RoomWidgetInfostandHandler.ts b/src/views/room/handlers/RoomWidgetInfostandHandler.ts index fc68071a..04385763 100644 --- a/src/views/room/handlers/RoomWidgetInfostandHandler.ts +++ b/src/views/room/handlers/RoomWidgetInfostandHandler.ts @@ -17,7 +17,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler this.processPetInfoEvent((event as RoomSessionPetInfoUpdateEvent)); return; case RoomSessionUserBadgesEvent.RSUBE_BADGES: - this.eventDispatcher.dispatchEvent(event); + this.container.eventDispatcher.dispatchEvent(event); return; } } @@ -50,11 +50,11 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler if(petMessages.indexOf(message.type) >= 0) { - userData = this.roomSession.userDataManager.getPetData(userId); + userData = this.container.roomSession.userDataManager.getPetData(userId); } else { - userData = this.roomSession.userDataManager.getUserData(userId); + userData = this.container.roomSession.userDataManager.getUserData(userId); } if(!userData) return null; @@ -82,7 +82,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler GetSessionDataManager().givePetRespect(userId); break; case RoomWidgetUserActionMessage.WHISPER_USER: - //this.eventDispatcher.dispatchEvent(new RoomWidgetChatInputContentUpdateEvent(RoomWidgetChatInputContentUpdateEvent.WHISPER, userData.name)); + //this.container.eventDispatcher.dispatchEvent(new RoomWidgetChatInputContentUpdateEvent(RoomWidgetChatInputContentUpdateEvent.WHISPER, userData.name)); break; case RoomWidgetUserActionMessage.IGNORE_USER: GetSessionDataManager().ignoreUser(userData.name); @@ -91,27 +91,27 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler GetSessionDataManager().unignoreUser(userData.name); break; case RoomWidgetUserActionMessage.KICK_USER: - this.roomSession.sendKickMessage((message as RoomWidgetUserActionMessage).userId); + this.container.roomSession.sendKickMessage((message as RoomWidgetUserActionMessage).userId); break; case RoomWidgetUserActionMessage.BAN_USER_DAY: case RoomWidgetUserActionMessage.BAN_USER_HOUR: case RoomWidgetUserActionMessage.BAN_USER_PERM: - this.roomSession.sendBanMessage((message as RoomWidgetUserActionMessage).userId, message.type); + this.container.roomSession.sendBanMessage((message as RoomWidgetUserActionMessage).userId, message.type); break; case RoomWidgetUserActionMessage.MUTE_USER_2MIN: - this.roomSession.sendMuteMessage((message as RoomWidgetUserActionMessage).userId, 2); + this.container.roomSession.sendMuteMessage((message as RoomWidgetUserActionMessage).userId, 2); break; case RoomWidgetUserActionMessage.MUTE_USER_5MIN: - this.roomSession.sendMuteMessage((message as RoomWidgetUserActionMessage).userId, 5); + this.container.roomSession.sendMuteMessage((message as RoomWidgetUserActionMessage).userId, 5); break; case RoomWidgetUserActionMessage.MUTE_USER_10MIN: - this.roomSession.sendMuteMessage((message as RoomWidgetUserActionMessage).userId, 10); + this.container.roomSession.sendMuteMessage((message as RoomWidgetUserActionMessage).userId, 10); break; case RoomWidgetUserActionMessage.GIVE_RIGHTS: - this.roomSession.sendGiveRightsMessage((message as RoomWidgetUserActionMessage).userId); + this.container.roomSession.sendGiveRightsMessage((message as RoomWidgetUserActionMessage).userId); break; case RoomWidgetUserActionMessage.TAKE_RIGHTS: - this.roomSession.sendTakeRightsMessage((message as RoomWidgetUserActionMessage).userId); + this.container.roomSession.sendTakeRightsMessage((message as RoomWidgetUserActionMessage).userId); break; case RoomWidgetUserActionMessage.START_TRADING: //if(userData) this._widget.inventoryTrading.startTrade(userData.roomIndex, userData.name); @@ -156,29 +156,29 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler GetConnection().send(new RoomUnitDropHandItemComposer()); break; case RoomWidgetUserActionMessage.REQUEST_PET_UPDATE: - this.roomSession.userDataManager.requestPetInfo(userId); + this.container.roomSession.userDataManager.requestPetInfo(userId); return; case RoomWidgetUserActionMessage.REPORT: return; case RoomWidgetUserActionMessage.REPORT_CFH_OTHER: return; case RoomWidgetUserActionMessage.AMBASSADOR_ALERT_USER: - this.roomSession.sendAmbassadorAlertMessage(userId); + this.container.roomSession.sendAmbassadorAlertMessage(userId); return; case RoomWidgetUserActionMessage.AMBASSADOR_KICK_USER: - this.roomSession.sendKickMessage(userId); + this.container.roomSession.sendKickMessage(userId); return; case RoomWidgetUserActionMessage.AMBASSADOR_MUTE_USER_2MIN: - this.roomSession.sendMuteMessage(userId, 2); + this.container.roomSession.sendMuteMessage(userId, 2); return; case RoomWidgetUserActionMessage.AMBASSADOR_MUTE_USER_10MIN: - this.roomSession.sendMuteMessage(userId, 10); + this.container.roomSession.sendMuteMessage(userId, 10); return; case RoomWidgetUserActionMessage.AMBASSADOR_MUTE_USER_60MIN: - this.roomSession.sendMuteMessage(userId, 60); + this.container.roomSession.sendMuteMessage(userId, 60); return; case RoomWidgetUserActionMessage.AMBASSADOR_MUTE_USER_18HOUR: - this.roomSession.sendMuteMessage(userId, 1080); + this.container.roomSession.sendMuteMessage(userId, 1080); return; case RoomWidgetFurniActionMessage.ROTATE: GetRoomEngine().processRoomObjectOperation(objectId, category, RoomObjectOperationType.OBJECT_ROTATE_POSITIVE); @@ -226,7 +226,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler return; } case RoomWidgetChangeMottoMessage.CHANGE_MOTTO: - this.roomSession.sendMottoMessage((message as RoomWidgetChangeMottoMessage).motto); + this.container.roomSession.sendMottoMessage((message as RoomWidgetChangeMottoMessage).motto); return; } @@ -243,7 +243,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler { case RoomObjectCategory.FLOOR: case RoomObjectCategory.WALL: { - const roomObject = GetRoomEngine().getRoomObject(this.roomSession.roomId, message.id, message.category); + const roomObject = GetRoomEngine().getRoomObject(this.container.roomSession.roomId, message.id, message.category); if(!roomObject) break; @@ -275,7 +275,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler break; } case RoomObjectCategory.UNIT: { - const userData = this.roomSession.userDataManager.getUserDataByIndex(message.id); + const userData = this.container.roomSession.userDataManager.getUserDataByIndex(message.id); if(!userData) break; @@ -286,14 +286,14 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler } } - if(name) this.eventDispatcher.dispatchEvent(new RoomWidgetObjectNameEvent(message.id, message.category, id, name, userType)); + if(name) this.container.eventDispatcher.dispatchEvent(new RoomWidgetObjectNameEvent(message.id, message.category, id, name, userType)); return null; } private processObjectInfoMessage(message: RoomWidgetRoomObjectMessage): RoomWidgetUpdateEvent { - const roomId = this.roomSession.roomId; + const roomId = this.container.roomSession.roomId; switch(message.category) { @@ -302,14 +302,14 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler this.processFurniInfoMessage(message, roomId); break; case RoomObjectCategory.UNIT: { - const userData = this.roomSession.userDataManager.getUserDataByIndex(message.id); + const userData = this.container.roomSession.userDataManager.getUserDataByIndex(message.id); if(!userData) break; switch(userData.type) { case RoomObjectType.PET: - this.roomSession.userDataManager.requestPetInfo(userData.webID); + this.container.roomSession.userDataManager.requestPetInfo(userData.webID); break; case RoomObjectType.USER: this.processUserInfoMessage(message, roomId, userData); @@ -408,8 +408,8 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler event.image = roomObjectImage.getImage(); event.isWallItem = (message.category === RoomObjectCategory.WALL); - event.isRoomOwner = this.roomSession.isRoomOwner; - event.roomControllerLevel = this.roomSession.controllerLevel; + event.isRoomOwner = this.container.roomSession.isRoomOwner; + event.roomControllerLevel = this.container.roomSession.controllerLevel; event.isAnyRoomController = GetSessionDataManager().isModerator; event.ownerId = model.getValue(RoomObjectVariable.FURNITURE_OWNER_ID); event.ownerName = model.getValue(RoomObjectVariable.FURNITURE_OWNER_NAME); @@ -425,7 +425,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler if(IsOwnerOfFurniture(roomObject)) event.isOwner = true; - this.eventDispatcher.dispatchEvent(event); + this.container.eventDispatcher.dispatchEvent(event); } private processUserInfoMessage(message: RoomWidgetRoomObjectMessage, roomId: number, userData: RoomUserData): void @@ -436,7 +436,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler const event = new RoomWidgetUpdateInfostandUserEvent(eventType); - event.isSpectatorMode = this.roomSession.isSpectator; + event.isSpectatorMode = this.container.roomSession.isSpectator; event.name = userData.name; event.motto = userData.custom; event.achievementScore = userData.activityPoints; @@ -454,9 +454,9 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler event.allowNameChange = GetSessionDataManager().canChangeName; } - event.amIOwner = this.roomSession.isRoomOwner; - event.isGuildRoom = this.roomSession.isGuildRoom; - event.roomControllerLevel = this.roomSession.controllerLevel; + event.amIOwner = this.container.roomSession.isRoomOwner; + event.isGuildRoom = this.container.roomSession.isGuildRoom; + event.roomControllerLevel = this.container.roomSession.controllerLevel; event.amIAnyRoomController = GetSessionDataManager().isModerator; event.isAmbassador = GetSessionDataManager().isAmbassador; @@ -487,7 +487,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler event.respectLeft = GetSessionDataManager().respectsLeft; const isShuttingDown = GetSessionDataManager().isSystemShutdown; - const tradeMode = this.roomSession.tradeMode; + const tradeMode = this.container.roomSession.tradeMode; if(isShuttingDown) { @@ -527,14 +527,14 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler event.groupId = parseInt(userData.guildId); //event._Str_5235 = GetSessionDataManager()._Str_17173(int(userData._Str_4592)); event.groupName = userData.groupName; - event.badges = this.roomSession.userDataManager.getUserBadges(userData.webID); + event.badges = this.container.roomSession.userDataManager.getUserBadges(userData.webID); event.figure = userData.figure; //var _local_8:Array = GetSessionDataManager()._Str_18437(userData.webID); //this._Str_16287(userData._Str_2394, _local_8); //this._container._Str_8097._Str_14387(userData.webID); //this._container.connection.send(new _Str_8049(userData._Str_2394)); - this.eventDispatcher.dispatchEvent(event); + this.container.eventDispatcher.dispatchEvent(event); } private processBotInfoMessage(message: RoomWidgetRoomObjectMessage, roomId: number, userData: RoomUserData): void @@ -551,15 +551,15 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler if(roomObject) event.carryItem = (roomObject.model.getValue(RoomObjectVariable.FIGURE_CARRY_OBJECT) || 0); - event.amIOwner = this.roomSession.isRoomOwner; - event.isGuildRoom = this.roomSession.isGuildRoom; - event.roomControllerLevel = this.roomSession.controllerLevel; + event.amIOwner = this.container.roomSession.isRoomOwner; + event.isGuildRoom = this.container.roomSession.isGuildRoom; + event.roomControllerLevel = this.container.roomSession.controllerLevel; event.amIAnyRoomController = GetSessionDataManager().isModerator; event.isAmbassador = GetSessionDataManager().isAmbassador; event.badges = [ RoomWidgetUpdateInfostandUserEvent.DEFAULT_BOT_BADGE_ID ]; event.figure = userData.figure; - this.eventDispatcher.dispatchEvent(event); + this.container.eventDispatcher.dispatchEvent(event); } private processRentableBotInfoMessage(message: RoomWidgetRoomObjectMessage, roomId: number, userData: RoomUserData): void @@ -578,13 +578,13 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler if(roomObject) event.carryItem = (roomObject.model.getValue(RoomObjectVariable.FIGURE_CARRY_OBJECT) || 0); - event.amIOwner = this.roomSession.isRoomOwner; - event.roomControllerLevel = this.roomSession.controllerLevel; + event.amIOwner = this.container.roomSession.isRoomOwner; + event.roomControllerLevel = this.container.roomSession.controllerLevel; event.amIAnyRoomController = GetSessionDataManager().isModerator; event.badges = [ RoomWidgetUpdateInfostandUserEvent.DEFAULT_BOT_BADGE_ID ]; event.figure = userData.figure; - this.eventDispatcher.dispatchEvent(event); + this.container.eventDispatcher.dispatchEvent(event); } private processPetInfoEvent(event: RoomSessionPetInfoUpdateEvent): void @@ -593,7 +593,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler if(!petData) return; - const roomPetData = this.roomSession.userDataManager.getPetData(petData.id); + const roomPetData = this.container.roomSession.userDataManager.getPetData(petData.id); if(!roomPetData) return; @@ -652,10 +652,10 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler } else { - if(this.roomSession.isRoomOwner || GetSessionDataManager().isModerator || (this.roomSession.controllerLevel >= RoomControllerLevel.GUEST)) infostandEvent.canRemovePet = true; + if(this.container.roomSession.isRoomOwner || GetSessionDataManager().isModerator || (this.container.roomSession.controllerLevel >= RoomControllerLevel.GUEST)) infostandEvent.canRemovePet = true; } - this.eventDispatcher.dispatchEvent(infostandEvent); + this.container.eventDispatcher.dispatchEvent(infostandEvent); } private checkGuildSetting(event: RoomWidgetUpdateInfostandUserEvent): boolean @@ -717,9 +717,9 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler private isValidSetting(event: RoomWidgetUpdateInfostandUserEvent, checkSetting: (event: RoomWidgetUpdateInfostandUserEvent, moderation: RoomModerationSettings) => boolean): boolean { - if(!this.roomSession._Str_7411) return false; + if(!this.container.roomSession._Str_7411) return false; - const moderation = this.roomSession.moderationSettings; + const moderation = this.container.roomSession.moderationSettings; let flag = false; diff --git a/src/views/room/handlers/index.ts b/src/views/room/handlers/index.ts index d9a3656c..39d82f56 100644 --- a/src/views/room/handlers/index.ts +++ b/src/views/room/handlers/index.ts @@ -1,6 +1,7 @@ export * from './IRoomWidgetHandler'; export * from './IRoomWidgetHandlerManager'; export * from './RoomWidgetAvatarInfoHandler'; +export * from './RoomWidgetChatInputHandler'; export * from './RoomWidgetHandler'; export * from './RoomWidgetHandlerManager'; export * from './RoomWidgetInfostandHandler'; diff --git a/src/views/room/messages/RoomWidgetChatMessage.ts b/src/views/room/messages/RoomWidgetChatMessage.ts new file mode 100644 index 00000000..59190a0d --- /dev/null +++ b/src/views/room/messages/RoomWidgetChatMessage.ts @@ -0,0 +1,44 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetChatMessage extends RoomWidgetMessage +{ + public static MESSAGE_CHAT: string = 'RWCM_MESSAGE_CHAT'; + public static CHAT_DEFAULT: number = 0; + public static CHAT_WHISPER: number = 1; + public static CHAT_SHOUT: number = 2; + + private _chatType: number; + private _text: string; + private _recipientName: string; + private _styleId: number; + + constructor(type: string, text: string, chatType: number, recipientName: string, styleId: number) + { + super(type); + + this._text = text; + this._chatType = chatType; + this._recipientName = recipientName; + this._styleId = styleId; + } + + public get text(): string + { + return this._text; + } + + public get chatType(): number + { + return this._chatType; + } + + public get recipientName(): string + { + return this._recipientName; + } + + public get styleId(): number + { + return this._styleId; + } +} diff --git a/src/views/room/messages/RoomWidgetChatSelectAvatarMessage.ts b/src/views/room/messages/RoomWidgetChatSelectAvatarMessage.ts new file mode 100644 index 00000000..9abbbf90 --- /dev/null +++ b/src/views/room/messages/RoomWidgetChatSelectAvatarMessage.ts @@ -0,0 +1,34 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetChatSelectAvatarMessage extends RoomWidgetMessage +{ + public static MESSAGE_SELECT_AVATAR: string = 'RWCSAM_MESSAGE_SELECT_AVATAR'; + + private _objectId: number; + private _userName: string; + private _roomId: number; + + constructor(type: string, objectId: number, userName: string, roomId: number) + { + super(type); + + this._objectId = objectId; + this._userName = userName; + this._roomId = roomId; + } + + public get objectId(): number + { + return this._objectId; + } + + public get userName(): string + { + return this._userName; + } + + public get roomId(): number + { + return this._roomId; + } +} diff --git a/src/views/room/messages/RoomWidgetChatTypingMessage.ts b/src/views/room/messages/RoomWidgetChatTypingMessage.ts new file mode 100644 index 00000000..b3b0aa06 --- /dev/null +++ b/src/views/room/messages/RoomWidgetChatTypingMessage.ts @@ -0,0 +1,20 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetChatTypingMessage extends RoomWidgetMessage +{ + public static TYPING_STATUS: string = 'RWCTM_TYPING_STATUS'; + + private _isTyping: boolean; + + constructor(isTyping: boolean) + { + super(RoomWidgetChatTypingMessage.TYPING_STATUS); + + this._isTyping = isTyping; + } + + public get isTyping(): boolean + { + return this._isTyping; + } +} diff --git a/src/views/room/messages/RoomWidgetRequestWidgetMessage.ts b/src/views/room/messages/RoomWidgetRequestWidgetMessage.ts new file mode 100644 index 00000000..883974e0 --- /dev/null +++ b/src/views/room/messages/RoomWidgetRequestWidgetMessage.ts @@ -0,0 +1,10 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetRequestWidgetMessage extends RoomWidgetMessage +{ + public static USER_CHOOSER: string = 'RWRWM_USER_CHOOSER'; + public static FURNI_CHOOSER: string = 'RWRWM_FURNI_CHOOSER'; + public static ME_MENU: string = 'RWRWM_ME_MENU'; + public static EFFECTS: string = 'RWRWM_EFFECTS'; + public static FLOOR_EDITOR: string = 'RWRWM_FLOOR_EDITOR'; +} diff --git a/src/views/room/messages/index.ts b/src/views/room/messages/index.ts index 320b77c2..b11cc9a7 100644 --- a/src/views/room/messages/index.ts +++ b/src/views/room/messages/index.ts @@ -1,8 +1,12 @@ export * from './RoomWidgetAvatarExpressionMessage'; export * from './RoomWidgetChangeMottoMessage'; export * from './RoomWidgetChangePostureMessage'; +export * from './RoomWidgetChatMessage'; +export * from './RoomWidgetChatSelectAvatarMessage'; +export * from './RoomWidgetChatTypingMessage'; export * from './RoomWidgetDanceMessage'; export * from './RoomWidgetFurniActionMessage'; export * from './RoomWidgetMessage'; +export * from './RoomWidgetRequestWidgetMessage'; export * from './RoomWidgetRoomObjectMessage'; export * from './RoomWidgetUserActionMessage'; diff --git a/src/views/room/widgets/chat-input/ChatInputView.scss b/src/views/room/widgets/chat-input/ChatInputView.scss index 199a3dd8..60995c42 100644 --- a/src/views/room/widgets/chat-input/ChatInputView.scss +++ b/src/views/room/widgets/chat-input/ChatInputView.scss @@ -4,72 +4,62 @@ left: 50%; transform: translateX(-50%); bottom: 65px !important; + z-index: $chatinput-zindex; } } -.nitro-chat-input { - pointer-events: none; - z-index: $chatinput-zindex; +.nitro-chat-input-container { + display: flex; + justify-content: center; + align-items: center; + position: relative; + height: 40px; + border-radius: 8px; + border: 2px solid rgb(0, 0, 0); + background: #EDEDED; + padding-right: 30px; + width: 100%; - .chatinput-container { - position: relative; - height: 40px; + &:before { + content: ""; + position: absolute; + width: 98%; + height: 5px; border-radius: 8px; - border: 2px solid rgb(0, 0, 0); - background: #EDEDED; - pointer-events: all; - padding-right: 30px; - width: 100%; + top: 1px; + left: 0; + right: 0; + margin: auto; + background: rgb(255, 255, 255); + z-index: 1; + } - .input-sizer { - display: inline-grid; - vertical-align: top; - align-items: center; - position: relative; - height: 100%; - padding: 0 10px; - - &::after, - input, - textarea { - width: auto; - min-width: 1em; - grid-area: 1 / 2; - margin: 0; - resize: none; - background: none; - appearance: none; - border: none; - } - - &::after { - content: attr(data-value) ' '; - visibility: hidden; - white-space: pre-wrap; - } - } - - .chat-input { - height: 100%; - font-size: 16px; - outline: 0; - border: 0; - position: relative; - background: transparent; + .input-sizer { + display: inline-grid; + vertical-align: top; + height: 100%; + padding: 0 10px; + + &::after, + input, + textarea { + width: auto; + min-width: 1em; + grid-area: 1 / 2; + margin: 0; + resize: none; + background: none; + appearance: none; + border: none; + outline: none; } - - &:before { - content: ""; - position: absolute; - width: 98%; - height: 5px; - border-radius: 8px; - top: 1px; - left: 0; - right: 0; - margin: auto; - background: rgb(255, 255, 255); - z-index: 1; + + &::after { + content: attr(data-value) ' '; + visibility: hidden; + white-space: pre-wrap; } } } + +@import './style-selector/ChatInputStyleSelectorView'; diff --git a/src/views/room/widgets/chat-input/ChatInputView.tsx b/src/views/room/widgets/chat-input/ChatInputView.tsx index a791cf2c..3c4b7474 100644 --- a/src/views/room/widgets/chat-input/ChatInputView.tsx +++ b/src/views/room/widgets/chat-input/ChatInputView.tsx @@ -1,9 +1,13 @@ -import { FC, MouseEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; -import { GetConfiguration, GetRoomSession, SendChatTypingMessage } from '../../../../api'; +import { GetConfiguration } from '../../../../api'; +import { CreateEventDispatcherHook } from '../../../../hooks/events'; import { LocalizeText } from '../../../../utils/LocalizeText'; import { useRoomContext } from '../../context/RoomContext'; -import { ChatInputMessageType, ChatInputViewProps } from './ChatInputView.types'; +import { RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateInfostandUserEvent } from '../../events'; +import { RoomWidgetChatMessage, RoomWidgetChatTypingMessage } from '../../messages'; +import { ChatInputViewProps } from './ChatInputView.types'; +import { ChatInputStyleSelectorView } from './style-selector/ChatInputStyleSelectorView'; let lastContent = ''; @@ -13,6 +17,8 @@ export const ChatInputView: FC = props => const [ chatValue, setChatValue ] = useState(''); const [ selectedUsername, setSelectedUsername ] = useState(''); const [ isTyping, setIsTyping ] = useState(false); + const [ typingStartedSent, setTypingStartedSent ] = useState(false); + const [ isIdle, setIsIdle ] = useState(false); const inputRef = useRef(); const chatModeIdWhisper = useMemo(() => @@ -59,35 +65,24 @@ export const ChatInputView: FC = props => { setChatValue(prevValue => { - if((prevValue !== LocalizeText('widgets.chatinput.mode.whisper')) || !selectedUsername.length) return prevValue; + if((prevValue !== chatModeIdWhisper) || !selectedUsername.length) return prevValue; return (`${ prevValue } ${ selectedUsername }`); }); - }, [ selectedUsername ]); + }, [ selectedUsername, chatModeIdWhisper ]); const sendChat = useCallback((text: string, chatType: number, recipientName: string = '', styleId: number = 0) => { setChatValue(''); - switch(chatType) - { - case ChatInputMessageType.CHAT_DEFAULT: - GetRoomSession().sendChatMessage(text, styleId); - return; - case ChatInputMessageType.CHAT_WHISPER: - GetRoomSession().sendWhisperMessage(recipientName, text, styleId); - return; - case ChatInputMessageType.CHAT_SHOUT: - GetRoomSession().sendShoutMessage(text, styleId); - return; - } - }, []); + widgetHandler.processWidgetMessage(new RoomWidgetChatMessage(RoomWidgetChatMessage.MESSAGE_CHAT, text, chatType, recipientName, styleId)); + }, [ widgetHandler ]); const sendChatValue = useCallback((value: string, shiftKey: boolean = false) => { if(!value || (value === '')) return; - let chatType = (shiftKey ? ChatInputMessageType.CHAT_SHOUT : ChatInputMessageType.CHAT_DEFAULT); + let chatType = (shiftKey ? RoomWidgetChatMessage.CHAT_SHOUT : RoomWidgetChatMessage.CHAT_DEFAULT); let text = value; const parts = text.split(' '); @@ -98,7 +93,7 @@ export const ChatInputView: FC = props => switch(parts[0]) { case chatModeIdWhisper: - chatType = ChatInputMessageType.CHAT_WHISPER; + chatType = RoomWidgetChatMessage.CHAT_WHISPER; recipientName = parts[1]; append = (chatModeIdWhisper + ' ' + recipientName + ' '); @@ -106,12 +101,12 @@ export const ChatInputView: FC = props => parts.shift(); break; case chatModeIdShout: - chatType = ChatInputMessageType.CHAT_SHOUT; + chatType = RoomWidgetChatMessage.CHAT_SHOUT; parts.shift(); break; case chatModeIdSpeak: - chatType = ChatInputMessageType.CHAT_DEFAULT; + chatType = RoomWidgetChatMessage.CHAT_DEFAULT; parts.shift(); break; @@ -119,6 +114,9 @@ export const ChatInputView: FC = props => text = parts.join(' '); + setIsTyping(false); + setIsIdle(false); + if(text.length <= maxChatLength) { // if(this.needsStyleUpdate) @@ -132,32 +130,114 @@ export const ChatInputView: FC = props => sendChat(text, chatType, recipientName, currentStyle); } + + setChatValue(append); }, [ chatModeIdWhisper, chatModeIdShout, chatModeIdSpeak, maxChatLength, sendChat ]); + const updateChatInput = useCallback((value: string) => + { + if(!value || !value.length) + { + setIsTyping(false); + } + else + { + setIsTyping(true); + setIsIdle(true); + } + + setChatValue(value); + }, []); + const onKeyDownEvent = useCallback((event: KeyboardEvent) => { if(!inputRef.current || anotherInputHasFocus()) return; if(document.activeElement !== inputRef.current) setInputFocus(); - switch(event.key) + const value = (event.target as HTMLInputElement).value; + + switch(event.code) { case 'Space': checkSpecialKeywordForInput(); return; case 'Enter': - sendChatValue((event.target as HTMLInputElement).value, event.shiftKey); + sendChatValue(value, event.shiftKey); return; case 'Backspace': + if(value) + { + const parts = value.split(' '); + + if((parts[0] === chatModeIdWhisper) && (parts.length === 3) && (parts[2] === '')) + { + setChatValue(''); + } + } return; } - }, [ inputRef, anotherInputHasFocus, setInputFocus, checkSpecialKeywordForInput, sendChatValue ]); + }, [ inputRef, chatModeIdWhisper, anotherInputHasFocus, setInputFocus, checkSpecialKeywordForInput, sendChatValue ]); - const onInputMouseDownEvent = useCallback((event: MouseEvent) => + const onStyleSelected = useCallback((styleId: number) => { - setInputFocus(); - }, [ setInputFocus ]); + + }, []); + + const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) => + { + setSelectedUsername(''); + }, []); + + CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent); + + const onRoomWidgetUpdateInfostandUserEvent = useCallback((event: RoomWidgetUpdateInfostandUserEvent) => + { + setSelectedUsername(event.name); + }, []); + + CreateEventDispatcherHook(RoomWidgetUpdateInfostandUserEvent.PEER, eventDispatcher, onRoomWidgetUpdateInfostandUserEvent); + + useEffect(() => + { + if(isTyping) + { + if(!typingStartedSent) + { + setTypingStartedSent(true); + + widgetHandler.processWidgetMessage(new RoomWidgetChatTypingMessage(isTyping)); + } + } + else + { + if(typingStartedSent) + { + setTypingStartedSent(false); + + widgetHandler.processWidgetMessage(new RoomWidgetChatTypingMessage(isTyping)); + } + } + }, [ widgetHandler, isTyping, typingStartedSent ]); + + useEffect(() => + { + if(!isIdle) return; + + let timeout: ReturnType = null; + + if(isIdle) + { + timeout = setTimeout(() => + { + setIsIdle(false); + setIsTyping(false) + }, 10000); + } + + return () => clearTimeout(timeout); + }, [ isIdle ]); useEffect(() => { @@ -169,59 +249,13 @@ export const ChatInputView: FC = props => } }, [ onKeyDownEvent ]); - useEffect(() => - { - let idleTimer: ReturnType = null; - - if(!chatValue || !chatValue.length) - { - setIsTyping(prevValue => - { - if(!prevValue) return prevValue; - - if(prevValue) SendChatTypingMessage(false); - - return false; - }); - } - else - { - setIsTyping(prevValue => - { - if(prevValue) return prevValue; - - if(!prevValue) SendChatTypingMessage(true); - - return true; - }); - - lastContent = chatValue; - - idleTimer = setTimeout(() => - { - setIsTyping(prevValue => - { - if(prevValue) SendChatTypingMessage(false); - - return false; - }); - }, 3000); - } - - return () => - { - if(idleTimer) clearTimeout(idleTimer); - } - }, [ chatValue ]); - return ( createPortal( -
-
-
- { event.target.parentElement.dataset.value = event.target.value; setChatValue(event.target.value) } } onMouseDown={ onInputMouseDownEvent } /> -
+
+
+ { event.target.parentElement.dataset.value = event.target.value; updateChatInput(event.target.value) } } onMouseDown={ event => setInputFocus() } />
+
, document.getElementById('toolbar-chat-input-container')) ); } diff --git a/src/views/room/widgets/chat-input/ChatInputView.types.ts b/src/views/room/widgets/chat-input/ChatInputView.types.ts index 563b9d4f..fe19aca1 100644 --- a/src/views/room/widgets/chat-input/ChatInputView.types.ts +++ b/src/views/room/widgets/chat-input/ChatInputView.types.ts @@ -4,10 +4,3 @@ export interface ChatInputViewProps extends RoomWidgetProps { } - -export class ChatInputMessageType -{ - public static CHAT_DEFAULT: number = 0; - public static CHAT_WHISPER: number = 1; - public static CHAT_SHOUT: number = 2; -} diff --git a/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.scss b/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.scss new file mode 100644 index 00000000..5be93b7c --- /dev/null +++ b/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.scss @@ -0,0 +1,61 @@ +.nitro-chat-style-selector-button { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + height: 100%; + right: 7px; +} + +.nitro-chat-style-selector-test { + display: flex; + position: relative; + right: 30px; + pointer-events: all; + height: 100%; + + i.icon { + cursor: pointer; + align-self: center; + } + + .nitro-chatstyle-selector { + position: absolute; + width: 250px; + top: -4px; + transition: transform 0.22s ease-in-out; + transform: translate(-81px, -50%) scale(0); + + &.active { + visibility: visible; + transform: translate(-160px, -100%) scale(1); + } + + .grid-container { + + .grid-items { + margin-top: -7px; + + .item-detail { + height: 30px; + max-height: 30px; + width: calc(1 / 3 * 100% - (1 - 1 / 3) * 7px); + margin: 7px 7px 0 0; + overflow: visible; + + &:hover { + cursor: pointer; + } + + .detail-info { + + .bubble-container { + visibility: visible; + width: 75%; + } + } + } + } + } + } +} diff --git a/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.tsx b/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.tsx new file mode 100644 index 00000000..52d1d43f --- /dev/null +++ b/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.tsx @@ -0,0 +1,20 @@ +import { FC, useState } from 'react'; +import { ChatInputStyleSelectorViewProps } from './ChatInputStyleSelectorView.types'; + +export const ChatInputStyleSelectorView: FC = props => +{ + const { onStyleSelected = null } = props; + const [ selectorVisible, setSelectorVisible ] = useState(false); + + return ( + <> +
+ +
+ { selectorVisible && +
+ +
} + + ) +} diff --git a/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.types.ts b/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.types.ts new file mode 100644 index 00000000..bd159ffe --- /dev/null +++ b/src/views/room/widgets/chat-input/style-selector/ChatInputStyleSelectorView.types.ts @@ -0,0 +1,4 @@ +export interface ChatInputStyleSelectorViewProps +{ + onStyleSelected: (styleId: number) => void; +}