From 33f880f4b1e7402212c556f0fd777b1f54784f73 Mon Sep 17 00:00:00 2001 From: Michael Peters Date: Tue, 8 Feb 2022 22:43:56 -0600 Subject: [PATCH] jump to bottom --- src/.prettierrc.json | 2 +- .../elements/components/infinite-scroll.tsx | 8 ++-- .../webapp/elements/lists/message-list.tsx | 46 +++++++++++++++---- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/.prettierrc.json b/src/.prettierrc.json index 0c476f5..d111229 100644 --- a/src/.prettierrc.json +++ b/src/.prettierrc.json @@ -1,5 +1,5 @@ { - "printWidth": 240, + "printWidth": 120, "tabWidth": 4, "useTabs": true, "semi": true, diff --git a/src/client/webapp/elements/components/infinite-scroll.tsx b/src/client/webapp/elements/components/infinite-scroll.tsx index 5997d3b..3179c73 100644 --- a/src/client/webapp/elements/components/infinite-scroll.tsx +++ b/src/client/webapp/elements/components/infinite-scroll.tsx @@ -1,10 +1,11 @@ -import React, { ReactNode } from 'react'; +import React, { MutableRefObject, ReactNode, RefObject, useCallback, useRef } from 'react'; import { LoadableValueScrolling } from '../require/loadables'; import { useScrollableCallables } from '../require/react-helper'; import Retry from './retry'; export interface InfiniteScrollRecoilProps { + infiniteScrollRef: MutableRefObject; scrollable: LoadableValueScrolling; initialErrorMessage: string; // for if there was a problem loading the initial messages aboveErrorMessage: string; // for if there was a problem loading messages above the list @@ -12,12 +13,13 @@ export interface InfiniteScrollRecoilProps { children: ReactNode; } function InfiniteScrollRecoil(props: InfiniteScrollRecoilProps) { - const { scrollable, initialErrorMessage, aboveErrorMessage, belowErrorMessage, children } = props; + const { infiniteScrollRef, scrollable, initialErrorMessage, aboveErrorMessage, belowErrorMessage, children } = + props; const { fetchAboveCallable, fetchBelowCallable, onScrollCallable } = useScrollableCallables(scrollable, 600); // activate fetch above/below when 600 client px from the top/bottom return ( -
+
{children} diff --git a/src/client/webapp/elements/lists/message-list.tsx b/src/client/webapp/elements/lists/message-list.tsx index 7d2eb15..465e728 100644 --- a/src/client/webapp/elements/lists/message-list.tsx +++ b/src/client/webapp/elements/lists/message-list.tsx @@ -3,22 +3,20 @@ const electronConsole = electronRemote.getGlobal('console') as Console; import Logger from '../../../../logger/logger'; const LOG = Logger.create(__filename, electronConsole); -import React, { FC, useEffect, useMemo } from 'react'; +import React, { FC, useEffect, useMemo, useRef } from 'react'; import { Message } from '../../data-types'; import MessageElement from './components/message-element'; -import { currGuildActiveChannelMessagesState, currGuildState } from '../require/atoms'; +import { currGuildActiveChannelMessagesState, currGuildSelfMemberState, currGuildState } from '../require/atoms'; import { useRecoilValue } from 'recoil'; import { isFailed, isLoaded, isPended, isUnload } from '../require/loadables'; import InfiniteScrollRecoil from '../components/infinite-scroll'; const MessageList: FC = () => { - // const scrollToBottomFunc = useCallback(() => { - // if (!infiniteScrollElementRef.current) return; - // infiniteScrollElementRef.current.scrollTop = 0; // Keep in mind that this is reversed since we are in flex-flow: column-reverse - // }, []); + const infiniteScrollElementRef = useRef(null); const guild = useRecoilValue(currGuildState); const messages = useRecoilValue(currGuildActiveChannelMessagesState); + const selfMember = useRecoilValue(currGuildSelfMemberState); // TODO: Show loading indicators if above/below are pending // TODO: Show nicer retry buttons (and test the retry buttons) @@ -34,9 +32,26 @@ const MessageList: FC = () => { } else if (isFailed(messages)) { LOG.debug('recoilMessages failed'); } - // lOG.debug('recoilMessages update', { recoilMessagesLength: recoilMessages.value?.length ?? 'unloaded' }); }, [messages]); + useEffect(() => { + if (guild === null) return; + const onMessages = (messages: Message[]) => { + if (!infiniteScrollElementRef.current) return; + if (!isLoaded(selfMember)) return; + for (const message of messages) { + if (message.member.id === selfMember.value.id) { + // keep in mind that this is reversed since we are in flex-flow: column-reverse + infiniteScrollElementRef.current.scrollTop = 0; + } + } + }; + guild.on('new-messages', onMessages); + return () => { + guild.off('new-messages', onMessages); + }; + }, [guild, selfMember]); + const messageElements = useMemo(() => { if (guild === null) return []; if (!isLoaded(messages)) return []; @@ -44,14 +59,27 @@ const MessageList: FC = () => { for (let i = 0; i < messages.value.length; ++i) { const prevMessage = messages.value[i - 1] ?? null; const message = messages.value[i] as Message; - result.push(); + result.push( + , + ); } return result; }, [guild, messages]); return (
- + {messageElements}