MOBILE-4304 core: Improve infinite-loader race conditions

main
Noel De Martin 2024-02-07 14:25:52 +01:00
parent 0c42071511
commit 7adf75f490
2 changed files with 23 additions and 9 deletions

View File

@ -69,17 +69,17 @@ export class CoreInfiniteLoadingComponent implements OnChanges {
return; return;
} }
// Wait until next tick to allow items to render and scroll content to grow. const scrollElement = await this.hostElement.closest('ion-content')?.getScrollElement();
await CoreUtils.nextTick();
// Calculate distance from edge. if (!scrollElement) {
const content = this.hostElement.closest('ion-content');
if (!content) {
return; return;
} }
const scrollElement = await content.getScrollElement(); // Wait to allow items to render and scroll content to grow.
await CoreUtils.nextTick();
await CoreUtils.waitFor(() => scrollElement.scrollHeight > scrollElement.clientHeight, { timeout: 1000 });
// Calculate distance from edge.
const infiniteHeight = this.hostElement.getBoundingClientRect().height; const infiniteHeight = this.hostElement.getBoundingClientRect().height;
const scrollTop = scrollElement.scrollTop; const scrollTop = scrollElement.scrollTop;
const height = scrollElement.offsetHeight; const height = scrollElement.offsetHeight;

View File

@ -1826,23 +1826,29 @@ export class CoreUtilsProvider {
* @param condition Condition. * @param condition Condition.
* @returns Cancellable promise. * @returns Cancellable promise.
*/ */
waitFor(condition: () => boolean, interval: number = 50): CoreCancellablePromise<void> { waitFor(condition: () => boolean): CoreCancellablePromise<void>;
waitFor(condition: () => boolean, options: CoreUtilsWaitOptions): CoreCancellablePromise<void>;
waitFor(condition: () => boolean, interval: number): CoreCancellablePromise<void>;
waitFor(condition: () => boolean, optionsOrInterval: CoreUtilsWaitOptions | number = {}): CoreCancellablePromise<void> {
const options = typeof optionsOrInterval === 'number' ? { interval: optionsOrInterval } : optionsOrInterval;
if (condition()) { if (condition()) {
return CoreCancellablePromise.resolve(); return CoreCancellablePromise.resolve();
} }
const startTime = Date.now();
let intervalId: number | undefined; let intervalId: number | undefined;
return new CoreCancellablePromise<void>( return new CoreCancellablePromise<void>(
async (resolve) => { async (resolve) => {
intervalId = window.setInterval(() => { intervalId = window.setInterval(() => {
if (!condition()) { if (!condition() && (!options.timeout || (Date.now() - startTime < options.timeout))) {
return; return;
} }
resolve(); resolve();
window.clearInterval(intervalId); window.clearInterval(intervalId);
}, interval); }, options.interval ?? 50);
}, },
() => window.clearInterval(intervalId), () => window.clearInterval(intervalId),
); );
@ -1939,6 +1945,14 @@ export type CoreUtilsOpenInAppOptions = InAppBrowserOptions & {
originalUrl?: string; // Original URL to open (in case the URL was treated, e.g. to add a token or an auto-login). originalUrl?: string; // Original URL to open (in case the URL was treated, e.g. to add a token or an auto-login).
}; };
/**
* Options for waiting.
*/
export type CoreUtilsWaitOptions = {
interval?: number;
timeout?: number;
};
/** /**
* Possible default picker actions. * Possible default picker actions.
*/ */