From 2b3470ce3631997b8ac5b5555538ea42fefd343a Mon Sep 17 00:00:00 2001 From: Michael Peters Date: Sat, 12 Feb 2022 15:47:30 -0600 Subject: [PATCH] fix fetch above not actually loading stuff on retry --- .../webapp/elements/require/elements-util.tsx | 3 +- .../webapp/elements/require/loadables.ts | 74 +++++++++++++++---- .../webapp/elements/require/react-helper.tsx | 12 +-- src/client/webapp/guild-combined.ts | 2 +- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/client/webapp/elements/require/elements-util.tsx b/src/client/webapp/elements/require/elements-util.tsx index 3f21c6d..d84a9cd 100644 --- a/src/client/webapp/elements/require/elements-util.tsx +++ b/src/client/webapp/elements/require/elements-util.tsx @@ -91,7 +91,7 @@ export default class ElementsUtil { } } - // avoid this function. Use useSoftImgSrcResourceSubscription instead + // avoid this function. Use useSoftImgSrcResourceSubscription instead (or even better, recoil!) static async getImageSrcFromResourceFailSoftly(guild: CombinedGuild, resourceId: string | null): Promise { if (resourceId === null) { return './img/loading.svg'; @@ -102,7 +102,6 @@ export default class ElementsUtil { return src; } catch (e) { LOG.warn('unable to fetch and convert guild resource, showing error instead', e); - //xLOG.warn('unable to fetch and convert guild resource, showing error instead', e); return './img/error.png'; } } diff --git a/src/client/webapp/elements/require/loadables.ts b/src/client/webapp/elements/require/loadables.ts index 7fa2572..cb4394e 100644 --- a/src/client/webapp/elements/require/loadables.ts +++ b/src/client/webapp/elements/require/loadables.ts @@ -31,8 +31,20 @@ export type FailedValue = { export type LoadableValue = UnloadedValue | LoadingValue | LoadedValue | FailedValue; export type QueriedValue = LoadingValue | LoadedValue | FailedValue; -export const DEF_UNLOADED_VALUE: UnloadedValue = { value: undefined, error: undefined, retry: undefined, hasError: undefined, loading: false }; -export const DEF_PENDED_VALUE: LoadingValue = { value: undefined, error: undefined, retry: undefined, hasError: undefined, loading: true }; +export const DEF_UNLOADED_VALUE: UnloadedValue = { + value: undefined, + error: undefined, + retry: undefined, + hasError: undefined, + loading: false, +}; +export const DEF_PENDED_VALUE: LoadingValue = { + value: undefined, + error: undefined, + retry: undefined, + hasError: undefined, + loading: true, +}; export function createLoadedValue(value: Defined, retry: () => Promise): LoadedValue { return { value, @@ -90,18 +102,25 @@ export interface LoadedScrollingEnd { loading: false; } export interface FailedScrollingEnd { - hasMore: undefined | boolean; + hasMore: undefined; hasError: true; error: unknown; fetch: (reference: T) => Promise; cancel: () => void; loading: false; } -export type LoadableScrollingEnd = CanceledScrollingEnd | LoadingScrollingEnd | LoadedScrollingEnd | FailedScrollingEnd; +export type LoadableScrollingEnd = + | CanceledScrollingEnd + | LoadingScrollingEnd + | LoadedScrollingEnd + | FailedScrollingEnd; export function createCancelledScrollingEnd(loadingScrollingEnd: LoadingScrollingEnd): CanceledScrollingEnd { return { ...loadingScrollingEnd, loading: false }; } -export function createLoadingScrollingEnd(fetch: (reference: T) => Promise, cancel: () => void): LoadingScrollingEnd { +export function createLoadingScrollingEnd( + fetch: (reference: T) => Promise, + cancel: () => void, +): LoadingScrollingEnd { return { hasMore: undefined, hasError: undefined, @@ -111,7 +130,11 @@ export function createLoadingScrollingEnd(fetch: (reference: T) => Promise(hasMore: boolean, fetch: (reference: T) => Promise, cancel: () => void): LoadedScrollingEnd { +export function createLoadedScrollingEnd( + hasMore: boolean, + fetch: (reference: T) => Promise, + cancel: () => void, +): LoadedScrollingEnd { return { hasMore, hasError: false, @@ -121,7 +144,11 @@ export function createLoadedScrollingEnd(hasMore: boolean, fetch: (reference: loading: false, }; } -export function createFailedScrollingEnd(error: unknown, fetch: (reference: T) => Promise, cancel: () => void): FailedScrollingEnd { +export function createFailedScrollingEnd( + error: unknown, + fetch: (reference: T) => Promise, + cancel: () => void, +): FailedScrollingEnd { return { hasMore: undefined, hasError: true, @@ -131,10 +158,14 @@ export function createFailedScrollingEnd(error: unknown, fetch: (reference: T loading: false, }; } -export function isEndPended(loadableScrollingEnd: LoadableScrollingEnd): loadableScrollingEnd is LoadingScrollingEnd { +export function isEndPended( + loadableScrollingEnd: LoadableScrollingEnd, +): loadableScrollingEnd is LoadingScrollingEnd { return loadableScrollingEnd.loading === true; } -export function isEndFailed(loadableScrollingEnd: LoadableScrollingEnd): loadableScrollingEnd is FailedScrollingEnd { +export function isEndFailed( + loadableScrollingEnd: LoadableScrollingEnd, +): loadableScrollingEnd is FailedScrollingEnd { return loadableScrollingEnd.hasError === true; } @@ -154,10 +185,27 @@ export type FailedValueScrolling = FailedValue & { above: undefined; below: undefined; }; -export type LoadableValueScrolling = UnloadedValueScrolling | LoadingValueScrolling | LoadedValueScrolling | FailedValueScrolling; -export const DEF_UNLOADED_SCROLLING_VALUE: UnloadedValueScrolling = { ...DEF_UNLOADED_VALUE, above: undefined, below: undefined }; -export const DEF_PENDED_SCROLLING_VALUE: LoadingValueScrolling = { ...DEF_PENDED_VALUE, above: undefined, below: undefined }; -export function createLoadedValueScrolling(value: Defined, retry: () => Promise, above: LoadableScrollingEnd, below: LoadableScrollingEnd): LoadedValueScrolling { +export type LoadableValueScrolling = + | UnloadedValueScrolling + | LoadingValueScrolling + | LoadedValueScrolling + | FailedValueScrolling; +export const DEF_UNLOADED_SCROLLING_VALUE: UnloadedValueScrolling = { + ...DEF_UNLOADED_VALUE, + above: undefined, + below: undefined, +}; +export const DEF_PENDED_SCROLLING_VALUE: LoadingValueScrolling = { + ...DEF_PENDED_VALUE, + above: undefined, + below: undefined, +}; +export function createLoadedValueScrolling( + value: Defined, + retry: () => Promise, + above: LoadableScrollingEnd, + below: LoadableScrollingEnd, +): LoadedValueScrolling { return { ...createLoadedValue(value, retry), above, below }; } export function createFailedValueScrolling(error: unknown, retry: () => Promise): FailedValueScrolling { diff --git a/src/client/webapp/elements/require/react-helper.tsx b/src/client/webapp/elements/require/react-helper.tsx index fdfab80..ffeb26e 100644 --- a/src/client/webapp/elements/require/react-helper.tsx +++ b/src/client/webapp/elements/require/react-helper.tsx @@ -26,7 +26,7 @@ import electron from 'electron'; import ElementsUtil, { IAlignment } from './elements-util'; import React from 'react'; import FileDropTarget from '../components/file-drop-target'; -import { isLoaded, LoadableValueScrolling } from './loadables'; +import { isEndFailed, isLoaded, LoadableValueScrolling } from './loadables'; /** returns a ref that is true if the component is mounted and false otherwise. Very useful for async stuff */ export function useIsMountedRef() { @@ -298,7 +298,7 @@ export function useScrollableCallables( const fetchAboveCallable = useCallback(async () => { if (loadingAbove) return; if (!isLoaded(scrollable)) return; - if (scrollable.above.hasMore !== true) return; // don't load unless we know there could be more + if (!isEndFailed(scrollable.above) && 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 { @@ -313,7 +313,7 @@ export function useScrollableCallables( const fetchBelowCallable = useCallback(async () => { if (loadingBelow) return; if (!isLoaded(scrollable)) return; - if (scrollable.below.hasMore !== true) return; // don't load unless we know there could be more + if (!isEndFailed(scrollable.below) && 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 { @@ -345,15 +345,15 @@ export function useScrollableCallables( //lOG.debug(`scroll callable update. to top: ${distToTop}, to bottom: ${distToBottom}`) - if (distToTop < threshold) { + if (distToTop < threshold && isLoaded(scrollable) && !isEndFailed(scrollable.above)) { await fetchAboveCallable(); } - if (distToBottom < threshold) { + if (distToBottom < threshold && isLoaded(scrollable) && !isEndFailed(scrollable.below)) { await fetchBelowCallable(); } }, - [fetchAboveCallable, fetchBelowCallable, threshold], + [scrollable, fetchAboveCallable, fetchBelowCallable, threshold], ); return { fetchAboveCallable, fetchBelowCallable, onScrollCallable }; diff --git a/src/client/webapp/guild-combined.ts b/src/client/webapp/guild-combined.ts index 9375ca0..090145b 100644 --- a/src/client/webapp/guild-combined.ts +++ b/src/client/webapp/guild-combined.ts @@ -376,7 +376,7 @@ export default class CombinedGuild return messages; } async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise { - Util.failSometimes(0.5); // for testing + // xUtil.failSometimes(0.05); // for testing const members = await this.grabRAMMembersMap(); const channels = await this.grabRAMChannelsMap(); const messages = await this.fetchable.fetchMessagesBefore(channelId, messageOrderId, number);