jump to bottom

This commit is contained in:
Michael Peters 2022-02-08 22:43:56 -06:00
parent 515738ae41
commit 33f880f4b1
3 changed files with 43 additions and 13 deletions

View File

@ -1,5 +1,5 @@
{
"printWidth": 240,
"printWidth": 120,
"tabWidth": 4,
"useTabs": true,
"semi": true,

View File

@ -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<T, E> {
infiniteScrollRef: MutableRefObject<HTMLDivElement | null>;
scrollable: LoadableValueScrolling<T, E>;
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<T, E> {
children: ReactNode;
}
function InfiniteScrollRecoil<T>(props: InfiniteScrollRecoilProps<T[], T>) {
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 (
<div className="infinite-scroll-scroll-base" onScroll={onScrollCallable}>
<div ref={infiniteScrollRef} className="infinite-scroll-scroll-base" onScroll={onScrollCallable}>
<div className="infinite-scroll-elements">
<Retry error={scrollable?.above?.error} text={aboveErrorMessage} retryFunc={fetchAboveCallable} />
{children}

View File

@ -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<HTMLDivElement>(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(<MessageElement key={guild.id + 'm#' + message.id} guild={guild} message={message} prevMessage={prevMessage} />);
result.push(
<MessageElement
key={guild.id + 'm#' + message.id}
guild={guild}
message={message}
prevMessage={prevMessage}
/>,
);
}
return result;
}, [guild, messages]);
return (
<div className="message-list">
<InfiniteScrollRecoil scrollable={messages} initialErrorMessage="Unable to retrieve recent messages" aboveErrorMessage="Unable to retrieve messages above" belowErrorMessage="Unable to retrieve messages below">
<InfiniteScrollRecoil
infiniteScrollRef={infiniteScrollElementRef}
scrollable={messages}
initialErrorMessage="Unable to retrieve recent messages"
aboveErrorMessage="Unable to retrieve messages above"
belowErrorMessage="Unable to retrieve messages below"
>
{messageElements}
</InfiniteScrollRecoil>
</div>