mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-26 23:50:52 +01:00
Room chat input updates
This commit is contained in:
parent
6ed7cb6b6f
commit
8f2446186f
@ -1,3 +1,87 @@
|
|||||||
.nitro-chat-input {
|
.nitro-chat-input {
|
||||||
|
position: fixed;
|
||||||
|
display: flex;
|
||||||
|
bottom: 57px;
|
||||||
|
left: 55px;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: $chatinput-zindex;
|
||||||
|
|
||||||
|
.chatinput-container {
|
||||||
|
position: relative;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1.5px solid rgb(0, 0, 0);
|
||||||
|
background: #EDEDED;
|
||||||
|
pointer-events: all;
|
||||||
|
padding-right:30px;
|
||||||
|
width:100%;
|
||||||
|
|
||||||
|
.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;
|
||||||
|
font: inherit;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
bottom:0;
|
||||||
|
margin: auto;
|
||||||
|
left: -5.5px;
|
||||||
|
height: 9px;
|
||||||
|
width: 9px;
|
||||||
|
background: #EDEDED;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
border-left: 1.5px solid $black;
|
||||||
|
border-bottom: 1.5px solid $black;
|
||||||
|
}
|
||||||
|
|
||||||
|
&: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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,146 @@
|
|||||||
import { FC } from 'react';
|
import { createRef, FC, MouseEvent, useCallback, useEffect, useState } from 'react';
|
||||||
|
import { SendChatTypingMessage } from '../../../../api/nitro/session/SendChatTypingMessage';
|
||||||
import { LocalizeText } from '../../../../utils/LocalizeText';
|
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||||
import { ChatInputViewProps } from './ChatInputView.types';
|
import { ChatInputViewProps } from './ChatInputView.types';
|
||||||
|
|
||||||
|
// const chatModeIdShout = LocalizeText('widgets.chatinput.mode.shout');
|
||||||
|
// const chatModeIdSpeak = LocalizeText('widgets.chatinput.mode.speak');
|
||||||
|
// const maxChatLength = GetConfiguration<number>('chat.input.maxlength', 100);
|
||||||
|
|
||||||
|
let lastContent = '';
|
||||||
|
|
||||||
export const ChatInputView: FC<ChatInputViewProps> = props =>
|
export const ChatInputView: FC<ChatInputViewProps> = props =>
|
||||||
{
|
{
|
||||||
|
const [ chatValue, setChatValue ] = useState<string>('');
|
||||||
|
const [ selectedUsername, setSelectedUsername ] = useState('');
|
||||||
|
const [ isTyping, setIsTyping ] = useState(false);
|
||||||
|
|
||||||
|
const inputRef = createRef<HTMLInputElement>();
|
||||||
|
|
||||||
|
const anotherInputHasFocus = useCallback(() =>
|
||||||
|
{
|
||||||
|
const activeElement = document.activeElement;
|
||||||
|
|
||||||
|
if(!activeElement) return false;
|
||||||
|
|
||||||
|
if(inputRef && (inputRef.current === activeElement)) return false;
|
||||||
|
|
||||||
|
if(!(activeElement instanceof HTMLInputElement) && !(activeElement instanceof HTMLTextAreaElement)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}, [ inputRef ]);
|
||||||
|
|
||||||
|
const setInputFocus = useCallback(() =>
|
||||||
|
{
|
||||||
|
inputRef.current.focus();
|
||||||
|
|
||||||
|
inputRef.current.setSelectionRange((inputRef.current.value.length * 2), (inputRef.current.value.length * 2));
|
||||||
|
}, [ inputRef ]);
|
||||||
|
|
||||||
|
const checkSpecialKeywordForInput = useCallback(() =>
|
||||||
|
{
|
||||||
|
setChatValue(prevValue =>
|
||||||
|
{
|
||||||
|
if((prevValue !== LocalizeText('widgets.chatinput.mode.whisper')) || !selectedUsername.length) return prevValue;
|
||||||
|
|
||||||
|
return (`${ prevValue } ${ selectedUsername }`);
|
||||||
|
});
|
||||||
|
}, [ selectedUsername ]);
|
||||||
|
|
||||||
|
const sendChatValue = useCallback((shiftKey: boolean = false) =>
|
||||||
|
{
|
||||||
|
if(!chatValue || (chatValue === '')) return;
|
||||||
|
}, [ chatValue ]);
|
||||||
|
|
||||||
|
const onKeyDownEvent = useCallback((event: KeyboardEvent) =>
|
||||||
|
{
|
||||||
|
if(!inputRef.current) return;
|
||||||
|
|
||||||
|
if(anotherInputHasFocus()) return;
|
||||||
|
|
||||||
|
if(document.activeElement !== inputRef.current) setInputFocus();
|
||||||
|
|
||||||
|
switch(event.key)
|
||||||
|
{
|
||||||
|
case 'Space':
|
||||||
|
checkSpecialKeywordForInput();
|
||||||
|
return;
|
||||||
|
case 'Enter':
|
||||||
|
sendChatValue(event.shiftKey);
|
||||||
|
return;
|
||||||
|
case 'Backspace':
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [ inputRef, anotherInputHasFocus, setInputFocus, checkSpecialKeywordForInput, sendChatValue ]);
|
||||||
|
|
||||||
|
const onInputMouseDownEvent = useCallback((event: MouseEvent<HTMLInputElement>) =>
|
||||||
|
{
|
||||||
|
setInputFocus();
|
||||||
|
}, [ setInputFocus ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
document.body.addEventListener('keydown', onKeyDownEvent);
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
document.body.removeEventListener('keydown', onKeyDownEvent);
|
||||||
|
}
|
||||||
|
}, [ onKeyDownEvent ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
let idleTimer: ReturnType<typeof setTimeout> = 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 (
|
return (
|
||||||
<div className="nitro-chat-input fixed-bottom mb-4 d-flex justify-content-center">
|
<div className="nitro-chat-input">
|
||||||
<div className="nitro-chat-form-input">
|
<div className="chatinput-container">
|
||||||
<input type="text" className="form-control" placeholder={ LocalizeText('widgets.chatinput.default') } />
|
<div className="input-sizer">
|
||||||
|
<input ref={ inputRef } type="text" className="chat-input" placeholder={ LocalizeText('widgets.chatinput.default') } value={ chatValue } onChange={ event => { event.target.parentElement.dataset.value = event.target.value; setChatValue(event.target.value) } } onMouseDown={ onInputMouseDownEvent } />
|
||||||
|
{/* <input #chatInputView type="text" class="chat-input" placeholder="{{ 'widgets.chatinput.default' | translate }}" (input)="chatInputView.parentElement.dataset.value = chatInputView.value" [disabled]="floodBlocked" [maxLength]="inputMaxLength" /> */}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user