diff --git a/archive/react-helper-partial.ts b/archive/react-helper-partial.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/client/webapp/elements/lists/components/message-element.tsx b/src/client/webapp/elements/lists/components/message-element.tsx index 8d8c037..6d36225 100644 --- a/src/client/webapp/elements/lists/components/message-element.tsx +++ b/src/client/webapp/elements/lists/components/message-element.tsx @@ -48,17 +48,16 @@ interface PreviewImageElementProps { resourcePreviewId: string; resourceId: string; resourceName: string; - resourceIdGuild: CombinedGuild; // TODO: Remove in favor of just one guild } const PreviewImageElement: FC = (props: PreviewImageElementProps) => { - const { guild, previewWidth, previewHeight, resourcePreviewId, resourceId, resourceName, resourceIdGuild } = props; + const { guild, previewWidth, previewHeight, resourcePreviewId, resourceId, resourceName } = props; const setOverlay = useSetRecoilState(overlayState); // TODO: Handle resourceError - const previewResource = useRecoilValue(guildResourceState({ guildId: resourceIdGuild.id, resourceId: resourcePreviewId })); - const previewImgSrc = useRecoilValueSoftImgSrc(guildResourceSoftImgSrcState({ guildId: resourceIdGuild.id, resourceId: resourcePreviewId })); + const previewResource = useRecoilValue(guildResourceState({ guildId: guild.id, resourceId: resourcePreviewId })); + const previewImgSrc = useRecoilValueSoftImgSrc(guildResourceSoftImgSrcState({ guildId: guild.id, resourceId: resourcePreviewId })); const [ contextMenu, onContextMenu ] = useContextClickContextMenu((_alignment: IAlignment, relativeToPos: { x: number, y: number }, close: () => void) => { if (!isLoaded(previewResource)) return null; @@ -71,7 +70,7 @@ const PreviewImageElement: FC = (props: PreviewImageEl }, [ previewResource, resourceName ]); const openImageOverlay = useCallback(() => { - setOverlay(); + setOverlay(); }, [ guild, resourceId, resourceName ]); return ( @@ -89,11 +88,10 @@ export interface MessageElementProps { guild: CombinedGuild; message: Message; prevMessage: Message | null; - messageGuild: CombinedGuild; } const MessageElement: FC = (props: MessageElementProps) => { - const { guild, message, prevMessage, messageGuild } = props; + const { guild, message, prevMessage } = props; const className = useMemo(() => { return message.isContinued(prevMessage) ? 'message-react continued' : 'message-react'; @@ -147,7 +145,6 @@ const MessageElement: FC = (props: MessageElementProps) => previewWidth={message.previewWidth} previewHeight={message.previewHeight} resourcePreviewId={message.resourcePreviewId} resourceId={message.resourceId} - resourceIdGuild={messageGuild} resourceName={message.resourceName ?? 'unknown.unk'} /> ); diff --git a/src/client/webapp/elements/lists/message-list.tsx b/src/client/webapp/elements/lists/message-list.tsx index 2fdb7c3..6a26309 100644 --- a/src/client/webapp/elements/lists/message-list.tsx +++ b/src/client/webapp/elements/lists/message-list.tsx @@ -3,94 +3,56 @@ const electronConsole = electronRemote.getGlobal('console') as Console; import Logger from '../../../../logger/logger'; const LOG = Logger.create(__filename, electronConsole); -import React, { Dispatch, FC, SetStateAction, useCallback, useEffect, useMemo, useRef } from 'react'; -import { Channel, Message } from '../../data-types'; -import CombinedGuild from '../../guild-combined'; +import React, { FC, useEffect, useMemo } from 'react'; +import { Message } from '../../data-types'; import MessageElement from './components/message-element'; -import InfiniteScroll from '../components/infinite-scroll'; -import { useMessagesScrollingSubscription } from '../require/guild-subscriptions'; -import { currGuildActiveChannelMessagesState } from '../require/atoms'; +import { currGuildActiveChannelMessagesState, currGuildState } from '../require/atoms'; import { useRecoilValue } from 'recoil'; import { isFailed, isLoaded, isPended, isUnload } from '../require/loadables'; +import InfiniteScrollRecoil from '../components/infinite-scroll-recoil'; -interface MessageListProps { - guild: CombinedGuild; - channel: Channel; - channelGuild: CombinedGuild; - setFetchRetryCallable: Dispatch Promise) | null>>; -} +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 MessageList: FC = (props: MessageListProps) => { - const { guild, channel, channelGuild, setFetchRetryCallable } = props; - - const infiniteScrollElementRef = useRef(null); - - 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 recoilMessages = useRecoilValue(currGuildActiveChannelMessagesState); + const guild = useRecoilValue(currGuildState); + const messages = useRecoilValue(currGuildActiveChannelMessagesState); useEffect(() => { - if (isUnload(recoilMessages)) { + if (isUnload(messages)) { LOG.debug('recoilMessages unloaded'); - } else if (isPended(recoilMessages)) { + } else if (isPended(messages)) { LOG.debug('recoilMessages pended'); - } else if (isLoaded(recoilMessages)) { - LOG.debug('recoilMessages loaded. length: ' + recoilMessages.value.length); - } else if (isFailed(recoilMessages)) { + } else if (isLoaded(messages)) { + LOG.debug('recoilMessages loaded. length: ' + messages.value.length); + } else if (isFailed(messages)) { LOG.debug('recoilMessages failed'); } // LOG.debug('recoilMessages update', { recoilMessagesLength: recoilMessages.value?.length ?? 'unloaded' }); - }, [ recoilMessages ]); - - // TODO: Store state higher up - const [ - fetchRetryCallable, - fetchAboveCallable, - fetchBelowCallable, - setScrollRatio, - messagesResult, - messagesFetchError, - messagesFetchAboveError, - messagesFetchBelowError - ] = useMessagesScrollingSubscription(guild, channel, channelGuild, scrollToBottomFunc); - - useEffect(() => { - // Note: have to use a function here otherwise React trys to "help out" by running the promise - setFetchRetryCallable(() => { return fetchRetryCallable }); - }, [ fetchRetryCallable ]); + }, [ messages ]); const messageElements = useMemo(() => { + if (guild === null) return []; + if (!isLoaded(messages)) return []; const result = []; - if (messagesResult) { - for (let i = 0; i < messagesResult.value.elements.length; ++i) { - const prevMessage = messagesResult.value.elements[i - 1] ?? null; - const message = messagesResult.value.elements[i] as Message; - result.push(); - } + 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(); } return result; - }, [ messagesResult ]); + }, [ messages ]); return (
- {messageElements} + {messageElements}
- ); } diff --git a/src/client/webapp/elements/require/atoms-funcs.ts b/src/client/webapp/elements/require/atoms-funcs.ts index baac234..f56b003f 100644 --- a/src/client/webapp/elements/require/atoms-funcs.ts +++ b/src/client/webapp/elements/require/atoms-funcs.ts @@ -6,7 +6,7 @@ const LOG = Logger.create(__filename, electronConsole); import { AtomEffect, Loadable, RecoilValue, useRecoilValueLoadable } from "recoil"; import CombinedGuild from "../../guild-combined"; import { Conflictable, Connectable } from "../../guild-types"; -import { createFailedScrollingEnd, createFailedValue, createFailedValueScrolling, createLoadedScrollingEnd, createLoadedValue, createLoadedValueScrolling, createLoadingScrollingEnd, Defined, DEF_PENDED_SCROLLING_VALUE, DEF_PENDED_VALUE, DEF_UNLOADED_SCROLL_END, isEndPended, isLoaded, isPended, LoadableScrollingEnd, LoadableValue, LoadableValueScrolling, LoadedScrollingEnd, LoadedValueScrolling } from "./loadables"; +import { createCancelledScrollingEnd, createFailedScrollingEnd, createFailedValue, createFailedValueScrolling, createLoadedScrollingEnd, createLoadedValue, createLoadedValueScrolling, createLoadingScrollingEnd, Defined, DEF_PENDED_SCROLLING_VALUE, DEF_PENDED_VALUE, isEndPended, isLoaded, isPended, LoadableScrollingEnd, LoadableValue, LoadableValueScrolling, LoadedScrollingEnd, LoadedValueScrolling } from "./loadables"; import { guildState } from './atoms'; import { Changes } from '../../data-types'; @@ -109,15 +109,16 @@ export function createFetchValueScrollingReferenceFunc( const selfState = await getPromise(node); if (!isLoaded(selfState)) return; // Don't send a request if the base LoadableValueScrolling isn't loaded yet - const selfEnd = getFunc(selfState); + let selfEnd = getFunc(selfState); if (isEndPended(selfEnd)) return; // Don't send a request if we're already loading canceled = false; - setSelf(applyEndToSelf(selfState, createLoadingScrollingEnd(fetchValueReferenceFunc, cancel))); + selfEnd = createLoadingScrollingEnd(fetchValueReferenceFunc, cancel); + setSelf(applyEndToSelf(selfState, selfEnd)); try { const result = await fetchReferenceFunc(guild, reference, count); if (canceled) { - setSelf(applyEndToSelf(selfState, DEF_UNLOADED_SCROLL_END)); + setSelf(applyEndToSelf(selfState, createCancelledScrollingEnd(selfEnd))); } else { const hasMore = result.length >= count; setSelf(applyResultToSelf(selfState, createLoadedScrollingEnd(hasMore, fetchValueReferenceFunc, cancel), result)); @@ -125,7 +126,7 @@ export function createFetchValueScrollingReferenceFunc( } catch (e: unknown) { if (canceled) { LOG.error('unable to fetch value based on reference (but we were canceled)', e); - setSelf(applyEndToSelf(selfState, DEF_UNLOADED_SCROLL_END)); + setSelf(applyEndToSelf(selfState, createCancelledScrollingEnd(selfEnd))); } else { LOG.error('unable to fetch value based on reference', e); setSelf(applyEndToSelf(selfState, createFailedScrollingEnd(e, fetchValueReferenceFunc, cancel))); diff --git a/src/client/webapp/elements/require/react-helper.tsx b/src/client/webapp/elements/require/react-helper.tsx index c2bf86c..e92309a 100644 --- a/src/client/webapp/elements/require/react-helper.tsx +++ b/src/client/webapp/elements/require/react-helper.tsx @@ -333,12 +333,12 @@ export function useScrollableCallables(scrollable: LoadableValueScrolling { if (loadingAbove) return; - setLoadingAbove(true); if (!isLoaded(scrollable)) return; if (scrollable.above.hasMore !== true) return; // Don't load unless we know there could be more if (scrollable.value.length === 0) return; // There's no references available. In this case, hasMore should already have been false/undefined anyway const topReference = scrollable.value[0] as T; try { + setLoadingAbove(true); await scrollable.above.fetch(topReference); } finally { if (isMounted.current) { @@ -348,12 +348,12 @@ export function useScrollableCallables(scrollable: LoadableValueScrolling { if (loadingBelow) return; - setLoadingBelow(true); if (!isLoaded(scrollable)) return; if (scrollable.below.hasMore !== true) return; // Don't load unless we know there could be more if (scrollable.value.length === 0) return; // There's no references available. In this case, hasMore should already have been false/undefined anyway const bottomReference = scrollable.value[scrollable.value.length - 1] as T; try { + setLoadingBelow(true); await scrollable.below.fetch(bottomReference); } finally { if (isMounted.current) { @@ -378,7 +378,7 @@ export function useScrollableCallables(scrollable: LoadableValueScrolling:] const distToBottom = -scrollTop; - //LOG.debug(`scroll callable update. to top: ${distToTop}, to bottom: ${distToBottom}`) + LOG.debug(`scroll callable update. to top: ${distToTop}, to bottom: ${distToBottom}`) if (distToTop < threshold) { await fetchAboveCallable(); diff --git a/src/client/webapp/elements/sections/guild.tsx b/src/client/webapp/elements/sections/guild.tsx index 8017c49..74ce29b 100644 --- a/src/client/webapp/elements/sections/guild.tsx +++ b/src/client/webapp/elements/sections/guild.tsx @@ -74,7 +74,7 @@ const GuildElement: FC = () => {
- {guild && isLoaded(activeChannel) && } + {guild && isLoaded(activeChannel) && } {guild && isLoaded(activeChannel) && }