MOBILE-4616 chore: Create CoreWait to add waiting functions
parent
7068db3f62
commit
7d9c9b6fe9
|
@ -23,6 +23,7 @@ import { CoreUtils } from '@services/utils/utils';
|
|||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreSite } from '@classes/sites/site';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Handler to support the MathJax filter.
|
||||
|
@ -321,7 +322,7 @@ export class AddonFilterMathJaxLoaderHandlerService extends CoreFilterDefaultHan
|
|||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.wait(250);
|
||||
await CoreWait.wait(250);
|
||||
await CoreUtils.ignoreErrors(this.waitForReady(retries + 1));
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import { CoreConstants } from '@/core/constants';
|
|||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreKeyboard } from '@singletons/keyboard';
|
||||
import { CoreText } from '@singletons/text';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that displays a message discussion page.
|
||||
|
@ -884,7 +885,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
|
|||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.wait(400);
|
||||
await CoreWait.wait(400);
|
||||
await CoreUtils.ignoreErrors(this.waitForFetch());
|
||||
}
|
||||
|
||||
|
@ -1072,7 +1073,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
|
|||
this.setNewMessagesBadge(0);
|
||||
|
||||
// Leave time for the view to be rendered.
|
||||
await CoreUtils.nextTicks(5);
|
||||
await CoreWait.nextTicks(5);
|
||||
|
||||
if (!this.viewDestroyed && this.content) {
|
||||
this.content.scrollToBottom(0);
|
||||
|
|
|
@ -32,6 +32,7 @@ import { CoreUser } from '@features/user/services/user';
|
|||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreTextErrorObject, CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Service to sync messages.
|
||||
|
@ -252,7 +253,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider<AddonMessage
|
|||
// In some Moodle versions, wait 1 second to make sure timecreated is different.
|
||||
// This is because there was a bug where messages with the same timecreated had a wrong order.
|
||||
if (!groupMessagingEnabled && i < messages.length - 1) {
|
||||
await CoreUtils.wait(1000);
|
||||
await CoreWait.wait(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import { AfterViewInit, Component, ViewChild } from '@angular/core';
|
|||
import { CoreCourseModuleMainActivityPage } from '@features/course/classes/main-activity-page';
|
||||
import { AddonModAssignIndexComponent } from '../../components/index/index';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that displays an assign.
|
||||
|
@ -44,7 +44,7 @@ export class AddonModAssignIndexPage extends CoreCourseModuleMainActivityPage<Ad
|
|||
async ngAfterViewInit(): Promise<void> {
|
||||
switch (this.action) {
|
||||
case 'editsubmission':
|
||||
await CoreUtils.waitFor(() => !!this.activityComponent?.submissionComponent, { timeout: 5000 });
|
||||
await CoreWait.waitFor(() => !!this.activityComponent?.submissionComponent, { timeout: 5000 });
|
||||
await this.activityComponent?.submissionComponent?.goToEdit();
|
||||
|
||||
break;
|
||||
|
|
|
@ -30,6 +30,7 @@ import { AddonModChatFormattedMessage, AddonModChatHelper } from '../../services
|
|||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreKeyboard } from '@singletons/keyboard';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that displays a chat session.
|
||||
|
@ -358,7 +359,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
|||
*/
|
||||
async scrollToBottom(): Promise<void> {
|
||||
// Need a timeout to leave time to the view to be rendered.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
if (!this.viewDestroyed) {
|
||||
this.content?.scrollToBottom();
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
|||
import { CoreWSError } from '@classes/errors/wserror';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT, AddonModQuizAttemptStates, ADDON_MOD_QUIZ_COMPONENT } from '../../constants';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that allows attempting a quiz.
|
||||
|
@ -831,7 +832,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
* @param slot Slot of the question to scroll to.
|
||||
*/
|
||||
protected async scrollToQuestion(slot: number): Promise<void> {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
await CoreDirectivesRegistry.waitDirectivesReady(this.elementRef.nativeElement, 'core-question');
|
||||
await CoreDom.scrollToElement(
|
||||
this.elementRef.nativeElement,
|
||||
|
|
|
@ -49,6 +49,7 @@ import {
|
|||
ADDON_MOD_SCORM_DATA_AUTO_SYNCED,
|
||||
ADDON_MOD_SCORM_PAGE_NAME,
|
||||
} from '../../constants';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Component that displays a SCORM entry page.
|
||||
|
@ -616,7 +617,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
|
||||
if (CoreSync.isBlocked(ADDON_MOD_SCORM_COMPONENT, this.scorm.id) && retries < 5) {
|
||||
// Sync is currently blocked, this can happen when SCORM player is left. Retry in a bit.
|
||||
await CoreUtils.wait(400);
|
||||
await CoreWait.wait(400);
|
||||
|
||||
return this.sync(retries + 1);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT,
|
||||
ADDON_MOD_SCORM_UPDATE_TOC_EVENT,
|
||||
} from '../../constants';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that allows playing a SCORM.
|
||||
|
@ -436,7 +437,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
|
|||
// Changing SCO. First unload the existing SCO to make sure the callback to send the data has been called.
|
||||
this.src = '';
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Load the SCO in the existing model.
|
||||
this.dataModel.loadSco(sco.id);
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
|
||||
import { CoreFormatTextDirective } from '@directives/format-text';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
||||
import { CoreCoordinates, CoreDom } from '@singletons/dom';
|
||||
import { CoreEventObserver } from '@singletons/events';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { AddonModQuizDdwtosQuestionData } from '../component/ddwtos';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Class to make a question of ddwtos type work.
|
||||
|
@ -491,7 +491,7 @@ export class AddonQtypeDdwtosQuestion {
|
|||
} else {
|
||||
// Group items should always have a parent, add a fallback just in case.
|
||||
await CoreDom.waitToBeInDOM(groupItems[0]);
|
||||
await CoreUtils.nextTicks(5);
|
||||
await CoreWait.nextTicks(5);
|
||||
}
|
||||
|
||||
// Find max height and width.
|
||||
|
|
|
@ -18,7 +18,7 @@ import { CoreQuestionHelper } from '@features/question/services/question-helper'
|
|||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { ItemReorderEventDetail } from '@ionic/angular';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { CorePlatform } from '@services/platform';
|
||||
|
||||
/**
|
||||
|
@ -153,7 +153,7 @@ export class AddonQtypeOrderingComponent extends CoreQuestionBaseComponent<Addon
|
|||
complete: () => {}, // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
});
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// When moving an item to the first or last position, the button that was clicked will be hidden. In this case, we need to
|
||||
// focus the other button. Otherwise, re-focus the same button since the focus is lost in some cases.
|
||||
|
|
|
@ -27,6 +27,7 @@ import { CorePlatform } from '@services/platform';
|
|||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { register } from 'swiper/element/bundle';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
register();
|
||||
|
||||
|
@ -83,7 +84,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
// Check if the path changes due to the back navigation handler, to know if we're at root level.
|
||||
// Ionic doc recommends IonRouterOutlet.canGoBack, but there's no easy way to get the current outlet from here.
|
||||
// The path seems to change immediately (0 ms timeout), but use 50ms just in case.
|
||||
await CoreUtils.wait(50);
|
||||
await CoreWait.wait(50);
|
||||
|
||||
if (CoreNavigator.getCurrentPath() != initialPath) {
|
||||
// Ionic has navigated back, nothing else to do.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { LoadingController } from '@singletons';
|
||||
|
||||
/**
|
||||
|
@ -105,7 +105,7 @@ export class CoreIonLoadingElement {
|
|||
// Wait a bit before presenting the modal, to prevent it being displayed if dismiss is called fast.
|
||||
this.scheduled = true;
|
||||
|
||||
await CoreUtils.wait(40);
|
||||
await CoreWait.wait(40);
|
||||
|
||||
if (!this.scheduled) {
|
||||
return;
|
||||
|
|
|
@ -19,6 +19,7 @@ import { AsyncDirective } from './async-directive';
|
|||
import { PageLoadsManager } from './page-loads-manager';
|
||||
import { CorePromisedValue } from './promised-value';
|
||||
import { WSObservable } from './sites/authenticated-site';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Class to watch requests from a page load (including requests from page sub-components).
|
||||
|
@ -111,7 +112,7 @@ export class PageLoadWatcher {
|
|||
this.checkHasLoaded();
|
||||
|
||||
// Subscription variable might not be set because the observable completed immediately. Wait for next tick.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
subscription?.unsubscribe();
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import { Md5 } from 'ts-md5';
|
|||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
import { CoreSiteWSCacheRecord } from '@services/database/sites';
|
||||
import { CoreErrorLogs } from '@singletons/error-logs';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Class that represents a site (combination of site + user) where the user has authenticated but the site hasn't been validated
|
||||
|
@ -1584,7 +1585,7 @@ export function chainRequests<T, O extends ObservableInput<any>>(
|
|||
firstValue = false;
|
||||
|
||||
// Wait to see if the observable is completed (no more values).
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
if (isCompleted) {
|
||||
// Current request only returns cached data. Let chained requests update in background.
|
||||
|
@ -1601,7 +1602,7 @@ export function chainRequests<T, O extends ObservableInput<any>>(
|
|||
complete: async () => {
|
||||
isCompleted = true;
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
subscriber.complete();
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@ import { CoreSettingsHelper } from '@features/settings/services/settings-helper'
|
|||
import { CoreAriaRoleTab, CoreAriaRoleTabFindable } from './aria-role-tab';
|
||||
import { CoreEventObserver } from '@singletons/events';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { CoreError } from './errors/error';
|
||||
import { CorePromisedValue } from './promised-value';
|
||||
import { AsyncDirective } from './async-directive';
|
||||
|
@ -218,7 +218,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
|
|||
this.slideChanged();
|
||||
|
||||
this.swiper.update();
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
if (!this.hasSliddenToInitial && this.selectedIndex && this.selectedIndex >= this.swiper.slidesPerViewDynamic()) {
|
||||
this.hasSliddenToInitial = true;
|
||||
|
@ -344,7 +344,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
|
|||
}
|
||||
|
||||
this.maxSlides = 3;
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
if (!this.swiper.width) {
|
||||
return;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { CoreQueueRunner } from '@classes/queue-runner';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
describe('CoreQueueRunner', () => {
|
||||
|
||||
|
@ -26,7 +26,7 @@ describe('CoreQueueRunner', () => {
|
|||
|
||||
// Act
|
||||
await Promise.all(range.map((i) => lock.run(async () => {
|
||||
await CoreUtils.wait(Math.floor(Math.random() * 10));
|
||||
await CoreWait.wait(Math.floor(Math.random() * 10));
|
||||
|
||||
items.push(`Item #${i}`);
|
||||
})));
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChange, ViewChild, ElementRef } from '@angular/core';
|
||||
import { IonInfiniteScroll } from '@ionic/angular';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
const THRESHOLD = .15; // % of the scroll element height that must be close to the edge to consider loading more items necessary.
|
||||
|
||||
|
@ -77,8 +77,8 @@ export class CoreInfiniteLoadingComponent implements OnChanges {
|
|||
}
|
||||
|
||||
// Wait to allow items to render and scroll content to grow.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreUtils.waitFor(() => scrollElement.scrollHeight > scrollElement.clientHeight, { timeout: 1000 });
|
||||
await CoreWait.nextTick();
|
||||
await CoreWait.waitFor(() => scrollElement.scrollHeight > scrollElement.clientHeight, { timeout: 1000 });
|
||||
|
||||
// Calculate distance from edge.
|
||||
const infiniteHeight = this.hostElement.getBoundingClientRect().height;
|
||||
|
@ -116,7 +116,7 @@ export class CoreInfiniteLoadingComponent implements OnChanges {
|
|||
*/
|
||||
async complete(): Promise<void> {
|
||||
// Wait a bit before allowing loading more, otherwise it could be re-triggered automatically when it shouldn't.
|
||||
await CoreUtils.wait(400);
|
||||
await CoreWait.wait(400);
|
||||
|
||||
await this.completeLoadMore();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
|||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { AsyncDirective } from '@classes/async-directive';
|
||||
import { CorePlatform } from '@services/platform';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Component to show a loading spinner and message while data is being loaded.
|
||||
|
@ -72,13 +73,13 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A
|
|||
|
||||
// Throttle 20ms to let mutations resolve.
|
||||
const throttleMutation = CoreUtils.throttle(async () => {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
if (!this.loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.element.style.display = 'inline';
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
this.element.style.removeProperty('display');
|
||||
}, 20);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular
|
|||
import { CoreModalComponent } from '@classes/modal-component';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { CoreModals } from '@services/modals';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { AngularFrameworkDelegate } from '@singletons';
|
||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
||||
|
||||
|
@ -64,13 +64,13 @@ export class CoreSheetModalComponent<T extends CoreModalComponent> implements Af
|
|||
const wrapper = await this.wrapperElement;
|
||||
this.content = await AngularFrameworkDelegate.attachViewToDom(wrapper, this.component, this.componentProps ?? {});
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
this.element.classList.add('active');
|
||||
this.element.style.zIndex = `${20000 + CoreModals.getTopOverlayIndex()}`;
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreUtils.wait(300);
|
||||
await CoreWait.nextTick();
|
||||
await CoreWait.wait(300);
|
||||
|
||||
const instance = CoreDirectivesRegistry.resolve(this.content, this.component);
|
||||
|
||||
|
@ -89,8 +89,8 @@ export class CoreSheetModalComponent<T extends CoreModalComponent> implements Af
|
|||
|
||||
this.element.classList.remove('active');
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreUtils.wait(300);
|
||||
await CoreWait.nextTick();
|
||||
await CoreWait.wait(300);
|
||||
await AngularFrameworkDelegate.removeViewFromDom(wrapper, this.content);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import { CoreSwipeSlidesItemsManager } from '@classes/items-management/swipe-sli
|
|||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { IonContent } from '@ionic/angular';
|
||||
import { CoreDomUtils, VerticalPoint } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { NgZone } from '@singletons';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreEventObserver } from '@singletons/events';
|
||||
|
@ -230,7 +230,7 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
*/
|
||||
protected async onItemsUpdated(): Promise<void> {
|
||||
// Wait for slides to be added in DOM.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Update the slides component so the slides list reflects the new items.
|
||||
await this.updateSlidesComponent();
|
||||
|
@ -348,7 +348,7 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
this.swiper.update();
|
||||
|
||||
// We need to ensure the slides are updated before continuing.
|
||||
await CoreUtils.nextTicks(2);
|
||||
await CoreWait.nextTicks(2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@ import { Directive, Input, ElementRef, AfterViewInit } from '@angular/core';
|
|||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Directive to auto focus an element when a view is loaded.
|
||||
|
@ -51,7 +52,7 @@ export class CoreAutoFocusDirective implements AfterViewInit {
|
|||
|
||||
// Wait in case there is an animation to enter the page, otherwise the interaction
|
||||
// between the keyboard appearing and the animation causes a visual glitch.
|
||||
await CoreUtils.wait(540);
|
||||
await CoreWait.wait(540);
|
||||
|
||||
CoreDomUtils.focusElement(this.element);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import { CoreEventObserver } from '@singletons/events';
|
|||
import { CoreLoadingComponent } from '@components/loading/loading';
|
||||
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Directive to make an element fixed at the bottom collapsible when scrolling.
|
||||
|
@ -101,7 +102,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
await this.viewportPromise;
|
||||
|
||||
this.element.classList.remove('is-active');
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Set a minimum height value.
|
||||
this.initialHeight = this.element.getBoundingClientRect().height || this.initialHeight;
|
||||
|
|
|
@ -27,6 +27,7 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
|||
import { CoreMath } from '@singletons/math';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CoreFormatTextDirective } from './format-text';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
declare module '@singletons/events' {
|
||||
|
||||
|
@ -344,7 +345,7 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
await this.visiblePromise;
|
||||
|
||||
this.page.classList.remove('collapsible-header-page-is-active');
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Add floating title and measure initial position.
|
||||
const collapsedHeaderTitle = this.collapsedHeader.querySelector('h1') as HTMLHeadingElement;
|
||||
|
@ -429,7 +430,7 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
}
|
||||
|
||||
// Make sure elements have been added to the DOM.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Wait all loadings and tabs to finish loading.
|
||||
await CoreDirectivesRegistry.waitMultipleDirectivesReady(this.page, [
|
||||
|
|
|
@ -56,6 +56,7 @@ import { FrameElement, FrameElementController } from '@classes/element-controlle
|
|||
import { CoreUrl } from '@singletons/url';
|
||||
import { CoreIcons } from '@singletons/icons';
|
||||
import { ContextLevel } from '../constants';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective
|
||||
|
@ -339,7 +340,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
|
|||
// Show the element again.
|
||||
this.element.classList.remove('core-loading');
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Emit the afterRender output.
|
||||
this.afterRender.emit();
|
||||
|
@ -380,7 +381,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
|
|||
this.elementControllers.forEach(controller => controller.destroy());
|
||||
this.elementControllers = result.elementControllers;
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Add magnifying glasses to images.
|
||||
this.addImageViewerButton();
|
||||
|
@ -705,7 +706,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
|
|||
const previousDisplay = getComputedStyle(this.element).display;
|
||||
|
||||
this.element.style.display = 'inline-block';
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
width = this.element.getBoundingClientRect().width;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import { CoreCoursesDashboard } from '@features/courses/services/dashboard';
|
|||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { ContextLevel } from '@/core/constants';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Component that displays the list of side blocks.
|
||||
|
@ -135,8 +136,8 @@ export class CoreBlockSideBlocksComponent implements OnInit {
|
|||
|
||||
const selector = '#block-' + this.initialBlockInstanceId;
|
||||
|
||||
await CoreUtils.waitFor(() => !!this.elementRef.nativeElement.querySelector(selector));
|
||||
await CoreUtils.wait(200);
|
||||
await CoreWait.waitFor(() => !!this.elementRef.nativeElement.querySelector(selector));
|
||||
await CoreWait.wait(200);
|
||||
|
||||
CoreDom.scrollToElement(this.elementRef.nativeElement, selector, { addYAxis: -10 });
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ import { CorePath } from '@singletons/path';
|
|||
import { CoreText } from '@singletons/text';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreUrl } from '@singletons/url';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { CoreWindow } from '@singletons/window';
|
||||
import { CoreCache } from '@classes/cache';
|
||||
import { CoreDelegate } from '@classes/delegate';
|
||||
|
@ -314,6 +315,7 @@ export class CoreCompileProvider {
|
|||
instance['CoreText'] = CoreText;
|
||||
instance['CoreTime'] = CoreTime;
|
||||
instance['CoreUrl'] = CoreUrl;
|
||||
instance['CoreWait'] = CoreWait;
|
||||
instance['CoreWindow'] = CoreWindow;
|
||||
instance['CoreCache'] = CoreCache; // @deprecated since 4.4, plugins should use plain objects instead.
|
||||
instance['CoreDelegate'] = CoreDelegate;
|
||||
|
|
|
@ -24,7 +24,7 @@ import { CoreCourseFormatDelegate } from '@features/course/services/format-deleg
|
|||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { ModalController } from '@singletons';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
|
||||
|
@ -123,11 +123,11 @@ export class CoreCourseCourseIndexComponent implements OnInit {
|
|||
this.highlighted = CoreCourseFormatDelegate.getSectionHightlightedName(this.course);
|
||||
|
||||
// Wait a bit to render the data, otherwise the modal takes a while to appear in big courses or slow devices.
|
||||
await CoreUtils.wait(400);
|
||||
await CoreWait.wait(400);
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
CoreDom.scrollToElement(
|
||||
this.elementRef.nativeElement,
|
||||
|
|
|
@ -42,6 +42,7 @@ import { CoreNavigator } from '@services/navigator';
|
|||
import { CoreRefreshContext, CORE_REFRESH_CONTEXT } from '@/core/utils/refresh-context';
|
||||
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that displays the contents of a course.
|
||||
|
@ -411,7 +412,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy, CoreRefreshCon
|
|||
this.changeDetectorRef.detectChanges();
|
||||
|
||||
if (scrollTop > 0) {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
this.content?.scrollToPoint(0, scrollTop, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import { CoreCoursesHelper, CoreCourseWithImageAndColor } from '@features/course
|
|||
import { CoreColors } from '@singletons/colors';
|
||||
import { CorePath } from '@singletons/path';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that displays the list of courses the user is enrolled in.
|
||||
|
@ -209,7 +210,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
|
|||
// Select the tab if needed.
|
||||
this.firstTabName = undefined;
|
||||
if (tabToLoad) {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
this.tabsComponent?.selectByIndex(tabToLoad);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import { CoreCourses } from '../../services/courses';
|
|||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page that shows a my courses.
|
||||
|
@ -129,7 +130,7 @@ export class CoreCoursesMyPage implements OnInit, OnDestroy, AsyncDirective {
|
|||
this.loadedBlock = blocks.mainBlocks.concat(blocks.sideBlocks).find((block) => block.name == 'myoverview');
|
||||
this.hasSideBlocks = supportsMyParam && CoreBlockDelegate.hasSupportedBlock(blocks.sideBlocks);
|
||||
|
||||
await CoreUtils.nextTicks(2);
|
||||
await CoreWait.nextTicks(2);
|
||||
|
||||
this.myOverviewBlock = this.block?.dynamicComponent?.instance as AddonBlockMyOverviewComponent;
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import { SwiperOptions } from 'swiper/types';
|
|||
import { ContextLevel } from '@/core/constants';
|
||||
import { CoreSwiper } from '@singletons/swiper';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Component to display a rich text editor if enabled.
|
||||
|
@ -369,7 +370,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit,
|
|||
* @returns Blank height in px. Will be negative if no blank space.
|
||||
*/
|
||||
protected async getBlankHeightInContent(): Promise<number> {
|
||||
await CoreUtils.nextTicks(5); // Ensure content is completely loaded in the DOM.
|
||||
await CoreWait.nextTicks(5); // Ensure content is completely loaded in the DOM.
|
||||
|
||||
let content: Element | null = this.element.closest('ion-content');
|
||||
const contentHeight = await CoreDomUtils.getContentHeight(this.content);
|
||||
|
@ -485,7 +486,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit,
|
|||
this.textareaElement?.removeAttribute('hidden');
|
||||
}
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
this.focusRTE(event);
|
||||
}
|
||||
|
@ -826,7 +827,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit,
|
|||
this.toolbarArrows = true;
|
||||
}
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
this.toolbarSlides.update();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { CoreError } from '@classes/errors/error';
|
||||
import { ILocalNotification, ILocalNotificationAction, LocalNotifications } from '@awesome-cordova-plugins/local-notifications/ngx';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { CorePlatform } from '@services/platform';
|
||||
|
||||
/**
|
||||
|
@ -340,7 +340,7 @@ export class LocalNotificationsMock extends LocalNotifications {
|
|||
// In some testing environments, Notification.requestPermission gets stuck and never returns.
|
||||
// Given that we don't actually need browser notifications to work in Behat tests, we can just
|
||||
// continue if the permissions haven't been granted after 1 second.
|
||||
permissionRequests.push(CoreUtils.wait(1000).then(() => 'granted'));
|
||||
permissionRequests.push(CoreWait.wait(1000).then(() => 'granted'));
|
||||
}
|
||||
|
||||
const permission = await Promise.race(permissionRequests);
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
||||
import { SubPartial } from '@/core/utils/types';
|
||||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Component that displays help to connect to a site.
|
||||
|
@ -118,7 +119,7 @@ export class CoreLoginSiteHelpComponent implements AfterViewInit, OnDestroy {
|
|||
const answers = Array.from(this.el.nativeElement.querySelectorAll<HTMLElement>('.core-login-site-help--answer'));
|
||||
|
||||
await Promise.all(answers.map(async answer => {
|
||||
await this.track(CoreUtils.waitFor(() => answer.clientHeight !== 0));
|
||||
await this.track(CoreWait.waitFor(() => answer.clientHeight !== 0));
|
||||
await this.track(CoreDomUtils.waitForImages(answer));
|
||||
|
||||
answer.style.setProperty('--height', `${answer.clientHeight}px`);
|
||||
|
|
|
@ -31,6 +31,7 @@ import { CoreSites } from '@services/sites';
|
|||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CorePlatform } from '@services/platform';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
const ANIMATION_DURATION = 500;
|
||||
|
||||
|
@ -203,7 +204,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
|
||||
if (this.loaded && (!mainMenuTab || removedHandlersPages.includes(mainMenuTab))) {
|
||||
// No tab selected or handler no longer available, select the first one.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
const tabPage = this.tabs[0] ? this.tabs[0].page : this.morePageName;
|
||||
const tabPageParams = this.tabs[0] ? this.tabs[0].pageParams : {};
|
||||
|
@ -330,9 +331,9 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
* Notify that the menu visibility has been updated.
|
||||
*/
|
||||
protected async notifyVisibilityUpdated(): Promise<void> {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreUtils.wait(ANIMATION_DURATION);
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
await CoreWait.wait(ANIMATION_DURATION);
|
||||
await CoreWait.nextTick();
|
||||
|
||||
CoreEvents.trigger(CoreMainMenuProvider.MAIN_MENU_VISIBILITY_UPDATED);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import { IonContent } from '@ionic/angular';
|
|||
import { CoreScreen } from '@services/screen';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Page to accept a site policy.
|
||||
|
@ -337,7 +338,7 @@ export class CorePolicySitePolicyPage implements OnInit, OnDestroy {
|
|||
* Check if the content has scroll.
|
||||
*/
|
||||
protected async checkScroll(): Promise<void> {
|
||||
await CoreUtils.wait(400);
|
||||
await CoreWait.wait(400);
|
||||
|
||||
const scrollElement = await this.content?.getScrollElement();
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
CoreReminderValueAndUnit,
|
||||
} from '@features/reminders/services/reminders';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { PopoverController } from '@singletons';
|
||||
import { CoreRemindersSetReminderCustomComponent } from '../set-reminder-custom/set-reminder-custom';
|
||||
|
||||
|
@ -175,7 +175,7 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
|||
this.customLabel = CoreReminders.getUnitValueLabel(this.customValue, this.customUnits);
|
||||
|
||||
// Let the dimissed popover to be removed.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
PopoverController.dismiss({ timeBefore: Math.abs(this.customValue) * this.customUnits });
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import { CoreSubscriptions } from '@singletons/subscriptions';
|
|||
import { CoreUserToursUserTourComponent } from '../components/user-tour/user-tour';
|
||||
import { APP_SCHEMA, CoreUserToursDBEntry, USER_TOURS_TABLE_NAME } from './database/user-tours';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/**
|
||||
* Service to manage User Tours.
|
||||
|
@ -113,7 +114,7 @@ export class CoreUserToursService {
|
|||
protected async show(options: CoreUserToursBasicOptions | CoreUserToursFocusedOptions): Promise<CoreUserToursUserTour> {
|
||||
const { delay, ...componentOptions } = options;
|
||||
|
||||
await CoreUtils.wait(delay ?? 200);
|
||||
await CoreWait.wait(delay ?? 200);
|
||||
|
||||
options.after && await this.waitForUserTour(options.after, options.afterTimeout);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Translate, makeSingleton } from '@singletons';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreForms } from '@singletons/form';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
@ -113,7 +113,7 @@ export class CoreErrorAccordionService {
|
|||
wrapper.style.setProperty('--description-height', `${description.clientHeight}px`);
|
||||
wrapper.classList.add('hydrated');
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
hideText.style.display = 'revert';
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import { Http } from '@singletons';
|
|||
import { of } from 'rxjs';
|
||||
import { CoreSite } from '@classes/sites/site';
|
||||
import { CoreHTMLClasses } from '@singletons/html-classes';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
describe('CoreSitesProvider', () => {
|
||||
|
||||
|
@ -74,7 +74,7 @@ describe('CoreSitesProvider', () => {
|
|||
|
||||
CoreEvents.trigger(CoreEvents.LOGIN, {}, '42');
|
||||
// Wait the event to be processed.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(true);
|
||||
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(false);
|
||||
|
@ -86,7 +86,7 @@ describe('CoreSitesProvider', () => {
|
|||
CoreEvents.trigger(CoreEvents.SITE_UPDATED, site.infos , '42');
|
||||
|
||||
// Wait the event to be processed.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(true);
|
||||
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(false);
|
||||
|
@ -99,7 +99,7 @@ describe('CoreSitesProvider', () => {
|
|||
CoreEvents.trigger(CoreEvents.SITE_ADDED, site.infos , '42');
|
||||
|
||||
// Wait the event to be processed.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(true);
|
||||
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(false);
|
||||
|
|
|
@ -59,6 +59,7 @@ import { CorePasswordModalParams, CorePasswordModalResponse } from '@components/
|
|||
import { CoreWSError } from '@classes/errors/wserror';
|
||||
import { CoreErrorLogs } from '@singletons/error-logs';
|
||||
import { CoreKeyboard } from '@singletons/keyboard';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
|
||||
/*
|
||||
* "Utils" service with helper functions for UI, DOM elements and HTML code.
|
||||
|
@ -333,7 +334,7 @@ export class CoreDomUtilsProvider {
|
|||
elementToFocus.focus();
|
||||
|
||||
if (elementToFocus === document.activeElement || (isIonButton && element === document.activeElement)) {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
if (CorePlatform.isAndroid() && this.supportsInputKeyboard(elementToFocus)) {
|
||||
// On some Android versions the keyboard doesn't open automatically.
|
||||
CoreKeyboard.open();
|
||||
|
@ -342,7 +343,7 @@ export class CoreDomUtilsProvider {
|
|||
}
|
||||
|
||||
// @TODO Probably a Mutation Observer would get this working.
|
||||
await CoreUtils.wait(50);
|
||||
await CoreWait.wait(50);
|
||||
retries--;
|
||||
}
|
||||
}
|
||||
|
@ -1762,7 +1763,7 @@ export class CoreDomUtilsProvider {
|
|||
}
|
||||
|
||||
// Wait a bit and try again.
|
||||
await CoreUtils.wait(50);
|
||||
await CoreWait.wait(50);
|
||||
|
||||
return this.waitForResizeDone(windowWidth, windowHeight, retries+1);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import { CoreUrlUtils } from './url';
|
|||
import { QRScanner } from '@features/native/plugins';
|
||||
import { CoreArray } from '@singletons/array';
|
||||
import { CoreText } from '@singletons/text';
|
||||
import { CoreWait, CoreWaitOptions } from '@singletons/wait';
|
||||
|
||||
export type TreeNode<T> = T & { children: TreeNode<T>[] };
|
||||
|
||||
|
@ -1783,10 +1784,10 @@ export class CoreUtilsProvider {
|
|||
* Wait some time.
|
||||
*
|
||||
* @param milliseconds Number of milliseconds to wait.
|
||||
* @returns Promise resolved after the time has passed.
|
||||
* @deprecated since 4.5. Use CoreWait.wait instead.
|
||||
*/
|
||||
wait(milliseconds: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
async wait(milliseconds: number): Promise<void> {
|
||||
await CoreWait.wait(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1794,51 +1795,34 @@ export class CoreUtilsProvider {
|
|||
*
|
||||
* @param condition Condition.
|
||||
* @returns Cancellable promise.
|
||||
* @deprecated since 4.5. Use CoreWait.waitFor instead.
|
||||
*/
|
||||
waitFor(condition: () => boolean): CoreCancellablePromise<void>;
|
||||
waitFor(condition: () => boolean, options: CoreUtilsWaitOptions): CoreCancellablePromise<void>;
|
||||
waitFor(condition: () => boolean, options: CoreWaitOptions): CoreCancellablePromise<void>;
|
||||
waitFor(condition: () => boolean, interval: number): CoreCancellablePromise<void>;
|
||||
waitFor(condition: () => boolean, optionsOrInterval: CoreUtilsWaitOptions | number = {}): CoreCancellablePromise<void> {
|
||||
waitFor(condition: () => boolean, optionsOrInterval: CoreWaitOptions | number = {}): CoreCancellablePromise<void> {
|
||||
const options = typeof optionsOrInterval === 'number' ? { interval: optionsOrInterval } : optionsOrInterval;
|
||||
|
||||
if (condition()) {
|
||||
return CoreCancellablePromise.resolve();
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
let intervalId: number | undefined;
|
||||
|
||||
return new CoreCancellablePromise<void>(
|
||||
async (resolve) => {
|
||||
intervalId = window.setInterval(() => {
|
||||
if (!condition() && (!options.timeout || (Date.now() - startTime < options.timeout))) {
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
window.clearInterval(intervalId);
|
||||
}, options.interval ?? 50);
|
||||
},
|
||||
() => window.clearInterval(intervalId),
|
||||
);
|
||||
return CoreWait.waitFor(condition, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the next tick.
|
||||
*
|
||||
* @returns Promise resolved when tick has been done.
|
||||
* @deprecated since 4.5. Use CoreWait.nextTick instead.
|
||||
*/
|
||||
nextTick(): Promise<void> {
|
||||
return this.wait(0);
|
||||
async nextTick(): Promise<void> {
|
||||
await CoreWait.nextTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until several next ticks.
|
||||
*
|
||||
* @param numTicks Number of ticks to wait.
|
||||
* @deprecated since 4.5. Use CoreWait.nextTicks instead.
|
||||
*/
|
||||
async nextTicks(numTicks = 0): Promise<void> {
|
||||
for (let i = 0; i < numTicks; i++) {
|
||||
await this.wait(0);
|
||||
}
|
||||
await CoreWait.nextTicks(numTicks);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1916,11 +1900,10 @@ export type CoreUtilsOpenInAppOptions = InAppBrowserOptions & {
|
|||
|
||||
/**
|
||||
* Options for waiting.
|
||||
*
|
||||
* @deprecated since 4.5. Use CoreWaitOptions instead.
|
||||
*/
|
||||
export type CoreUtilsWaitOptions = {
|
||||
interval?: number;
|
||||
timeout?: number;
|
||||
};
|
||||
export type CoreUtilsWaitOptions = CoreWaitOptions;
|
||||
|
||||
/**
|
||||
* Possible default picker actions.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Directive } from '@angular/core';
|
||||
import { AsyncDirective } from '@classes/async-directive';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from './wait';
|
||||
import { CoreLogger } from './logger';
|
||||
|
||||
/**
|
||||
|
@ -135,7 +135,7 @@ export class CoreDirectivesRegistry {
|
|||
}));
|
||||
|
||||
// Wait for next tick to ensure directives are completely rendered.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Check if there are new elements now that the found elements are ready (there could be nested elements).
|
||||
if (elements.length !== findElements().length) {
|
||||
|
@ -181,7 +181,7 @@ export class CoreDirectivesRegistry {
|
|||
}));
|
||||
|
||||
// Wait for next tick to ensure directives are completely rendered.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
// Check if there are new elements now that the found elements are ready (there could be nested elements).
|
||||
const elementsAfterReady = directives.reduce((elements, directive) => {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { EventEmitter } from '@angular/core';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from './wait';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
/**
|
||||
|
@ -52,7 +52,7 @@ export class CoreSubscriptions {
|
|||
};
|
||||
const unsubscribe = async () => {
|
||||
// Subscription variable might not be set because we can receive a value immediately. Wait for next tick.
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
subscription?.unsubscribe();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
||||
|
||||
/**
|
||||
* Singleton with helper functions to wait.
|
||||
*/
|
||||
export class CoreWait {
|
||||
|
||||
/**
|
||||
* Wait until the next tick.
|
||||
*
|
||||
* @returns Promise resolved when tick has been done.
|
||||
*/
|
||||
static async nextTick(): Promise<void> {
|
||||
return CoreWait.wait(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until several next ticks.
|
||||
*
|
||||
* @param numTicks Number of ticks to wait.
|
||||
*/
|
||||
static async nextTicks(numTicks = 0): Promise<void> {
|
||||
for (let i = 0; i < numTicks; i++) {
|
||||
await CoreWait.wait(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait some time.
|
||||
*
|
||||
* @param milliseconds Number of milliseconds to wait.
|
||||
* @returns Promise resolved after the time has passed.
|
||||
*/
|
||||
static wait(milliseconds: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until a given condition is met.
|
||||
*
|
||||
* @param condition Condition.
|
||||
* @returns Cancellable promise.
|
||||
*/
|
||||
static waitFor(condition: () => boolean): CoreCancellablePromise<void>;
|
||||
static waitFor(condition: () => boolean, options: CoreWaitOptions): CoreCancellablePromise<void>;
|
||||
static waitFor(condition: () => boolean, interval: number): CoreCancellablePromise<void>;
|
||||
static waitFor(condition: () => boolean, optionsOrInterval: CoreWaitOptions | number = {}): CoreCancellablePromise<void> {
|
||||
const options = typeof optionsOrInterval === 'number' ? { interval: optionsOrInterval } : optionsOrInterval;
|
||||
|
||||
if (condition()) {
|
||||
return CoreCancellablePromise.resolve();
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
let intervalId: number | undefined;
|
||||
|
||||
return new CoreCancellablePromise<void>(
|
||||
async (resolve) => {
|
||||
intervalId = window.setInterval(() => {
|
||||
if (!condition() && (!options.timeout || (Date.now() - startTime < options.timeout))) {
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
window.clearInterval(intervalId);
|
||||
}, options.interval ?? 50);
|
||||
},
|
||||
() => window.clearInterval(intervalId),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for waiting.
|
||||
*/
|
||||
export type CoreWaitOptions = {
|
||||
interval?: number;
|
||||
timeout?: number;
|
||||
};
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { makeSingleton, NgZone } from '@singletons';
|
||||
import { BehatTestsWindow, TestingBehatRuntime } from './behat-runtime';
|
||||
|
||||
|
@ -117,7 +117,7 @@ export class TestingBehatBlockingService {
|
|||
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
|
||||
// "This API does not guarantee that timers will run exactly on schedule.
|
||||
// Delays due to CPU load, other tasks, etc, are to be expected."
|
||||
await CoreUtils.nextTicks(10);
|
||||
await CoreWait.nextTicks(10);
|
||||
}
|
||||
|
||||
// Check there isn't a spinner...
|
||||
|
@ -193,7 +193,7 @@ export class TestingBehatBlockingService {
|
|||
* (and if not, removes it).
|
||||
*/
|
||||
protected async checkUIBlocked(): Promise<void> {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
|
||||
const blockingElements = Array.from(
|
||||
document.querySelectorAll<HTMLElement>('div.core-loading-container, ion-loading'),
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWait } from '@singletons/wait';
|
||||
import { makeSingleton, NgZone } from '@singletons';
|
||||
import { TestingBehatElementLocator, TestingBehatFindOptions } from './behat-runtime';
|
||||
|
||||
|
@ -756,7 +756,7 @@ export class TestingBehatDomUtilsService {
|
|||
|
||||
// Pretend we have cut and pasted the new text.
|
||||
if (element.tagName !== 'ION-SELECT' && getValue() !== '') {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
await setValue('');
|
||||
|
||||
element.dispatchEvent(new InputEvent('input', {
|
||||
|
@ -768,7 +768,7 @@ export class TestingBehatDomUtilsService {
|
|||
}
|
||||
|
||||
if (value !== '') {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreWait.nextTick();
|
||||
await setValue(value);
|
||||
|
||||
element.dispatchEvent(new InputEvent('input', {
|
||||
|
|
Loading…
Reference in New Issue