import { isMobileOrTablet, rand } from '../../common/helper'; import seedrandom from 'seedrandom'; const nameColorPallete = { H: [1, 360], S: [30, 100], L: [50, 100], }; export class Chat { public element = document.createElement('div'); private _history = document.createElement('div'); private _wrapper = document.createElement('div'); private _mobToggle = document.createElement('button'); private _inpBox = document.createElement('div'); private _input = document.createElement('input'); private _visible = true; private _rehide = false; private _keyhandler = true; private _sendFn?: (message: string) => void; get visible() { return this._visible; } initialize() { this.element.classList.add('chat__wrapper'); this._wrapper.classList.add('chat'); this._history.classList.add('chat__history'); this._inpBox.classList.add('chat__input-wrapper'); this._input.classList.add('chat__input'); this._mobToggle.classList.add('chat__toggle'); this._inpBox.append(this._input); this._wrapper.append(this._history, this._inpBox); this.element.append(this._mobToggle, this._wrapper); this._input.setAttribute( 'placeholder', 'Type a message here and press Enter to send...', ); this._input.setAttribute('maxlength', '260'); this._input.addEventListener('keydown', (e) => { e.stopPropagation(); if (e.key === 'Enter') { if (!this._input.value?.trim()) { this._input.blur(); if (this._rehide) { this.hide(); this._rehide = false; } return; } if (this._sendFn) { this._sendFn(this._input.value); } this._input.value = null; if (this._rehide) { this.hide(); this._rehide = false; } } else if (e.key === 'Escape') { this._input.blur(); this._input.value = null; if (this._rehide) { this.hide(); this._rehide = false; } } }); this._input.addEventListener('focus', () => { this.element.classList.add('focused'); }); this._input.addEventListener('blur', () => { this.element.classList.remove('focused'); }); this._mobToggle.addEventListener('click', () => { if (this._visible) { this.hide(); } else { this.focus(); } }); window.addEventListener('keydown', (e) => { if (!this._keyhandler) { return; } if (e.key === 'Enter' && (e.target as HTMLElement).tagName !== 'INPUT') { this.focus(!this.visible); } }); document.body.append(this.element); if (!isMobileOrTablet()) { this.show(); } else { this.hide(); } } public registerSendFunction(fn: (message: string) => void) { this._sendFn = fn; } public show() { this._visible = true; this._wrapper.classList.add('visible'); this._wrapper.classList.remove('invisible'); } public hide() { this._visible = false; this._wrapper.classList.remove('visible'); this._wrapper.classList.add('invisible'); } public focus(rehide = false) { if (!this._visible) { this.show(); } this._input.focus(); this._rehide = rehide; } public addMessage(sender: string, message: string, meta?: any) { const msg = document.createElement('div'); const msgSender = document.createElement('div'); const msgTime = document.createElement('div'); const msgContent = document.createElement('div'); msg.classList.add('chat__message'); msgTime.classList.add('chat__message-timestamp'); msgSender.classList.add('chat__message-sender'); msgContent.classList.add('chat__message-content'); msg.append(msgTime, msgSender, msgContent); const stamp = meta?.time ? new Date(meta.time) : new Date(); // TODO: timestamp utility msgTime.innerText = `${stamp.getHours().toString().padStart(2, '0')}:${stamp .getMinutes() .toString() .padStart(2, '0')}`; msgSender.innerText = sender; msgSender.style.setProperty('--name-color', this.getNameColor(sender)); msgContent.innerText = message; // const bottomed = this._history.scrollTop ,this._history.scrollHeight; this._history.append(msg); this._history.scrollTop = this._history.scrollHeight; setTimeout(() => { msg.classList.add('chat__message--old'); }, 5000); } public getNameColor(name: string) { const randgen = seedrandom(name); const h = rand(randgen, nameColorPallete.H[0], nameColorPallete.H[1]); const s = rand(randgen, nameColorPallete.S[0], nameColorPallete.S[1]); const l = rand(randgen, nameColorPallete.L[0], nameColorPallete.L[1]); return 'hsl(' + h + ',' + s + '%,' + l + '%)'; } public setKeyHandlerEnabled(isEnabled: boolean) { this._keyhandler = isEnabled; } }