From 69552fbf107fa3843eff5d140319afbf7b85927a Mon Sep 17 00:00:00 2001 From: HF Date: Tue, 12 May 2020 09:02:37 +0200 Subject: [PATCH] fix text selection in chat fix auto-scrolling in chat --- src/components/Chat.jsx | 71 +++++++++++++++++++++++-------------- src/core/constants.js | 1 + src/core/voxExport.js | 4 +++ src/reducers/user.js | 4 ++- src/utils/storeSelection.js | 27 ++++++++++++++ 5 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 src/utils/storeSelection.js diff --git a/src/components/Chat.jsx b/src/components/Chat.jsx index 3224de8..6e0bad1 100644 --- a/src/components/Chat.jsx +++ b/src/components/Chat.jsx @@ -3,18 +3,27 @@ * @flow */ -import React, { useRef, useLayoutEffect } from 'react'; +import React, { + useRef, useLayoutEffect, useState, useEffect, +} from 'react'; import useStayScrolled from 'react-stay-scrolled'; import { connect } from 'react-redux'; +import { MAX_CHAT_MESSAGES } from '../core/constants'; import type { State } from '../reducers'; import ChatInput from './ChatInput'; +import { saveSelection, restoreSelection } from '../utils/storeSelection'; import { colorFromText, splitCoordsInString } from '../core/utils'; + function ChatMessage({ name, text, country }) { + if (!name || !text) { + return null; + } + const msgText = text.trim(); - let className = 'msg'; const isInfo = (name === 'info'); + let className = 'msg'; if (isInfo) { className += ' info'; } else if (text.charAt(0) === '>') { @@ -27,28 +36,25 @@ function ChatMessage({ name, text, country }) { { (!isInfo) && ( - { - e.target.onerror = null; - e.target.src = './cf/xx.gif'; - }} - /> - ) - } - { - (!isInfo) - && ( - -   - {name} + + { + e.target.onerror = null; + e.target.src = './cf/xx.gif'; + }} + /> + +   + {name} + ) @@ -73,6 +79,7 @@ function ChatMessage({ name, text, country }) { const Chat = ({ chatMessages, chatChannel }) => { const listRef = useRef(); + const [selection, setSelection] = useState(null); const { stayScrolled } = useStayScrolled(listRef, { initialScroll: Infinity, }); @@ -81,11 +88,23 @@ const Chat = ({ chatMessages, chatChannel }) => { useLayoutEffect(() => { stayScrolled(); - }, [channelMessages.length]); + }, [channelMessages.slice(-1)]); + + useEffect(() => { + if (channelMessages.length === MAX_CHAT_MESSAGES) { + restoreSelection(selection); + } + }); return (
-
    +
      { setSelection(saveSelection); }} + role="presentation" + > { channelMessages.map((message) => ( { @@ -94,6 +96,8 @@ async function exportVox( // 4 * 256 palette content (rgba * 256 colors) const rgbaChunkSize = 4 * 256; const rgbaChunkLength = 4 + 4 + 4 + rgbaChunkSize; + // TODO deactivated cause its not finished + // eslint-disable-next-line no-unused-vars const rgbaPadding = [256, 256, 256, 256]; // Main Chunk // 4 bytes MAIN diff --git a/src/reducers/user.js b/src/reducers/user.js index d538667..4598161 100644 --- a/src/reducers/user.js +++ b/src/reducers/user.js @@ -1,5 +1,7 @@ /* @flow */ +import { MAX_CHAT_MESSAGES } from '../core/constants'; + import type { Action } from '../actions/types'; @@ -127,7 +129,7 @@ export default function user( } = action; const chatMessages = state.chatMessages.slice(); let channelMessages = chatMessages[channel]; - if (channelMessages.length > 50) { + if (channelMessages.length > MAX_CHAT_MESSAGES) { channelMessages = channelMessages.slice(-50); } channelMessages = channelMessages.concat([ diff --git a/src/utils/storeSelection.js b/src/utils/storeSelection.js new file mode 100644 index 0000000..a9a79cf --- /dev/null +++ b/src/utils/storeSelection.js @@ -0,0 +1,27 @@ +/* + * @flow + */ + +export function saveSelection() { + if (window.getSelection) { + const sel = window.getSelection(); + if (sel.getRangeAt && sel.rangeCount) { + return sel.getRangeAt(0); + } + } else if (document.selection && document.selection.createRange) { + return document.selection.createRange(); + } + return null; +} + +export function restoreSelection(range) { + if (range) { + if (window.getSelection) { + const sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } else if (document.selection && range.select) { + range.select(); + } + } +}