fix text selection in chat

fix auto-scrolling in chat
This commit is contained in:
HF 2020-05-12 09:02:37 +02:00
parent b53ff19876
commit 69552fbf10
5 changed files with 80 additions and 27 deletions

View File

@ -3,18 +3,27 @@
* @flow * @flow
*/ */
import React, { useRef, useLayoutEffect } from 'react'; import React, {
useRef, useLayoutEffect, useState, useEffect,
} from 'react';
import useStayScrolled from 'react-stay-scrolled'; import useStayScrolled from 'react-stay-scrolled';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { MAX_CHAT_MESSAGES } from '../core/constants';
import type { State } from '../reducers'; import type { State } from '../reducers';
import ChatInput from './ChatInput'; import ChatInput from './ChatInput';
import { saveSelection, restoreSelection } from '../utils/storeSelection';
import { colorFromText, splitCoordsInString } from '../core/utils'; import { colorFromText, splitCoordsInString } from '../core/utils';
function ChatMessage({ name, text, country }) { function ChatMessage({ name, text, country }) {
if (!name || !text) {
return null;
}
const msgText = text.trim(); const msgText = text.trim();
let className = 'msg';
const isInfo = (name === 'info'); const isInfo = (name === 'info');
let className = 'msg';
if (isInfo) { if (isInfo) {
className += ' info'; className += ' info';
} else if (text.charAt(0) === '>') { } else if (text.charAt(0) === '>') {
@ -27,28 +36,25 @@ function ChatMessage({ name, text, country }) {
{ {
(!isInfo) (!isInfo)
&& ( && (
<img <span>
alt="" <img
title={country} alt=""
src={`${window.assetserver}/cf/${country}.gif`} title={country}
onError={(e) => { src={`${window.assetserver}/cf/${country}.gif`}
e.target.onerror = null; onError={(e) => {
e.target.src = './cf/xx.gif'; e.target.onerror = null;
}} e.target.src = './cf/xx.gif';
/> }}
) />
} <span
{ className="chatname"
(!isInfo) style={{
&& ( color: colorFromText(name),
<span }}
className="chatname" >
style={{ &nbsp;
color: colorFromText(name), {name}
}} </span>
>
&nbsp;
{name}
:&nbsp; :&nbsp;
</span> </span>
) )
@ -73,6 +79,7 @@ function ChatMessage({ name, text, country }) {
const Chat = ({ chatMessages, chatChannel }) => { const Chat = ({ chatMessages, chatChannel }) => {
const listRef = useRef(); const listRef = useRef();
const [selection, setSelection] = useState(null);
const { stayScrolled } = useStayScrolled(listRef, { const { stayScrolled } = useStayScrolled(listRef, {
initialScroll: Infinity, initialScroll: Infinity,
}); });
@ -81,11 +88,23 @@ const Chat = ({ chatMessages, chatChannel }) => {
useLayoutEffect(() => { useLayoutEffect(() => {
stayScrolled(); stayScrolled();
}, [channelMessages.length]); }, [channelMessages.slice(-1)]);
useEffect(() => {
if (channelMessages.length === MAX_CHAT_MESSAGES) {
restoreSelection(selection);
}
});
return ( return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}> <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<ul className="chatarea" ref={listRef} style={{ flexGrow: 1 }}> <ul
className="chatarea"
ref={listRef}
style={{ flexGrow: 1 }}
onMouseUp={() => { setSelection(saveSelection); }}
role="presentation"
>
{ {
channelMessages.map((message) => ( channelMessages.map((message) => (
<ChatMessage <ChatMessage

View File

@ -91,3 +91,4 @@ export const MONTH = 30 * DAY;
// available Chat Channels // available Chat Channels
export const CHAT_CHANNELS = ['en', 'int']; export const CHAT_CHANNELS = ['en', 'int'];
export const MAX_CHAT_MESSAGES = 100;

View File

@ -44,6 +44,8 @@ async function exportVox(
canvas, canvas,
centerPoint, centerPoint,
) { ) {
// TODO deactivated cause its not finished
// eslint-disable-next-line no-unused-vars
const { size: canvasSize, colors } = canvas; const { size: canvasSize, colors } = canvas;
// round to chunk with its -x and -y corner closest to centerPoint // round to chunk with its -x and -y corner closest to centerPoint
const [xc,, yc] = centerPoint.map((z) => { const [xc,, yc] = centerPoint.map((z) => {
@ -94,6 +96,8 @@ async function exportVox(
// 4 * 256 palette content (rgba * 256 colors) // 4 * 256 palette content (rgba * 256 colors)
const rgbaChunkSize = 4 * 256; const rgbaChunkSize = 4 * 256;
const rgbaChunkLength = 4 + 4 + 4 + rgbaChunkSize; 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]; const rgbaPadding = [256, 256, 256, 256];
// Main Chunk // Main Chunk
// 4 bytes MAIN // 4 bytes MAIN

View File

@ -1,5 +1,7 @@
/* @flow */ /* @flow */
import { MAX_CHAT_MESSAGES } from '../core/constants';
import type { Action } from '../actions/types'; import type { Action } from '../actions/types';
@ -127,7 +129,7 @@ export default function user(
} = action; } = action;
const chatMessages = state.chatMessages.slice(); const chatMessages = state.chatMessages.slice();
let channelMessages = chatMessages[channel]; let channelMessages = chatMessages[channel];
if (channelMessages.length > 50) { if (channelMessages.length > MAX_CHAT_MESSAGES) {
channelMessages = channelMessages.slice(-50); channelMessages = channelMessages.slice(-50);
} }
channelMessages = channelMessages.concat([ channelMessages = channelMessages.concat([

View File

@ -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();
}
}
}