mirror of
https://github.com/duckietm/Nitro-Cool-UI.git
synced 2025-06-21 22:36:58 +00:00
Added: ChatColors / Make stuff LocalCache in browser
This commit is contained in:
parent
c00f4329d3
commit
e1bcafbb28
@ -22,10 +22,13 @@ export class ChatBubbleMessage
|
|||||||
public type: number = 0,
|
public type: number = 0,
|
||||||
public styleId: number = 0,
|
public styleId: number = 0,
|
||||||
public imageUrl: string = null,
|
public imageUrl: string = null,
|
||||||
public color: string = null
|
public color: string = null,
|
||||||
|
public chatColours: string = ""
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.id = ++ChatBubbleMessage.BUBBLE_COUNTER;
|
this.id = ++ChatBubbleMessage.BUBBLE_COUNTER;
|
||||||
|
this.color = color;
|
||||||
|
this.chatColours = chatColours;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get top(): number
|
public get top(): number
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const allowedColours: Map<string, string> = new Map();
|
import { GetConfiguration } from '@nitrots/nitro-renderer';
|
||||||
|
export const allowedColours: Map<string, string> = new Map();
|
||||||
|
|
||||||
allowedColours.set('r', 'red');
|
allowedColours.set('r', 'red');
|
||||||
allowedColours.set('b', 'blue');
|
allowedColours.set('b', 'blue');
|
||||||
@ -11,16 +12,109 @@ allowedColours.set('br', 'brown');
|
|||||||
allowedColours.set('pr', 'purple');
|
allowedColours.set('pr', 'purple');
|
||||||
allowedColours.set('pk', 'pink');
|
allowedColours.set('pk', 'pink');
|
||||||
|
|
||||||
|
allowedColours.set('black', 'black');
|
||||||
allowedColours.set('red', 'red');
|
allowedColours.set('red', 'red');
|
||||||
allowedColours.set('blue', 'blue');
|
allowedColours.set('orangered', 'orangered');
|
||||||
allowedColours.set('green', 'green');
|
|
||||||
allowedColours.set('yellow', 'yellow');
|
|
||||||
allowedColours.set('white', 'white');
|
|
||||||
allowedColours.set('orange', 'orange');
|
allowedColours.set('orange', 'orange');
|
||||||
allowedColours.set('cyan', 'cyan');
|
allowedColours.set('yellow', 'yellow');
|
||||||
allowedColours.set('brown', 'brown');
|
allowedColours.set('yellowgreen', 'yellowgreen');
|
||||||
|
allowedColours.set('green', 'green');
|
||||||
|
allowedColours.set('seagreen', 'seagreen');
|
||||||
|
allowedColours.set('teal', 'teal');
|
||||||
|
allowedColours.set('blue', 'blue');
|
||||||
|
allowedColours.set('darkblue', 'darkblue');
|
||||||
|
allowedColours.set('indigo', 'indigo');
|
||||||
allowedColours.set('purple', 'purple');
|
allowedColours.set('purple', 'purple');
|
||||||
allowedColours.set('pink', 'pink');
|
allowedColours.set('violet', 'violet');
|
||||||
|
allowedColours.set('brown', 'brown');
|
||||||
|
allowedColours.set('burlywood', 'burlywood');
|
||||||
|
allowedColours.set('rosybrown', 'rosybrown');
|
||||||
|
allowedColours.set('saddlebrown', 'saddlebrown');
|
||||||
|
allowedColours.set('maroon', 'maroon');
|
||||||
|
allowedColours.set('firebrick', 'firebrick');
|
||||||
|
allowedColours.set('darkred', 'darkred');
|
||||||
|
allowedColours.set('chocolate', 'chocolate');
|
||||||
|
allowedColours.set('sienna', 'sienna');
|
||||||
|
allowedColours.set('peru', 'peru');
|
||||||
|
allowedColours.set('darkorange', 'darkorange');
|
||||||
|
allowedColours.set('orange', 'orange');
|
||||||
|
allowedColours.set('orangered', 'orangered');
|
||||||
|
allowedColours.set('tomato', 'tomato');
|
||||||
|
allowedColours.set('coral', 'coral');
|
||||||
|
allowedColours.set('darkolivegreen', 'darkolivegreen');
|
||||||
|
allowedColours.set('olive', 'olive');
|
||||||
|
allowedColours.set('olivedrab', 'olivedrab');
|
||||||
|
allowedColours.set('greenyellow', 'greenyellow');
|
||||||
|
allowedColours.set('yellowgreen', 'yellowgreen');
|
||||||
|
allowedColours.set('darkgreen', 'darkgreen');
|
||||||
|
allowedColours.set('limegreen', 'limegreen');
|
||||||
|
allowedColours.set('lime', 'lime');
|
||||||
|
allowedColours.set('lawngreen', 'lawngreen');
|
||||||
|
allowedColours.set('palegreen', 'palegreen');
|
||||||
|
allowedColours.set('springgreen', 'springgreen');
|
||||||
|
allowedColours.set('mediumseagreen', 'mediumseagreen');
|
||||||
|
allowedColours.set('mediumaquamarine', 'mediumaquamarine');
|
||||||
|
allowedColours.set('aquamarine', 'aquamarine');
|
||||||
|
allowedColours.set('turquoise', 'turquoise');
|
||||||
|
allowedColours.set('mediumturquoise', 'mediumturquoise');
|
||||||
|
allowedColours.set('darkturquoise', 'darkturquoise');
|
||||||
|
allowedColours.set('aqua', 'aqua');
|
||||||
|
allowedColours.set('cyan', 'cyan');
|
||||||
|
allowedColours.set('lightcyan', 'lightcyan');
|
||||||
|
allowedColours.set('paleturquoise', 'paleturquoise');
|
||||||
|
allowedColours.set('azure', 'azure');
|
||||||
|
allowedColours.set('lightblue', 'lightblue');
|
||||||
|
allowedColours.set('powderblue', 'powderblue');
|
||||||
|
allowedColours.set('deepskyblue', 'deepskyblue');
|
||||||
|
allowedColours.set('skyblue', 'skyblue');
|
||||||
|
allowedColours.set('lightskyblue', 'lightskyblue');
|
||||||
|
allowedColours.set('steelblue', 'steelblue');
|
||||||
|
allowedColours.set('royalblue', 'royalblue');
|
||||||
|
allowedColours.set('mediumslateblue', 'mediumslateblue');
|
||||||
|
allowedColours.set('slateblue', 'slateblue');
|
||||||
|
allowedColours.set('darkslateblue', 'darkslateblue');
|
||||||
|
allowedColours.set('mediumpurple', 'mediumpurple');
|
||||||
|
allowedColours.set('blueviolet', 'blueviolet');
|
||||||
|
allowedColours.set('darkviolet', 'darkviolet');
|
||||||
|
allowedColours.set('darkmagenta', 'darkmagenta');
|
||||||
|
allowedColours.set('mediumvioletred', 'mediumvioletred');
|
||||||
|
allowedColours.set('violetred', 'violetred');
|
||||||
|
allowedColours.set('orchid', 'orchid');
|
||||||
|
allowedColours.set('darkorchid', 'darkorchid');
|
||||||
|
allowedColours.set('mediumorchid', 'mediumorchid');
|
||||||
|
allowedColours.set('thistle', 'thistle');
|
||||||
|
allowedColours.set('plum', 'plum');
|
||||||
|
allowedColours.set('purple', 'purple');
|
||||||
|
allowedColours.set('darkgrey', 'darkgrey');
|
||||||
|
allowedColours.set('dimgray', 'dimgray');
|
||||||
|
allowedColours.set('lightgrey', 'lightgrey');
|
||||||
|
allowedColours.set('grey', 'grey');
|
||||||
|
allowedColours.set('slategrey', 'slategrey');
|
||||||
|
allowedColours.set('lightslategrey', 'lightslategrey');
|
||||||
|
allowedColours.set('whitesmoke', 'whitesmoke');
|
||||||
|
allowedColours.set('white', 'white');
|
||||||
|
allowedColours.set('snow', 'snow');
|
||||||
|
allowedColours.set('mistyrose', 'mistyrose');
|
||||||
|
allowedColours.set('seashell', 'seashell');
|
||||||
|
allowedColours.set('antiquewhite', 'antiquewhite');
|
||||||
|
allowedColours.set('linen', 'linen');
|
||||||
|
allowedColours.set('oldlace', 'oldlace');
|
||||||
|
allowedColours.set('papayawhip', 'papayawhip');
|
||||||
|
allowedColours.set('blanchedalmond', 'blanchedalmond');
|
||||||
|
allowedColours.set('moccasin', 'moccasin');
|
||||||
|
allowedColours.set('wheat', 'wheat');
|
||||||
|
allowedColours.set('navajowhite', 'navajowhite');
|
||||||
|
allowedColours.set('burlywood', 'burlywood');
|
||||||
|
allowedColours.set('tan', 'tan');
|
||||||
|
allowedColours.set('rosybrown', 'rosybrown');
|
||||||
|
allowedColours.set('sandybrown', 'sandybrown');
|
||||||
|
allowedColours.set('goldenrod', 'goldenrod');
|
||||||
|
allowedColours.set('darkgoldenrod', 'darkgoldenrod');
|
||||||
|
allowedColours.set('peru', 'peru');
|
||||||
|
allowedColours.set('chocolate', 'chocolate');
|
||||||
|
allowedColours.set('saddlebrown', 'saddlebrown');
|
||||||
|
allowedColours.set('sienna', 'sienna');
|
||||||
|
allowedColours.set('brown', 'brown');
|
||||||
|
|
||||||
const encodeHTML = (str: string) =>
|
const encodeHTML = (str: string) =>
|
||||||
{
|
{
|
||||||
@ -37,37 +131,38 @@ const encodeHTML = (str: string) =>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RoomChatFormatter = (content: string) =>
|
export const RoomChatFormatter = (content: string) => {
|
||||||
{
|
|
||||||
let result = '';
|
let result = '';
|
||||||
|
|
||||||
content = encodeHTML(content);
|
content = encodeHTML(content);
|
||||||
//content = (joypixels.shortnameToUnicode(content) as string)
|
content = content.replace(/\[tag\](.*?)\[\/tag\]/g, '<span class="chat-tag"><b>$1</b></span>');
|
||||||
|
|
||||||
if(content.startsWith('@') && content.indexOf('@', 1) > -1)
|
// Youtube link
|
||||||
{
|
if (!GetConfiguration<boolean>('youtube.publish.disabled', false)) {
|
||||||
let match = null;
|
content = content.replace(
|
||||||
|
/(?:http:\/\/|https:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?.*v=|shorts\/)?([a-zA-Z0-9_-]{11})/g,
|
||||||
|
`
|
||||||
|
<div>
|
||||||
|
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEQElEQVR4nO2X7WscRRzHt+AbfeEfICK+VVTwjWhVUnI7l8SkDY3Wu5ltfbiZXBNbq8ldiZEkVbHSIAEjCtUWNLXFaNWQElOUomKwD0bxoVLtk3I+oPhUjbvZ5x2Zmb29DUlaa3fTO9gvDOzMbx5+n535zYMkJUqUKFFNKoVIK0CEyogcKZfJCO/2y3qkaldLPn+ZDLEGELYbFeVyVgYgLnGADL5GqgUBRCaYwwC1NzUq5EruPCQnpVpRGpG87/RgGhJFLB88xGzyuvxVAOGtAOIXmU2SpGWsHKzNXcfaySh/Pe9DyeVSkNxzUQDkbO4KgIjH4kBGZLuAaa/j5ZD8LmZHJBniAd4Gtj8kynCXyBNVRuRX6WIJIDLN4gBA/CNzuq5uyyWhmRllQL69VJUAMsQDlT+NR3ynHhXLKVfkkJCcAZDoVQmQyuZuLAOkYPudNQcgSdIysZ0SWq/cf20tAkgyJDMJQHXNAN7ox8WTN6/pulRG2AAI/xZeQjLEj7ATG0BsVd0Sqs/iG2REHO64f70ACL/BbKEtVpUh+VvUqzIAJqDgewEip5lNRmQfO9xYeUNm/dUAkZ8AwidkmL+tKoI40VLJeGZbv97dWdIIVLVcRtOUVlPNrrR4urvZVlvrvSClb6Fq6iaR2HfYxur67TSl1eR9Eaiyvo1nB/ticV7vL04HDsWc9P5i8EiKRObw4GNL5bzqJzbbkQHo3R0/sE7dE99Qb2ZmXnK++HRRR6zxvbyO9fru85uFro7vIwPQcFZlnXq//EwXkvvtqUUdsQ/s53Xst8fOC0DLZdToANa1Gfyv9DxIjSd6qVv6Tjh+/Gue14sPRA+wdrURGYCaXWmHO3e+/Iw75Rz8UEx3X4Far45Qvb9AtUwz/7Z27ZwLMPUeNV9+gVqju6i2GlTW+uDj1Jl6n9ofHOD9BONkW+zoANrS7tkA7Mlx4eT+fVTvWi/WlefOAQjL+Ui0M3c8P8+mFzeIcdrSbnQALSu8CwVwjx0N6nnqP9zm/fmHaPfOBHVPnwz64OO0rPCiA2hYTi8UgMWA3vuwb/Ooesftlb9e6KTWm6Oiz+lDYpyG5TQ6gPCpGhVAc10A4GkapabpAxyOASCCJXQ2gLCcQ1MxLKEIgngOAKVzAPTuDrZtUn3zRjpLYAxBfI5t9H8BhGOguIFab/kx8PHB6LfR8kF2LgD31HG+2ywE4Bz9nFp7XhI22xK70F9neJYFsHvsK2GaHI/+ICtfJRYDsF7ZWVnEtr0gQFjMWd5u7555Nr1nU/RXifJlrpzM54aoPTFGjaGnxGB3NVL73Ul+cZvdRLjNGntNnLTbtvC8uX2Y/2m258/et8bfaW6l1sgODuR8coQaW/viuczV/HWaiT0ylsp5fWDzYSkOseeeXgg9KeEqq/KkbHL++5OyyQmelHCVFTwpC50lY/jp3licT5QoUSIpDv0L7jL5ksuHFDUAAAAASUVORK5CYII="
|
||||||
|
alt="YouTube Icon" style="vertical-align: middle; margin-right: 5px;"><strong>Click on open video to see the YouTube video</strong>
|
||||||
|
</div><center><a href="https://youtu.be/$1" target="_blank" style="background-color: red; color: white; padding: 5px 10px; border-radius: 5px; text-decoration: none;">Open Video</a></center>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
while((match = /@[a-zA-Z]+@/g.exec(content)) !== null)
|
const match = content.match(/@[a-zA-Z]+@/);
|
||||||
{
|
if (match) {
|
||||||
const colorTag = match[0].toString();
|
const colorTag = match[0].toString();
|
||||||
const colorName = colorTag.substr(1, colorTag.length - 2);
|
const colorName = colorTag.substr(1, colorTag.length - 2);
|
||||||
const text = content.replace(colorTag, '');
|
const text = content.replace(colorTag, '');
|
||||||
|
|
||||||
if(!allowedColours.has(colorName))
|
if (!allowedColours.has(colorName)) {
|
||||||
{
|
|
||||||
result = text;
|
result = text;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
const color = allowedColours.get(colorName);
|
const color = allowedColours.get(colorName);
|
||||||
result = '<span style="color: ' + color + '">' + text + '</span>';
|
result = `<span style="color: ${color}">${text}</span>`;
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = content;
|
result = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
import { FC, useEffect, useRef, useState } from 'react';
|
||||||
|
import { Overlay, Popover } from 'react-bootstrap';
|
||||||
|
import { MdFormatColorText } from 'react-icons/md';
|
||||||
|
import { allowedColours } from '../../../../api';
|
||||||
|
import { AutoGrid, Base, LayoutGridItem, NitroCardContentView } from '../../../../common';
|
||||||
|
|
||||||
|
interface ChatInputColorSelectorViewProps
|
||||||
|
{
|
||||||
|
chatColour: string;
|
||||||
|
selectColour: (color: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatInputColorSelectorView: FC<ChatInputColorSelectorViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { chatColour = 'black', selectColour = null } = props;
|
||||||
|
const [ selectorVisible, setSelectorVisible ] = useState(false);
|
||||||
|
const [ colours, setColours ] = useState<Map<string, string>>(null);
|
||||||
|
const iconRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const excludedColors = new Set(["r", "b", "g", "y", "w", "o", "c", "br", "pr", "pk"]);
|
||||||
|
const uniqueColours = new Map<string, string>();
|
||||||
|
|
||||||
|
allowedColours.forEach((value, key) => {
|
||||||
|
if (!excludedColors.has(key) && !Array.from(uniqueColours.values()).includes(value)) {
|
||||||
|
uniqueColours.set(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setColours(uniqueColours);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const selectColor = (color: string) =>
|
||||||
|
{
|
||||||
|
selectColour(color);
|
||||||
|
setSelectorVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleSelector = () =>
|
||||||
|
{
|
||||||
|
setSelectorVisible(prevValue => !prevValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Base pointer onClick={ () => toggleSelector() } innerRef={ iconRef } style={ { color: (colours && colours.get(chatColour)) ?? 'black' } }>
|
||||||
|
<MdFormatColorText />
|
||||||
|
</Base>
|
||||||
|
<Overlay show={ selectorVisible } target={ iconRef } placement="top">
|
||||||
|
<Popover className="nitro-chat-style-selector-container">
|
||||||
|
<NitroCardContentView overflow="hidden" className="bg-transparent colour-container image-rendering-pixelated">
|
||||||
|
<AutoGrid gap={ 1 } columnCount={ 6 } columnMinWidth={ 20 } columnMinHeight={ 20 }>
|
||||||
|
{ colours && (colours.size > 0) && Array.from(colours).map(([ color, hex ]) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<LayoutGridItem itemHighlight itemColor={ hex } itemActive={ chatColour === color } className="clear-bg" onClick={ event => selectColor(color) } key={ color }></LayoutGridItem>
|
||||||
|
);
|
||||||
|
}) }
|
||||||
|
</AutoGrid>
|
||||||
|
</NitroCardContentView>
|
||||||
|
</Popover>
|
||||||
|
</Overlay>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
import { FC, MouseEvent, useEffect, useRef, useState } from 'react';
|
||||||
|
import { Overlay, Popover } from 'react-bootstrap';
|
||||||
|
import { Base, Flex, Grid, NitroCardContentView } from '../../../../common';
|
||||||
|
import data from '@emoji-mart/data'
|
||||||
|
import Picker from '@emoji-mart/react'
|
||||||
|
|
||||||
|
interface ChatInputEmojiSelectorViewProps
|
||||||
|
{
|
||||||
|
addChatEmoji: (emoji: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatInputEmojiSelectorView: FC<ChatInputEmojiSelectorViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { addChatEmoji = null } = props;
|
||||||
|
const [ selectorVisible, setSelectorVisible ] = useState(false);
|
||||||
|
const [ target, setTarget ] = useState<(EventTarget & HTMLElement)>(null);
|
||||||
|
const iconRef = useRef<HTMLDivElement>(null);
|
||||||
|
const componentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleEmojiSelect = (emoji: any) => {
|
||||||
|
addChatEmoji(emoji.native);
|
||||||
|
setSelectorVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addEmojiToChat = (emoji: string) => {
|
||||||
|
setChatValue(chatValue + emoji);
|
||||||
|
setIsTyping(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
const className = 'emoji-icon';
|
||||||
|
if (componentRef.current && !componentRef.current.contains(event.target as Node) && !(event.target as Element).classList.contains(className)) {
|
||||||
|
setSelectorVisible(false);
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside as any);
|
||||||
|
setTarget(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectEmoji = (emoji: string) =>
|
||||||
|
{
|
||||||
|
addChatEmoji(emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleSelector = (event: MouseEvent<HTMLElement>) =>
|
||||||
|
{
|
||||||
|
setSelectorVisible(prevValue => !prevValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(selectorVisible) {
|
||||||
|
document.addEventListener('mousedown', handleClickOutside as any);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTarget(null);
|
||||||
|
}
|
||||||
|
}, [ componentRef, selectorVisible ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Base pointer onClick={toggleSelector} innerRef={iconRef}>🙂</Base>
|
||||||
|
<Overlay show={selectorVisible} target={iconRef} placement="top-end">
|
||||||
|
<Popover>
|
||||||
|
<Picker data={data} onEmojiSelect={handleEmojiSelect} />
|
||||||
|
</Popover>
|
||||||
|
</Overlay>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -46,9 +46,9 @@ export const ChatInputStyleSelectorView: FC<ChatInputStyleSelectorViewProps> = p
|
|||||||
<>
|
<>
|
||||||
<Base pointer className="icon chatstyles-icon" onClick={ toggleSelector } />
|
<Base pointer className="icon chatstyles-icon" onClick={ toggleSelector } />
|
||||||
<Overlay show={ selectorVisible } target={ target } placement="top">
|
<Overlay show={ selectorVisible } target={ target } placement="top">
|
||||||
<Popover className="nitro-chat-style-selector-container image-rendering-pixelated">
|
<Popover className="nitro-chat-style-selector-container">
|
||||||
<NitroCardContentView overflow="hidden" className="bg-transparent">
|
<NitroCardContentView overflow="hidden" className="bg-transparent bubble-window image-rendering-pixelated">
|
||||||
<Grid columnCount={ 3 } overflow="auto">
|
<Grid gap={ 1 } columnCount={ 3 } overflow="auto">
|
||||||
{ chatStyleIds && (chatStyleIds.length > 0) && chatStyleIds.map((styleId) =>
|
{ chatStyleIds && (chatStyleIds.length > 0) && chatStyleIds.map((styleId) =>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
|
@ -1,29 +1,30 @@
|
|||||||
.nitro-chat-input-container {
|
.nitro-chat-input-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 8px;
|
border-radius: 0.5rem;
|
||||||
border: 2px solid rgb(0, 0, 0);
|
border: 2px solid #000;
|
||||||
background: #EDEDED;
|
box-shadow: 0 0 0 1pt #fff!important;
|
||||||
|
background: #ededed;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
width: -webkit-fill-available;
|
||||||
|
|
||||||
@include media-breakpoint-down(sm) {
|
@include media-breakpoint-down(xxl) {
|
||||||
display: flex;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 70px;
|
bottom: 70px;
|
||||||
left: calc(100% / 3);
|
left: 50%;
|
||||||
width: 200px;
|
transform: translateX(-50%);
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 5px;
|
height: 2px;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -54,15 +55,42 @@
|
|||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: attr(data-value) ' ';
|
content: attr(data-value) ' ';
|
||||||
|
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.colour-container {
|
||||||
|
visibility: visible;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.bubble-container {
|
.bubble-container {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
}
|
}
|
||||||
|
.nitro-chat-style-box {
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 0.75em;
|
||||||
|
margin-right: 2px;
|
||||||
|
width: 34px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-chat-input-container .input-sizer input{
|
||||||
|
width: auto;
|
||||||
|
min-width: 1em;
|
||||||
|
grid-area: 1 / 2;
|
||||||
|
margin: 0;
|
||||||
|
resize: none;
|
||||||
|
background: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-chat-style-selector-container {
|
.nitro-chat-style-selector-container {
|
||||||
@ -73,6 +101,34 @@
|
|||||||
max-height: $chat-input-style-selector-widget-height !important;
|
max-height: $chat-input-style-selector-widget-height !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: lightblue;
|
||||||
|
border-radius: 60%;
|
||||||
|
z-index: -1;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji:hover {
|
||||||
|
transform: scale(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
.bubble-parent-container {
|
.bubble-parent-container {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|
||||||
@ -82,3 +138,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info-habbopages {
|
||||||
|
cursor: pointer;
|
||||||
|
background-image: url("@/assets/images/boxes/card/questionmark.png");
|
||||||
|
width: 19px;
|
||||||
|
height: 20px;
|
||||||
|
right: -2px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-image: url("@/assets/images/boxes/card/questionmark_hover.png");
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-image: url("@/assets/images/boxes/card/questionmark_click.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
import { GetSessionDataManager, HabboClubLevelEnum, RoomControllerLevel } from '@nitrots/nitro-renderer';
|
import { CreateLinkEvent, GetSessionDataManager, HabboClubLevelEnum, RoomControllerLevel } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { ChatMessageTypeEnum, GetClubMemberLevel, GetConfigurationValue, LocalizeText, RoomWidgetUpdateChatInputContentEvent } from '../../../../api';
|
import { ChatMessageTypeEnum, GetConfigurationValue, GetClubMemberLevel, LocalizeText, RoomWidgetUpdateChatInputContentEvent } from '../../../../api';
|
||||||
import { Text } from '../../../../common';
|
import { Base, Flex, Text } from '../../../../common';
|
||||||
import { useChatInputWidget, useRoom, useSessionInfo, useUiEvent } from '../../../../hooks';
|
import { useChatInputWidget, useRoom, useSessionInfo, useUiEvent } from '../../../../hooks';
|
||||||
import { ChatInputStyleSelectorView } from './ChatInputStyleSelectorView';
|
import { ChatInputStyleSelectorView } from './ChatInputStyleSelectorView';
|
||||||
|
import { ChatInputEmojiSelectorView } from './ChatInputEmojiSelectorView';
|
||||||
|
import { ChatInputColorSelectorView } from './ChatInputColorSelectorView';
|
||||||
|
|
||||||
|
|
||||||
export const ChatInputView: FC<{}> = props =>
|
export const ChatInputView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ chatValue, setChatValue ] = useState<string>('');
|
const [ chatValue, setChatValue ] = useState<string>('');
|
||||||
const { chatStyleId = 0, updateChatStyleId = null } = useSessionInfo();
|
const { chatStyleId = 0, updateChatStyleId = null, chatColour = '', updateChatColour = null } = useSessionInfo();
|
||||||
const { selectedUsername = '', floodBlocked = false, floodBlockedSeconds = 0, setIsTyping = null, setIsIdle = null, sendChat = null } = useChatInputWidget();
|
const { selectedUsername = '', floodBlocked = false, floodBlockedSeconds = 0, setIsTyping = null, setIsIdle = null, sendChat = null } = useChatInputWidget();
|
||||||
|
const [ showInfoHabboPages, setShowInfohabboPages ] = useState<boolean>(false);
|
||||||
const { roomSession = null } = useRoom();
|
const { roomSession = null } = useRoom();
|
||||||
const inputRef = useRef<HTMLInputElement>();
|
|
||||||
|
|
||||||
|
const inputRef = useRef<HTMLInputElement>();
|
||||||
const chatModeIdWhisper = useMemo(() => LocalizeText('widgets.chatinput.mode.whisper'), []);
|
const chatModeIdWhisper = useMemo(() => LocalizeText('widgets.chatinput.mode.whisper'), []);
|
||||||
const chatModeIdShout = useMemo(() => LocalizeText('widgets.chatinput.mode.shout'), []);
|
const chatModeIdShout = useMemo(() => LocalizeText('widgets.chatinput.mode.shout'), []);
|
||||||
const chatModeIdSpeak = useMemo(() => LocalizeText('widgets.chatinput.mode.speak'), []);
|
const chatModeIdSpeak = useMemo(() => LocalizeText('widgets.chatinput.mode.speak'), []);
|
||||||
@ -97,12 +101,12 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
setChatValue('');
|
setChatValue('');
|
||||||
sendChat(text, chatType, recipientName, chatStyleId);
|
sendChat(text, chatType, recipientName, chatStyleId, chatColour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setChatValue(append);
|
setChatValue(append);
|
||||||
}, [ chatModeIdWhisper, chatModeIdShout, chatModeIdSpeak, maxChatLength, chatStyleId, setIsTyping, setIsIdle, sendChat ]);
|
}, [ chatModeIdWhisper, chatModeIdShout, chatModeIdSpeak, maxChatLength, chatStyleId, setIsTyping, setIsIdle, sendChat, chatColour ]);
|
||||||
|
|
||||||
const updateChatInput = useCallback((value: string) =>
|
const updateChatInput = useCallback((value: string) =>
|
||||||
{
|
{
|
||||||
@ -214,6 +218,11 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
return styleIds;
|
return styleIds;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const addEmojiToChat = (emoji: string) => {
|
||||||
|
setChatValue(chatValue + emoji);
|
||||||
|
setIsTyping(true);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
document.body.addEventListener('keydown', onKeyDownEvent);
|
document.body.addEventListener('keydown', onKeyDownEvent);
|
||||||
@ -235,14 +244,30 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
createPortal(
|
createPortal(
|
||||||
<div className="nitro-chat-input-container">
|
<div className="nitro-chat-input-container" onMouseEnter={ () => setShowInfohabboPages(true) } onMouseLeave={ () => setTimeout(() => setShowInfohabboPages(false), 100) }>
|
||||||
<div className="input-sizer align-items-center">
|
<div className="input-sizer align-items-center">
|
||||||
{ !floodBlocked &&
|
{ !floodBlocked &&
|
||||||
<input ref={ inputRef } type="text" className="chat-input" placeholder={ LocalizeText('widgets.chatinput.default') } value={ chatValue } maxLength={ maxChatLength } onChange={ event => updateChatInput(event.target.value) } onMouseDown={ event => setInputFocus() } /> }
|
<input
|
||||||
|
ref={ inputRef }
|
||||||
|
type="text"
|
||||||
|
className="chat-input"
|
||||||
|
placeholder={ LocalizeText('widgets.chatinput.default') }
|
||||||
|
value={ chatValue }
|
||||||
|
maxLength={ maxChatLength }
|
||||||
|
onChange={ event => updateChatInput(event.target.value) }
|
||||||
|
onMouseDown={ event => setInputFocus() } />
|
||||||
|
}
|
||||||
{ floodBlocked &&
|
{ floodBlocked &&
|
||||||
<Text variant="danger">{ LocalizeText('chat.input.alert.flood', [ 'time' ], [ floodBlockedSeconds.toString() ]) } </Text> }
|
<Text variant="danger">{ LocalizeText('chat.input.alert.flood', [ 'time' ], [ floodBlockedSeconds.toString() ]) } </Text> }
|
||||||
</div>
|
</div>
|
||||||
|
<Flex>
|
||||||
|
<ChatInputEmojiSelectorView addChatEmoji={ addEmojiToChat } />
|
||||||
|
<ChatInputColorSelectorView chatColour={ chatColour } selectColour={ updateChatColour } />
|
||||||
<ChatInputStyleSelectorView chatStyleId={ chatStyleId } chatStyleIds={ chatStyleIds } selectChatStyleId={ updateChatStyleId } />
|
<ChatInputStyleSelectorView chatStyleId={ chatStyleId } chatStyleIds={ chatStyleIds } selectChatStyleId={ updateChatStyleId } />
|
||||||
|
{
|
||||||
|
(showInfoHabboPages) && <Base className="info-habbopages" onClick={ () => CreateLinkEvent('habbopages/chat/chatting') }></Base>
|
||||||
|
}
|
||||||
|
</Flex>
|
||||||
</div>, document.getElementById('toolbar-chat-input-container'))
|
</div>, document.getElementById('toolbar-chat-input-container'))
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -7,11 +7,11 @@ interface ChatWidgetMessageViewProps
|
|||||||
chat: ChatBubbleMessage;
|
chat: ChatBubbleMessage;
|
||||||
makeRoom: (chat: ChatBubbleMessage) => void;
|
makeRoom: (chat: ChatBubbleMessage) => void;
|
||||||
bubbleWidth?: number;
|
bubbleWidth?: number;
|
||||||
|
selectedEmoji?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props => {
|
||||||
{
|
const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL, selectedEmoji } = props;
|
||||||
const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props;
|
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const [ isReady, setIsReady ] = useState<boolean>(false);
|
const [ isReady, setIsReady ] = useState<boolean>(false);
|
||||||
const elementRef = useRef<HTMLDivElement>();
|
const elementRef = useRef<HTMLDivElement>();
|
||||||
@ -76,7 +76,8 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
|||||||
}, [ chat, isReady, isVisible, makeRoom ]);
|
}, [ chat, isReady, isVisible, makeRoom ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ elementRef } className={ `bubble-container ${ isVisible ? 'visible' : 'invisible' }` } onClick={ event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }>
|
<div ref={elementRef} className={`bubble-container newbubblehe ${isVisible ? 'visible' : 'invisible'}`} onClick={event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT)}>
|
||||||
|
{selectedEmoji && <span>{DOMPurify.sanitize(selectedEmoji)}</span>}
|
||||||
{ (chat.styleId === 0) &&
|
{ (chat.styleId === 0) &&
|
||||||
<div className="user-container-bg" style={ { backgroundColor: chat.color } } /> }
|
<div className="user-container-bg" style={ { backgroundColor: chat.color } } /> }
|
||||||
<div className={ `chat-bubble bubble-${ chat.styleId } type-${ chat.type }` } style={ { maxWidth: getBubbleWidth } }>
|
<div className={ `chat-bubble bubble-${ chat.styleId } type-${ chat.type }` } style={ { maxWidth: getBubbleWidth } }>
|
||||||
@ -86,7 +87,7 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
|||||||
</div>
|
</div>
|
||||||
<div className="chat-content">
|
<div className="chat-content">
|
||||||
<b className="username mr-1" dangerouslySetInnerHTML={ { __html: `${ chat.username }: ` } } />
|
<b className="username mr-1" dangerouslySetInnerHTML={ { __html: `${ chat.username }: ` } } />
|
||||||
<span className="message" dangerouslySetInnerHTML={ { __html: `${ chat.formattedText }` } } />
|
<span className="message" style={{ color: chat.chatColours }} dangerouslySetInnerHTML={{ __html: `${chat.formattedText}` }} onClick={e => onClickChat(e)} />
|
||||||
</div>
|
</div>
|
||||||
<div className="pointer" />
|
<div className="pointer" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { CreateLinkEvent, Dispose, DropBounce, EaseOut, GetConfiguration, GetSessionDataManager, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait } from '@nitrots/nitro-renderer';
|
import { CreateLinkEvent, Dispose, DropBounce, EaseOut, GetSessionDataManager, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { MessengerIconState, OpenMessengerChat, VisitDesktop } from '../../api';
|
import { GetConfigurationValue, MessengerIconState, OpenMessengerChat, VisitDesktop } from '../../api';
|
||||||
import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common';
|
import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common';
|
||||||
import { useAchievements, useFriends, useInventoryUnseenTracker, useMessageEvent, useMessenger, useNitroEvent, useSessionInfo } from '../../hooks';
|
import { useAchievements, useFriends, useInventoryUnseenTracker, useMessageEvent, useMessenger, useNitroEvent, useSessionInfo } from '../../hooks';
|
||||||
import { ToolbarMeView } from './ToolbarMeView';
|
import { ToolbarMeView } from './ToolbarMeView';
|
||||||
@ -81,7 +81,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
|||||||
{ !isInRoom &&
|
{ !isInRoom &&
|
||||||
<Base pointer className="navigation-item icon icon-house click-box" onClick={ event => CreateLinkEvent('navigator/goto/home') } /> }
|
<Base pointer className="navigation-item icon icon-house click-box" onClick={ event => CreateLinkEvent('navigator/goto/home') } /> }
|
||||||
<Base pointer className="navigation-item icon icon-rooms click-box" onClick={ event => CreateLinkEvent('navigator/toggle') } />
|
<Base pointer className="navigation-item icon icon-rooms click-box" onClick={ event => CreateLinkEvent('navigator/toggle') } />
|
||||||
{ GetConfiguration('game.center.enabled') && <Base pointer className="navigation-item icon icon-game click-box" onClick={ event => CreateLinkEvent('games/toggle') } /> }
|
{ GetConfigurationValue('game.center.enabled') && <Base pointer className="navigation-item icon icon-game click-box" onClick={ event => CreateLinkEvent('games/toggle') } /> }
|
||||||
<Base pointer className="navigation-item icon icon-catalog click-box" onClick={ event => CreateLinkEvent('catalog/toggle') } />
|
<Base pointer className="navigation-item icon icon-catalog click-box" onClick={ event => CreateLinkEvent('catalog/toggle') } />
|
||||||
<Base pointer className="navigation-item icon icon-inventory click-box" onClick={ event => CreateLinkEvent('inventory/toggle') }>
|
<Base pointer className="navigation-item icon icon-inventory click-box" onClick={ event => CreateLinkEvent('inventory/toggle') }>
|
||||||
{ (getFullCount > 0) &&
|
{ (getFullCount > 0) &&
|
||||||
|
@ -3,6 +3,7 @@ import { useState } from 'react';
|
|||||||
import { useBetween } from 'use-between';
|
import { useBetween } from 'use-between';
|
||||||
import { ChatEntryType, ChatHistoryCurrentDate, IChatEntry, IRoomHistoryEntry, MessengerHistoryCurrentDate } from '../../api';
|
import { ChatEntryType, ChatHistoryCurrentDate, IChatEntry, IRoomHistoryEntry, MessengerHistoryCurrentDate } from '../../api';
|
||||||
import { useMessageEvent, useNitroEvent } from '../events';
|
import { useMessageEvent, useNitroEvent } from '../events';
|
||||||
|
import { useLocalStorage } from '../useLocalStorage';
|
||||||
|
|
||||||
const CHAT_HISTORY_MAX = 1000;
|
const CHAT_HISTORY_MAX = 1000;
|
||||||
const ROOM_HISTORY_MAX = 10;
|
const ROOM_HISTORY_MAX = 10;
|
||||||
@ -13,10 +14,10 @@ let MESSENGER_HISTORY_COUNTER: number = 0;
|
|||||||
|
|
||||||
const useChatHistoryState = () =>
|
const useChatHistoryState = () =>
|
||||||
{
|
{
|
||||||
const [ chatHistory, setChatHistory ] = useState<IChatEntry[]>([]);
|
const [ chatHistory, setChatHistory ] = useLocalStorage<IChatEntry[]>('chatHistory', []);
|
||||||
const [ roomHistory, setRoomHistory ] = useState<IRoomHistoryEntry[]>([]);
|
const [ roomHistory, setRoomHistory ] = useLocalStorage<IRoomHistoryEntry[]>('roomHistory', []);
|
||||||
const [ messengerHistory, setMessengerHistory ] = useState<IChatEntry[]>([]);
|
const [ messengerHistory, setMessengerHistory ] = useLocalStorage<IChatEntry[]>('messengerHistory', []);
|
||||||
const [ needsRoomInsert, setNeedsRoomInsert ] = useState(false);
|
const [ needsRoomInsert, setNeedsRoomInsert ] = useLocalStorage('needsRoomInsert', false);
|
||||||
|
|
||||||
const addChatEntry = (entry: IChatEntry) =>
|
const addChatEntry = (entry: IChatEntry) =>
|
||||||
{
|
{
|
||||||
|
4
src/hooks/events/useRoomSessionManagerEvent.tsx
Normal file
4
src/hooks/events/useRoomSessionManagerEvent.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { GetRoomSessionManager, NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
import { useEventDispatcher } from './useEventDispatcher';
|
||||||
|
|
||||||
|
export const useRoomSessionManagerEvent = <T extends NitroEvent>(type: string | string[], handler: (event: T) => void) => useEventDispatcher(type, GetRoomSessionManager().events, handler);
|
@ -17,7 +17,7 @@ const useChatInputWidgetState = () =>
|
|||||||
const { showNitroAlert = null, showConfirm = null } = useNotification();
|
const { showNitroAlert = null, showConfirm = null } = useNotification();
|
||||||
const { roomSession = null } = useRoom();
|
const { roomSession = null } = useRoom();
|
||||||
|
|
||||||
const sendChat = (text: string, chatType: number, recipientName: string = '', styleId: number = 0) =>
|
const sendChat = (text: string, chatType: number, recipientName: string = '', styleId: number = 0, chatColour: string = '') =>
|
||||||
{
|
{
|
||||||
if(text === '') return null;
|
if(text === '') return null;
|
||||||
|
|
||||||
@ -108,8 +108,17 @@ const useChatInputWidgetState = () =>
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
case ':zoom':
|
case ':zoom':
|
||||||
GetEventDispatcher().dispatchEvent(new RoomZoomEvent(roomSession.roomId, parseFloat(secondPart), false));
|
let requestedZoomLevel = parseFloat(secondPart);
|
||||||
|
if (isNaN(requestedZoomLevel)) {
|
||||||
|
requestedZoomLevel = 1;
|
||||||
|
}
|
||||||
|
if (requestedZoomLevel >= 1 && requestedZoomLevel <= 5) {
|
||||||
|
GetRoomEngine().events.dispatchEvent(new RoomZoomEvent(roomSession.roomId, requestedZoomLevel, false));
|
||||||
|
} else if (requestedZoomLevel === 0) {
|
||||||
|
GetRoomEngine().events.dispatchEvent(new RoomZoomEvent(roomSession.roomId, 1, false));
|
||||||
|
} else {
|
||||||
|
GetRoomEngine().events.dispatchEvent(new RoomZoomEvent(roomSession.roomId, 1, false));
|
||||||
|
};
|
||||||
return null;
|
return null;
|
||||||
case ':screenshot':
|
case ':screenshot':
|
||||||
const texture = GetRoomEngine().createTextureFromRoom(roomSession.roomId, 1);
|
const texture = GetRoomEngine().createTextureFromRoom(roomSession.roomId, 1);
|
||||||
@ -131,7 +140,7 @@ const useChatInputWidgetState = () =>
|
|||||||
{
|
{
|
||||||
GetSessionDataManager().sendSpecialCommandMessage(':pickall');
|
GetSessionDataManager().sendSpecialCommandMessage(':pickall');
|
||||||
},
|
},
|
||||||
null, null, null, LocalizeText('generic.alert.title'));
|
null, null, null, LocalizeText('generic.alert.title'), null, 'pickall');
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -180,10 +189,10 @@ const useChatInputWidgetState = () =>
|
|||||||
switch(chatType)
|
switch(chatType)
|
||||||
{
|
{
|
||||||
case ChatMessageTypeEnum.CHAT_DEFAULT:
|
case ChatMessageTypeEnum.CHAT_DEFAULT:
|
||||||
roomSession.sendChatMessage(text, styleId);
|
roomSession.sendChatMessage(text, styleId, chatColour);
|
||||||
break;
|
break;
|
||||||
case ChatMessageTypeEnum.CHAT_SHOUT:
|
case ChatMessageTypeEnum.CHAT_SHOUT:
|
||||||
roomSession.sendShoutMessage(text, styleId);
|
roomSession.sendChatMessage(text, styleId, chatColour);
|
||||||
break;
|
break;
|
||||||
case ChatMessageTypeEnum.CHAT_WHISPER:
|
case ChatMessageTypeEnum.CHAT_WHISPER:
|
||||||
roomSession.sendWhisperMessage(recipientName, text, styleId);
|
roomSession.sendWhisperMessage(recipientName, text, styleId);
|
||||||
@ -216,7 +225,7 @@ const useChatInputWidgetState = () =>
|
|||||||
|
|
||||||
let seconds = 0;
|
let seconds = 0;
|
||||||
|
|
||||||
const interval = setInterval(() =>
|
const interval = window.setInterval(() =>
|
||||||
{
|
{
|
||||||
setFloodBlockedSeconds(prevValue =>
|
setFloodBlockedSeconds(prevValue =>
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,7 @@ const useChatWidgetState = () =>
|
|||||||
let userType = 0;
|
let userType = 0;
|
||||||
let petType = -1;
|
let petType = -1;
|
||||||
let text = event.message;
|
let text = event.message;
|
||||||
|
let chatColours = event._chatColours
|
||||||
|
|
||||||
if(userData)
|
if(userData)
|
||||||
{
|
{
|
||||||
@ -60,6 +61,7 @@ const useChatWidgetState = () =>
|
|||||||
case RoomObjectType.PET:
|
case RoomObjectType.PET:
|
||||||
imageUrl = await ChatBubbleUtilities.getPetImage(figure, 2, true, 64, roomObject.model.getValue<string>(RoomObjectVariable.FIGURE_POSTURE));
|
imageUrl = await ChatBubbleUtilities.getPetImage(figure, 2, true, 64, roomObject.model.getValue<string>(RoomObjectVariable.FIGURE_POSTURE));
|
||||||
petType = new PetFigureData(figure).typeId;
|
petType = new PetFigureData(figure).typeId;
|
||||||
|
chatColours = "black"
|
||||||
break;
|
break;
|
||||||
case RoomObjectType.USER:
|
case RoomObjectType.USER:
|
||||||
imageUrl = await ChatBubbleUtilities.getUserImage(figure);
|
imageUrl = await ChatBubbleUtilities.getUserImage(figure);
|
||||||
@ -67,6 +69,7 @@ const useChatWidgetState = () =>
|
|||||||
case RoomObjectType.RENTABLE_BOT:
|
case RoomObjectType.RENTABLE_BOT:
|
||||||
case RoomObjectType.BOT:
|
case RoomObjectType.BOT:
|
||||||
styleId = SystemChatStyleEnum.BOT;
|
styleId = SystemChatStyleEnum.BOT;
|
||||||
|
chatColours = "black"
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,10 +147,11 @@ const useChatWidgetState = () =>
|
|||||||
chatType,
|
chatType,
|
||||||
styleId,
|
styleId,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
color);
|
color,
|
||||||
|
chatColours);
|
||||||
|
|
||||||
setChatMessages(prevValue => [ ...prevValue, chatMessage ]);
|
setChatMessages(prevValue => [ ...prevValue, chatMessage ]);
|
||||||
addChatEntry({ id: -1, webId: userData.webID, entityId: userData.roomIndex, name: username, imageUrl, style: styleId, chatType: chatType, entityType: userData.type, message: formattedText, timestamp: ChatHistoryCurrentDate(), type: ChatEntryType.TYPE_CHAT, roomId: roomSession.roomId, color });
|
addChatEntry({ id: -1, webId: userData.webID, entityId: userData.roomIndex, name: username, imageUrl, style: styleId, chatType: chatType, entityType: userData.type, message: formattedText, timestamp: ChatHistoryCurrentDate(), type: ChatEntryType.TYPE_CHAT, roomId: roomSession.roomId, color, chatColours });
|
||||||
});
|
});
|
||||||
|
|
||||||
useNitroEvent<RoomDragEvent>(RoomDragEvent.ROOM_DRAG, event =>
|
useNitroEvent<RoomDragEvent>(RoomDragEvent.ROOM_DRAG, event =>
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import { FigureUpdateEvent, GetSessionDataManager, RoomUnitChatStyleComposer, UserInfoDataParser, UserInfoEvent, UserSettingsEvent } from '@nitrots/nitro-renderer';
|
import { FigureUpdateEvent, GetSessionDataManager, RoomUnitChatStyleComposer, UserInfoDataParser, UserInfoEvent, UserSettingsEvent } from '@nitrots/nitro-renderer';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useBetween } from 'use-between';
|
import { useBetween } from 'use-between';
|
||||||
import { SendMessageComposer } from '../../api';
|
import { GetLocalStorage, SendMessageComposer } from '../../api';
|
||||||
import { useMessageEvent } from '../events';
|
import { useMessageEvent } from '../events';
|
||||||
|
import { useLocalStorage } from '../useLocalStorage';
|
||||||
|
|
||||||
const useSessionInfoState = () =>
|
const useSessionInfoState = () =>
|
||||||
{
|
{
|
||||||
const [ userInfo, setUserInfo ] = useState<UserInfoDataParser>(null);
|
const [ userInfo, setUserInfo ] = useState<UserInfoDataParser>(null);
|
||||||
const [ userFigure, setUserFigure ] = useState<string>(null);
|
const [ userFigure, setUserFigure ] = useState<string>(null);
|
||||||
const [ chatStyleId, setChatStyleId ] = useState<number>(0);
|
const [ chatStyleId, setChatStyleId ] = useLocalStorage<number>(0);
|
||||||
|
const [ chatColour, setChatColour ] = useLocalStorage<string>('chatColour', '');
|
||||||
const [ userRespectRemaining, setUserRespectRemaining ] = useState<number>(0);
|
const [ userRespectRemaining, setUserRespectRemaining ] = useState<number>(0);
|
||||||
const [ petRespectRemaining, setPetRespectRemaining ] = useState<number>(0);
|
const [ petRespectRemaining, setPetRespectRemaining ] = useState<number>(0);
|
||||||
|
|
||||||
@ -19,6 +21,11 @@ const useSessionInfoState = () =>
|
|||||||
SendMessageComposer(new RoomUnitChatStyleComposer(styleId));
|
SendMessageComposer(new RoomUnitChatStyleComposer(styleId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateChatColour = (colour: string) =>
|
||||||
|
{
|
||||||
|
setChatColour(colour);
|
||||||
|
}
|
||||||
|
|
||||||
const respectUser = (userId: number) =>
|
const respectUser = (userId: number) =>
|
||||||
{
|
{
|
||||||
GetSessionDataManager().giveRespect(userId);
|
GetSessionDataManager().giveRespect(userId);
|
||||||
@ -57,7 +64,7 @@ const useSessionInfoState = () =>
|
|||||||
setChatStyleId(parser.chatType);
|
setChatStyleId(parser.chatType);
|
||||||
});
|
});
|
||||||
|
|
||||||
return { userInfo, userFigure, chatStyleId, userRespectRemaining, petRespectRemaining, respectUser, respectPet, updateChatStyleId };
|
return { userInfo, userFigure, chatStyleId, userRespectRemaining, petRespectRemaining, respectUser, respectPet, updateChatStyleId, updateChatColour, chatColour };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSessionInfo = () => useBetween(useSessionInfoState);
|
export const useSessionInfo = () => useBetween(useSessionInfoState);
|
@ -2,16 +2,17 @@ import { NitroLogger } from '@nitrots/nitro-renderer';
|
|||||||
import { Dispatch, SetStateAction, useState } from 'react';
|
import { Dispatch, SetStateAction, useState } from 'react';
|
||||||
import { GetLocalStorage, SetLocalStorage } from '../api';
|
import { GetLocalStorage, SetLocalStorage } from '../api';
|
||||||
|
|
||||||
|
const userId = new URLSearchParams(window.location.search).get('userid') || 0;
|
||||||
|
|
||||||
const useLocalStorageState = <T>(key: string, initialValue: T): [ T, Dispatch<SetStateAction<T>>] =>
|
const useLocalStorageState = <T>(key: string, initialValue: T): [ T, Dispatch<SetStateAction<T>>] =>
|
||||||
{
|
{
|
||||||
|
key = userId ? `${ key }.${ userId }` : key;
|
||||||
|
|
||||||
const [ storedValue, setStoredValue ] = useState<T>(() =>
|
const [ storedValue, setStoredValue ] = useState<T>(() =>
|
||||||
{
|
{
|
||||||
if(typeof window === 'undefined') return initialValue;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const item = GetLocalStorage<T>(key);
|
const item = typeof window !== 'undefined' ? GetLocalStorage<T>(key) as T : undefined;
|
||||||
|
|
||||||
return item ?? initialValue;
|
return item ?? initialValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user