jump to bottom
This commit is contained in:
parent
515738ae41
commit
33f880f4b1
@ -1,5 +1,5 @@
|
||||
{
|
||||
"printWidth": 240,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"useTabs": true,
|
||||
"semi": true,
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user