diff --git a/client/src/Board.js b/client/src/Board.js index 87c463c..e7cd736 100755 --- a/client/src/Board.js +++ b/client/src/Board.js @@ -247,18 +247,19 @@ class Resource extends React.Component { }; const Chat = ({ board, promoteGameState }) => { - const [lastHeight, setLastHeight] = useState(0); + const [lastTop, setLastTop] = useState(0), + [autoScroll, setAutoscroll] = useState(true), + [scrollTime, setScrollTime] = useState(0); const chatInput = (event) => { }; const chatKeyPress = (event) => { if (event.key === "Enter") { - console.log(`Send: ${event.target.value} ${lastHeight}`); - const chatList = document.getElementById("ChatList"); - setLastHeight(0); /* Reset sticky scroll */ - chatList.scrollTop = chatList.scrollHeight - chatList.offsetHeight; - + if (!autoScroll) { + setAutoscroll(true); + } + promoteGameState({ chat: { player: board.game.color ? board.game.color : undefined, @@ -269,22 +270,49 @@ const Chat = ({ board, promoteGameState }) => { } }; - const classes = useStyles(); - useEffect(() => { - const chatList = document.getElementById("ChatList"); + const chatScroll = (event) => { + const chatList = event.target, + fromBottom = Math.round(Math.abs((chatList.scrollHeight - chatList.offsetHeight) - chatList.scrollTop)); - const scrolled = Math.abs((lastHeight ? lastHeight : chatList.scrollHeight) - chatList.offsetHeight - chatList.scrollTop); - - if (lastHeight !== Math.round(chatList.scrollHeight)) { - if (lastHeight === 0 || scrolled < 20) { - console.log("Auto scroll", scrolled, chatList.scrollHeight, lastHeight); - chatList.scrollTop = chatList.scrollHeight - chatList.offsetHeight; - setLastHeight(Math.round(chatList.scrollHeight)); - } else { - console.log('Sticking scroll position', scrolled, chatList.scrollHeight, lastHeight); - setLastHeight(Math.round(chatList.scrollHeight)); + /* If scroll is within 20 pixels of the bottom, turn on auto-scroll */ + const shouldAutoscroll = (fromBottom < 20); + + if (shouldAutoscroll !== autoScroll) { + setAutoscroll(shouldAutoscroll); + } + + /* If the list should not auto scroll, then cache the current + * top of the list and record when we did this so we honor + * the auto-scroll for at least 500ms */ + if (!shouldAutoscroll) { + const target = Math.round(chatList.scrollTop); + if (target !== lastTop) { + setLastTop(target); + setScrollTime(Date.now()); } } + }; + + const classes = useStyles(); + + useEffect(() => { + const chatList = document.getElementById("ChatList"), + currentTop = Math.round(chatList.scrollTop); + + if (autoScroll) { + /* Auto-scroll to the bottom of the chat window */ + const target = Math.round(chatList.scrollHeight - chatList.offsetHeight); + if (currentTop !== target) { + chatList.scrollTop = target; + } + return; + } + + /* Maintain current position in scrolled view if the user hasn't + * been scrolling in the past 0.5s */ + if ((Date.now() - scrollTime) > 500 && currentTop !== lastTop) { + chatList.scrollTop = lastTop; + } }); //const timeDelta = game.timestamp - Date.now(); @@ -303,7 +331,7 @@ const Chat = ({ board, promoteGameState }) => { return ( - + { messages } { date: Date.now(), message: changes.chat.message }); +/* if (game.chat.length > 10) { game.chat.splice(0, game.chat.length - 10); } +*/ break; } }