mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-27 08:00:51 +01:00
Add chat style selector
This commit is contained in:
parent
a9d4bd1559
commit
823ec8c650
@ -1,13 +1,3 @@
|
|||||||
@media only screen and (max-width: 600px) {
|
|
||||||
.nitro-chat-input {
|
|
||||||
position: fixed;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
bottom: 65px !important;
|
|
||||||
z-index: $chatinput-zindex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nitro-chat-input-container {
|
.nitro-chat-input-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -17,7 +7,7 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 2px solid rgb(0, 0, 0);
|
border: 2px solid rgb(0, 0, 0);
|
||||||
background: #EDEDED;
|
background: #EDEDED;
|
||||||
padding-right: 30px;
|
padding-right: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
@ -60,6 +50,40 @@
|
|||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bubble-container {
|
||||||
|
visibility: visible;
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './style-selector/ChatInputStyleSelectorView';
|
.nitro-chat-style-selector-button {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-chat-style-selector-container {
|
||||||
|
width: $chat-input-style-selector-widget-width;
|
||||||
|
height: $chat-input-style-selector-widget-height;
|
||||||
|
|
||||||
|
.grid-item {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
height: 30px !important;
|
||||||
|
border-color: unset !important;
|
||||||
|
border: 0 !important;
|
||||||
|
padding: 1px 3px;
|
||||||
|
|
||||||
|
&:not(.active) {
|
||||||
|
background-color: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble-container {
|
||||||
|
visibility: visible;
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { 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 { GetConfiguration, GetSessionDataManager, LocalizeText, RoomWidgetChatMessage, RoomWidgetChatTypingMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateInfostandUserEvent } from '../../../../api';
|
import { GetConfiguration, GetSessionDataManager, LocalizeText, RoomWidgetChatMessage, RoomWidgetChatTypingMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateInfostandUserEvent } from '../../../../api';
|
||||||
@ -117,6 +118,7 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
{
|
{
|
||||||
if(needsChatStyleUpdate)
|
if(needsChatStyleUpdate)
|
||||||
{
|
{
|
||||||
|
console.log('send')
|
||||||
GetSessionDataManager().sendChatStyleUpdate(chatStyleId);
|
GetSessionDataManager().sendChatStyleUpdate(chatStyleId);
|
||||||
|
|
||||||
setNeedsChatStyleUpdate(false);
|
setNeedsChatStyleUpdate(false);
|
||||||
@ -175,12 +177,6 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
|
|
||||||
}, [ inputRef, chatModeIdWhisper, anotherInputHasFocus, setInputFocus, checkSpecialKeywordForInput, sendChatValue ]);
|
}, [ inputRef, chatModeIdWhisper, anotherInputHasFocus, setInputFocus, checkSpecialKeywordForInput, sendChatValue ]);
|
||||||
|
|
||||||
const onStyleSelected = useCallback((styleId: number) =>
|
|
||||||
{
|
|
||||||
setChatStyleId(styleId);
|
|
||||||
setNeedsChatStyleUpdate(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
|
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
|
||||||
{
|
{
|
||||||
setSelectedUsername('');
|
setSelectedUsername('');
|
||||||
@ -210,6 +206,61 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
|
|
||||||
CreateEventDispatcherHook(RoomWidgetUpdateChatInputContentEvent.CHAT_INPUT_CONTENT, eventDispatcher, onRoomWidgetChatInputContentUpdateEvent);
|
CreateEventDispatcherHook(RoomWidgetUpdateChatInputContentEvent.CHAT_INPUT_CONTENT, eventDispatcher, onRoomWidgetChatInputContentUpdateEvent);
|
||||||
|
|
||||||
|
const selectChatStyleId = useCallback((styleId: number) =>
|
||||||
|
{
|
||||||
|
setChatStyleId(styleId);
|
||||||
|
setNeedsChatStyleUpdate(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const chatStyleIds = useMemo(() =>
|
||||||
|
{
|
||||||
|
let styleIds: number[] = [];
|
||||||
|
|
||||||
|
const styles = GetConfiguration<{ styleId: number, minRank: number, isSystemStyle: boolean, isHcOnly: boolean, isAmbassadorOnly: boolean }[]>('chat.styles');
|
||||||
|
|
||||||
|
for(const style of styles)
|
||||||
|
{
|
||||||
|
if(!style) continue;
|
||||||
|
|
||||||
|
if(style.minRank > 0)
|
||||||
|
{
|
||||||
|
if(GetSessionDataManager().hasSecurity(style.minRank)) styleIds.push(style.styleId);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(style.isSystemStyle)
|
||||||
|
{
|
||||||
|
if(GetSessionDataManager().hasSecurity(RoomControllerLevel.MODERATOR))
|
||||||
|
{
|
||||||
|
styleIds.push(style.styleId);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GetConfiguration<number[]>('chat.styles.disabled').indexOf(style.styleId) >= 0) continue;
|
||||||
|
|
||||||
|
if(style.isHcOnly && (GetSessionDataManager().clubLevel >= HabboClubLevelEnum.CLUB))
|
||||||
|
{
|
||||||
|
styleIds.push(style.styleId);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(style.isAmbassadorOnly && GetSessionDataManager().isAmbassador)
|
||||||
|
{
|
||||||
|
styleIds.push(style.styleId);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!style.isHcOnly && !style.isAmbassadorOnly) styleIds.push(style.styleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return styleIds;
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
if(isTyping)
|
if(isTyping)
|
||||||
@ -273,7 +324,7 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
<div className="input-sizer">
|
<div className="input-sizer">
|
||||||
<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() } />
|
||||||
</div>
|
</div>
|
||||||
<ChatInputStyleSelectorView onStyleSelected={ onStyleSelected } />
|
<ChatInputStyleSelectorView chatStyleId={ chatStyleId } chatStyleIds={ chatStyleIds } selectChatStyleId={ selectChatStyleId } />
|
||||||
</div>, document.getElementById('toolbar-chat-input-container'))
|
</div>, document.getElementById('toolbar-chat-input-container'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
.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%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,69 @@
|
|||||||
import { FC, useState } from 'react';
|
import { FC, MouseEvent, useCallback, useEffect, useState } from 'react';
|
||||||
|
import { Overlay, Popover } from 'react-bootstrap';
|
||||||
|
import { BatchUpdates } from '../../../../../hooks';
|
||||||
|
import { NitroCardContentView, NitroCardGridItemView, NitroCardGridView } from '../../../../../layout';
|
||||||
import { ChatInputStyleSelectorViewProps } from './ChatInputStyleSelectorView.types';
|
import { ChatInputStyleSelectorViewProps } from './ChatInputStyleSelectorView.types';
|
||||||
|
|
||||||
export const ChatInputStyleSelectorView: FC<ChatInputStyleSelectorViewProps> = props =>
|
export const ChatInputStyleSelectorView: FC<ChatInputStyleSelectorViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { onStyleSelected = null } = props;
|
const { chatStyleId = 0, chatStyleIds = null, selectChatStyleId = null } = props;
|
||||||
|
const [ target, setTarget ] = useState<(EventTarget & HTMLElement)>(null);
|
||||||
const [ selectorVisible, setSelectorVisible ] = useState(false);
|
const [ selectorVisible, setSelectorVisible ] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(selectorVisible) return;
|
||||||
|
|
||||||
|
setTarget(null);
|
||||||
|
}, [ selectorVisible ]);
|
||||||
|
|
||||||
|
const selectStyle = (styleId: number) =>
|
||||||
|
{
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
selectChatStyleId(styleId);
|
||||||
|
setSelectorVisible(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleSelector = useCallback((event: MouseEvent<HTMLElement>) =>
|
||||||
|
{
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
let visible = false;
|
||||||
|
|
||||||
|
setSelectorVisible(prevValue =>
|
||||||
|
{
|
||||||
|
visible = !prevValue;
|
||||||
|
|
||||||
|
return visible;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(visible) setTarget((event.target as (EventTarget & HTMLElement)));
|
||||||
|
})
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="nitro-chat-style-selector-button">
|
<i className="icon chatstyles-icon cursor-pointer" onClick={ toggleSelector } />
|
||||||
<i className="icon chatstyles-icon" />
|
<Overlay show={ selectorVisible } target={ target } placement="top">
|
||||||
|
<Popover className="nitro-chat-style-selector-container" id="chat-style-selector">
|
||||||
|
<NitroCardContentView className="bg-transparent">
|
||||||
|
<NitroCardGridView>
|
||||||
|
{ chatStyleIds && (chatStyleIds.length > 0) && chatStyleIds.map((styleId) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<NitroCardGridItemView key={ styleId } itemActive={ (chatStyleId === styleId) } onClick={ event => selectStyle(styleId) }>
|
||||||
|
<div className="bubble-container">
|
||||||
|
<div className={ 'w-100 chat-bubble bubble-' + styleId }> </div>
|
||||||
</div>
|
</div>
|
||||||
{ selectorVisible &&
|
</NitroCardGridItemView>
|
||||||
<div className="nitro-chat-style-selector-container">
|
);
|
||||||
|
}) }
|
||||||
</div> }
|
</NitroCardGridView>
|
||||||
|
</NitroCardContentView>
|
||||||
|
</Popover>
|
||||||
|
</Overlay>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export interface ChatInputStyleSelectorViewProps
|
export interface ChatInputStyleSelectorViewProps
|
||||||
{
|
{
|
||||||
onStyleSelected: (styleId: number) => void;
|
chatStyleId: number;
|
||||||
|
chatStyleIds: number[];
|
||||||
|
selectChatStyleId: (styleId: number) => void;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
@import './message/ChatWidgetMessageView';
|
@import './message/ChatWidgetMessageView';
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user