fix fetch above not actually loading stuff on retry

This commit is contained in:
Michael Peters 2022-02-12 15:47:30 -06:00
parent aa79034d7e
commit 2b3470ce36
4 changed files with 69 additions and 22 deletions

View File

@ -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<string> {
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';
}
}

View File

@ -31,8 +31,20 @@ export type FailedValue = {
export type LoadableValue<T> = UnloadedValue | LoadingValue | LoadedValue<T> | FailedValue;
export type QueriedValue<T> = LoadingValue | LoadedValue<T> | 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<T>(value: Defined<T>, retry: () => Promise<void>): LoadedValue<T> {
return {
value,
@ -90,18 +102,25 @@ export interface LoadedScrollingEnd<T> {
loading: false;
}
export interface FailedScrollingEnd<T> {
hasMore: undefined | boolean;
hasMore: undefined;
hasError: true;
error: unknown;
fetch: (reference: T) => Promise<void>;
cancel: () => void;
loading: false;
}
export type LoadableScrollingEnd<T> = CanceledScrollingEnd<T> | LoadingScrollingEnd<T> | LoadedScrollingEnd<T> | FailedScrollingEnd<T>;
export type LoadableScrollingEnd<T> =
| CanceledScrollingEnd<T>
| LoadingScrollingEnd<T>
| LoadedScrollingEnd<T>
| FailedScrollingEnd<T>;
export function createCancelledScrollingEnd<T>(loadingScrollingEnd: LoadingScrollingEnd<T>): CanceledScrollingEnd<T> {
return { ...loadingScrollingEnd, loading: false };
}
export function createLoadingScrollingEnd<T>(fetch: (reference: T) => Promise<void>, cancel: () => void): LoadingScrollingEnd<T> {
export function createLoadingScrollingEnd<T>(
fetch: (reference: T) => Promise<void>,
cancel: () => void,
): LoadingScrollingEnd<T> {
return {
hasMore: undefined,
hasError: undefined,
@ -111,7 +130,11 @@ export function createLoadingScrollingEnd<T>(fetch: (reference: T) => Promise<vo
loading: true,
};
}
export function createLoadedScrollingEnd<T>(hasMore: boolean, fetch: (reference: T) => Promise<void>, cancel: () => void): LoadedScrollingEnd<T> {
export function createLoadedScrollingEnd<T>(
hasMore: boolean,
fetch: (reference: T) => Promise<void>,
cancel: () => void,
): LoadedScrollingEnd<T> {
return {
hasMore,
hasError: false,
@ -121,7 +144,11 @@ export function createLoadedScrollingEnd<T>(hasMore: boolean, fetch: (reference:
loading: false,
};
}
export function createFailedScrollingEnd<T>(error: unknown, fetch: (reference: T) => Promise<void>, cancel: () => void): FailedScrollingEnd<T> {
export function createFailedScrollingEnd<T>(
error: unknown,
fetch: (reference: T) => Promise<void>,
cancel: () => void,
): FailedScrollingEnd<T> {
return {
hasMore: undefined,
hasError: true,
@ -131,10 +158,14 @@ export function createFailedScrollingEnd<T>(error: unknown, fetch: (reference: T
loading: false,
};
}
export function isEndPended<T>(loadableScrollingEnd: LoadableScrollingEnd<T>): loadableScrollingEnd is LoadingScrollingEnd<T> {
export function isEndPended<T>(
loadableScrollingEnd: LoadableScrollingEnd<T>,
): loadableScrollingEnd is LoadingScrollingEnd<T> {
return loadableScrollingEnd.loading === true;
}
export function isEndFailed<T>(loadableScrollingEnd: LoadableScrollingEnd<T>): loadableScrollingEnd is FailedScrollingEnd<T> {
export function isEndFailed<T>(
loadableScrollingEnd: LoadableScrollingEnd<T>,
): loadableScrollingEnd is FailedScrollingEnd<T> {
return loadableScrollingEnd.hasError === true;
}
@ -154,10 +185,27 @@ export type FailedValueScrolling = FailedValue & {
above: undefined;
below: undefined;
};
export type LoadableValueScrolling<T, E> = UnloadedValueScrolling | LoadingValueScrolling | LoadedValueScrolling<T, E> | 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<T, E>(value: Defined<T>, retry: () => Promise<void>, above: LoadableScrollingEnd<E>, below: LoadableScrollingEnd<E>): LoadedValueScrolling<T, E> {
export type LoadableValueScrolling<T, E> =
| UnloadedValueScrolling
| LoadingValueScrolling
| LoadedValueScrolling<T, E>
| 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<T, E>(
value: Defined<T>,
retry: () => Promise<void>,
above: LoadableScrollingEnd<E>,
below: LoadableScrollingEnd<E>,
): LoadedValueScrolling<T, E> {
return { ...createLoadedValue(value, retry), above, below };
}
export function createFailedValueScrolling(error: unknown, retry: () => Promise<void>): FailedValueScrolling {

View File

@ -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<T>(
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<T>(
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<T>(
//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 };

View File

@ -376,7 +376,7 @@ export default class CombinedGuild
return messages;
}
async fetchMessagesBefore(channelId: string, messageOrderId: string, number: number): Promise<Message[]> {
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);