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
*/
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)
&& (
<img
alt=""
title={country}
src={`${window.assetserver}/cf/${country}.gif`}
onError={(e) => {
e.target.onerror = null;
e.target.src = './cf/xx.gif';
}}
/>
)
}
{
(!isInfo)
&& (
<span
className="chatname"
style={{
color: colorFromText(name),
}}
>
&nbsp;
{name}
<span>
<img
alt=""
title={country}
src={`${window.assetserver}/cf/${country}.gif`}
onError={(e) => {
e.target.onerror = null;
e.target.src = './cf/xx.gif';
}}
/>
<span
className="chatname"
style={{
color: colorFromText(name),
}}
>
&nbsp;
{name}
</span>
:&nbsp;
</span>
)
@ -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 (
<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) => (
<ChatMessage

View File

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

View File

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

View File

@ -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([

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