MOBILE-4653 utils: Completely migrate utils to singleton

main
Pau Ferrer Ocaña 2024-11-15 13:51:01 +01:00
parent 96f3be2ff1
commit f75bcea915
85 changed files with 545 additions and 359 deletions

View File

@ -14,7 +14,7 @@
import { Injectable } from '@angular/core';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { AddonBadges } from '../badges';
import { makeSingleton } from '@singletons';

View File

@ -28,7 +28,7 @@ import {
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion';
import { CoreBlockBaseComponent } from '@features/block/classes/base-block-component';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreSite } from '@classes/sites/site';
import { CoreSharedModule } from '@/core/shared.module';
import { CoreCoursesComponentsModule } from '@features/courses/components/components.module';

View File

@ -21,7 +21,7 @@ import {
} from '../../services/recentlyaccesseditems';
import { CoreText } from '@singletons/text';
import { CoreLoadings } from '@services/loadings';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreSharedModule } from '@/core/shared.module';
/**

View File

@ -23,7 +23,7 @@ import {
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion';
import { CoreBlockBaseComponent } from '@features/block/classes/base-block-component';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreSite } from '@classes/sites/site';
import { AddonBlockStarredCourse, AddonBlockStarredCourses } from '../../services/starredcourses';
import { CoreSharedModule } from '@/core/shared.module';

View File

@ -20,7 +20,7 @@ import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreCategoryData, CoreCourses, CoreCourseSearchedData, CoreEnrolledCourseData } from '@features/courses/services/courses';
import { CoreEditorRichTextEditorComponent } from '@features/editor/components/rich-text-editor/rich-text-editor';
import {

View File

@ -17,7 +17,7 @@ import { CoreSyncBaseProvider, CoreSyncBlockedError } from '@classes/base-sync';
import { CoreNetwork } from '@services/network';
import { CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import {
AddonCalendar,
AddonCalendarEvent,

View File

@ -19,7 +19,7 @@ import { CorePushNotificationsClickHandler } from '@features/pushnotifications/s
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreNavigator } from '@services/navigator';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { AddonCompetency } from '../competency';
import { CorePromiseUtils } from '@singletons/promise-utils';

View File

@ -21,7 +21,7 @@ import {
AddonMessagesMessageAreaContact,
} from '../../services/messages';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { ActivatedRoute, Params } from '@angular/router';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';

View File

@ -33,7 +33,7 @@ import { Translate } from '@singletons';
import { Subscription } from 'rxjs';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { ActivatedRoute, Params } from '@angular/router';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreNavigator } from '@services/navigator';
import { CoreScreen } from '@services/screen';
import { CorePlatform } from '@services/platform';

View File

@ -20,7 +20,7 @@ import { CoreMainMenuHandler, CoreMainMenuHandlerToDisplay } from '@features/mai
import { CoreCronHandler } from '@services/cron';
import { CoreSites } from '@services/sites';
import { CoreEvents } from '@singletons/events';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import {
CorePushNotificationsNotificationBasicData,
} from '@features/pushnotifications/services/pushnotifications';

View File

@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { AddonMessages } from '../messages';
import { AddonMessagesMainMenuHandlerService } from './mainmenu';

View File

@ -37,7 +37,7 @@ import { CoreTabsComponent } from '@components/tabs/tabs';
import { CoreTabComponent } from '@components/tabs/tab';
import { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreGradesFormattedItem, CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CoreMenuItem, CoreUtils } from '@services/utils/utils';
import { CoreMenuItem, CoreUtils } from '@singletons/utils';
import { AddonModAssignHelper, AddonModAssignSubmissionFormatted } from '../../services/assign-helper';
import { CoreDomUtils } from '@services/utils/dom';
import { Translate } from '@singletons';

View File

@ -17,7 +17,7 @@ import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { AddonModAssign } from '../assign';
import { ADDON_MOD_ASSIGN_FEATURE_NAME } from '../../constants';

View File

@ -23,7 +23,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreForms } from '@singletons/form';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { AddonModDataComponentsCompileModule } from '../../components/components-compile.module';

View File

@ -22,7 +22,7 @@ import { CoreNetwork } from '@services/network';
import { CoreNavigator } from '@services/navigator';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { NgZone, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { Subscription } from 'rxjs';

View File

@ -20,7 +20,7 @@ import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreFileHelper } from '@services/file-helper';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton, Translate } from '@singletons';
import {
AddonModFeedback,

View File

@ -17,7 +17,7 @@ import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { AddonModFeedbackHelper } from '../feedback-helper';

View File

@ -29,7 +29,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreScreen } from '@services/screen';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { NgZone, Translate } from '@singletons';
import { CoreDom } from '@singletons/dom';
import { CoreEventObserver, CoreEvents } from '@singletons/events';

View File

@ -31,7 +31,7 @@ import { CoreDomUtils } from '@services/utils/dom';
import { Translate } from '@singletons';
import { CoreSync } from '@services/sync';
import { AddonModForumDiscussionOptions, AddonModForumOffline } from '@addons/mod/forum/services/forum-offline';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { AddonModForumHelper } from '@addons/mod/forum/services/forum-helper';
import { CoreFileUploader } from '@features/fileuploader/services/fileuploader';
import { CoreText } from '@singletons/text';

View File

@ -28,7 +28,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons';
import { CorePromiseUtils } from '@singletons/promise-utils';

View File

@ -20,7 +20,7 @@ import { CoreNetwork } from '@services/network';
import { CoreFile } from '@services/file';
import { CoreSites } from '@services/sites';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton, Translate } from '@singletons';
import {
AddonModForum,

View File

@ -22,7 +22,7 @@ import { CoreNetwork } from '@services/network';
import { CoreGroups } from '@services/groups';
import { CoreSites } from '@services/sites';
import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import {

View File

@ -25,7 +25,7 @@ import { CoreFileEntry } from '@services/file-helper';
import { CoreGroups } from '@services/groups';
import { CoreSitesCommonWSOptions, CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import {
CoreStatusWithWarningsWSResponse,
CoreWSExternalFile,

View File

@ -20,7 +20,7 @@ import { CoreNavigator } from '@services/navigator';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { isSafeNumber } from '@/core/utils/types';

View File

@ -19,7 +19,7 @@ import { CoreGrades } from '@features/grades/services/grades';
import { CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
/**

View File

@ -26,7 +26,7 @@ import {
AddonModLessonGetPageDataWSResponse,
} from './lesson';
import { CoreTime } from '@singletons/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { AddonModLessonPageSubtype } from '../constants';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';

View File

@ -19,7 +19,7 @@ import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';

View File

@ -16,7 +16,7 @@ import { Component, OnInit, Optional } from '@angular/core';
import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { AddonModPagePage, AddonModPage } from '../../services/page';
import { AddonModPageHelper } from '../../services/page-helper';
import { ADDON_MOD_PAGE_COMPONENT } from '../../constants';

View File

@ -18,7 +18,7 @@ import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { AddonModQuiz } from '../quiz';
import { AddonModQuizHelper } from '../quiz-helper';

View File

@ -30,7 +30,7 @@ import { CoreQuestionDelegate } from '@features/question/services/question-deleg
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger';

View File

@ -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 { CoreUtils } from '@singletons/utils';
import { CoreEvents } from '@singletons/events';
import {
AddonModScorm,

View File

@ -17,7 +17,7 @@ import { CoreError } from '@classes/errors/error';
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton, Translate } from '@singletons';
import {
AddonModScorm,

View File

@ -18,7 +18,7 @@ import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync';
import { CoreText } from '@singletons/text';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import {

View File

@ -22,7 +22,7 @@ import { CoreFileSession } from '@services/file-session';
import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreFormFields, CoreForms } from '@singletons/form';

View File

@ -20,7 +20,7 @@ import { CoreFile } from '@services/file';
import { CoreFileEntry } from '@services/file-helper';
import { CoreSites } from '@services/sites';
import { CoreText, CoreTextFormat } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton, Translate } from '@singletons';
import { CoreFormFields } from '@singletons/form';
import { AddonModWorkshopAssessmentStrategyFieldErrors } from '../components/assessment-strategy/assessment-strategy';

View File

@ -16,7 +16,7 @@ import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import {
AddonNotifications, AddonNotificationsNotificationMessageFormatted, AddonNotificationsProvider,

View File

@ -15,7 +15,7 @@
import { Injectable } from '@angular/core';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '@features/mainmenu/services/mainmenu-delegate';

View File

@ -15,7 +15,7 @@
import { Injectable } from '@angular/core';
import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';

View File

@ -17,7 +17,7 @@ import { Validators, FormControl } from '@angular/forms';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
/**
* Directive to render a checkbox user profile field.

View File

@ -16,7 +16,7 @@ import { FormControl, Validators } from '@angular/forms';
import { Component } from '@angular/core';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component';

View File

@ -16,7 +16,7 @@ import { Component } from '@angular/core';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
/**
* Directive to render a text user profile field.

View File

@ -18,7 +18,7 @@ import { Subscription } from 'rxjs';
import { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreNavigator } from '@services/navigator';
import { CoreScreen } from '@services/screen';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreRoutedItemsManagerSource } from './routed-items-manager-source';
import { CoreRoutedItemsManager } from './routed-items-manager';

View File

@ -23,7 +23,7 @@ import {
} from '@services/ws';
import { CoreToasts, ToastDuration } from '@services/toasts';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreCacheUpdateFrequency, CoreConstants, MINIMUM_MOODLE_VERSION, MOODLE_RELEASES } from '@/core/constants';
import { CoreError } from '@classes/errors/error';
import { CoreWSError } from '@classes/errors/wserror';

View File

@ -16,7 +16,7 @@ import { Component, Input, OnInit, OnDestroy, ElementRef, ChangeDetectorRef } fr
import { Subject, Subscription } from 'rxjs';
import { auditTime } from 'rxjs/operators';
import { CorePopovers } from '@services/popovers';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons';
import { CoreContextMenuItemComponent } from './context-menu-item';
import { CoreDirectivesRegistry } from '@singletons/directives-registry';

View File

@ -14,7 +14,7 @@
import { Component, Input, OnInit, OnChanges, SimpleChange, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreAnimations } from '@components/animations';
import { Translate } from '@singletons';
import { CoreDirectivesRegistry } from '@singletons/directives-registry';

View File

@ -23,7 +23,7 @@ import {
} from '@angular/core';
import { IonRouterOutlet, IonTabs, ViewDidEnter, ViewDidLeave } from '@ionic/angular';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Params } from '@angular/router';
import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons';
import { StackDidChangeEvent } from '@ionic/angular/common/directives/navigation/stack-utils';

View File

@ -15,7 +15,7 @@
import { Component, Input, Output, OnInit, OnDestroy, ElementRef, EventEmitter, ContentChild, TemplateRef } from '@angular/core';
import { CoreTabBase } from '@classes/tabs';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons';
import { CoreTabsComponent } from './tabs';

View File

@ -15,7 +15,7 @@
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange } from '@angular/core';
import { CoreSiteBasicInfo, CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { USER_PROFILE_PICTURE_UPDATED, CoreUserBasicData } from '@features/user/services/user';
import { CoreNavigator } from '@services/navigator';

View File

@ -15,7 +15,7 @@
import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
import { ScrollDetail } from '@ionic/core';
import { IonContent } from '@ionic/angular';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreMath } from '@singletons/math';
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
import { CoreFormatTextDirective } from './format-text';

View File

@ -16,7 +16,7 @@ import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreLoadingComponent } from '@components/loading/loading';
import { CoreSettingsHelper } from '@features/settings/services/settings-helper';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons';
import { CoreColors } from '@singletons/colors';
import { CoreDirectivesRegistry } from '@singletons/directives-registry';

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Directive, ElementRef, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
/**
* Directive to listen for element resize events.

View File

@ -16,7 +16,6 @@ import { Injectable } from '@angular/core';
import { CoreLogger } from '@singletons/logger';
import { CoreSites } from '@services/sites';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons';
import { CoreText } from '@singletons/text';
import { CorePromiseUtils } from '@singletons/promise-utils';
@ -188,7 +187,7 @@ export class CoreContentLinksDelegateService {
}
// Filter the site IDs using the isEnabled function.
promises.push(CoreUtils.filterEnabledSites(siteIds, isEnabledFn, checkAll).then(async (siteIds) => {
promises.push(CoreSites.filterEnabledSites(siteIds, isEnabledFn, checkAll).then(async (siteIds) => {
if (!siteIds.length) {
// No sites supported, no actions.
return;

View File

@ -19,7 +19,7 @@ import { CoreNetwork } from '@services/network';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreLogger } from '@singletons/logger';

View File

@ -29,7 +29,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { ModalController, NgZone } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { Subscription } from 'rxjs';

View File

@ -16,7 +16,7 @@ import { Component, ViewChild, OnInit, OnDestroy, forwardRef, ChangeDetectorRef
import { IonContent } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreCourses, CoreCourseAnyCourseData } from '@features/courses/services/courses';
import {
CoreCourse,

View File

@ -21,7 +21,7 @@ import { CoreModals } from '@services/modals';
import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
/**
* Page that displays a module preview.

View File

@ -15,7 +15,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreCategoryData, CoreCourseListItem, CoreCourses } from '../../services/courses';
import { Translate } from '@singletons';
import { CoreNavigator } from '@services/navigator';

View File

@ -20,7 +20,7 @@ import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifi
import { CoreLoadings } from '@services/loadings';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
/**

View File

@ -20,7 +20,7 @@ import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifi
import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons';
import { CorePath } from '@singletons/path';
import { CoreCourses } from '../courses';

View File

@ -32,7 +32,7 @@ import { CoreSites } from '@services/sites';
import { CoreFilepool } from '@services/filepool';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreEventFormActionData, CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreEditorOffline } from '../../services/editor-offline';
import { CoreDirectivesRegistry } from '@singletons/directives-registry';

View File

@ -15,7 +15,7 @@
import { Injectable } from '@angular/core';
import { makeSingleton } from '@singletons';
import { CoreEnrolAction, CoreEnrolDelegate, CoreEnrolInfoIcon } from './enrol-delegate';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreEnrol, CoreEnrolEnrolmentMethod } from './enrol';
import { CoreArray } from '@singletons/array';

View File

@ -15,7 +15,7 @@
import { Injectable } from '@angular/core';
import { makeSingleton } from '@singletons';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreEnrolAction, CoreEnrolDelegate } from './enrol-delegate';
import { CoreCacheUpdateFrequency } from '@/core/constants';

View File

@ -24,7 +24,7 @@ import { CoreFilepool } from '@services/filepool';
import { CoreSites } from '@services/sites';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreWSFile, CoreWSFileUploadOptions, CoreWSUploadFileResult } from '@services/ws';
import { makeSingleton, Translate, MediaCapture, Camera } from '@singletons';
import { CoreLogger } from '@singletons/logger';

View File

@ -35,7 +35,7 @@ import {
} from '@features/grades/services/grades';
import { CoreText } from '@singletons/text';
import { CoreUrl } from '@singletons/url';
import { CoreMenuItem, CoreUtils } from '@services/utils/utils';
import { CoreMenuItem, CoreUtils } from '@singletons/utils';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreNavigator } from '@services/navigator';
import { makeSingleton, Translate } from '@singletons';

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreH5P } from '@features/h5p/services/h5p';
import { Translate } from '@singletons';
import { CoreH5PCore, CoreH5PLibraryData, CoreH5PLibraryAddonData, CoreH5PContentDepsTreeDependency } from './core';

View File

@ -16,7 +16,7 @@ import { Md5 } from 'ts-md5/dist/md5';
import { CoreSites } from '@services/sites';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreH5P } from '@features/h5p/services/h5p';
import { CoreH5PFileStorage } from './file-storage';
import { CoreH5PFramework } from './framework';

View File

@ -17,7 +17,6 @@ import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
import { CoreFile, CoreFileProvider } from '@services/file';
import { CoreSites } from '@services/sites';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreUtils } from '@services/utils/utils';
import { CoreH5P } from '../services/h5p';
import { CoreH5PCore, CoreH5PDisplayOptions, CoreH5PLocalization } from './core';
import { CoreError } from '@classes/errors/error';
@ -56,10 +55,8 @@ export class CoreH5PHelper {
const config: CoreH5PDisplayOptions = {
export: false, // Don't allow downloading in the app.
embed: false, // Don't display the embed button in the app.
copyright: CoreUtils.notNullOrUndefined(displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT]) ?
displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT] : false,
icon: CoreUtils.notNullOrUndefined(displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_ABOUT]) ?
displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_ABOUT] : false,
copyright: displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT] ?? false,
icon: displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_ABOUT] ?? false,
};
config.frame = config.copyright || config.export || config.embed;

View File

@ -15,7 +15,7 @@
import { CoreFile } from '@services/file';
import { CoreSites } from '@services/sites';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreH5P } from '../services/h5p';
import { CoreH5PCore, CoreH5PDisplayOptions, CoreH5PContentData, CoreH5PDependenciesFiles } from './core';
import { CoreH5PCoreSettings, CoreH5PHelper } from './helper';

View File

@ -18,7 +18,7 @@ import { FormBuilder, FormGroup, ValidatorFn, AbstractControl, ValidationErrors
import { CoreNetwork } from '@services/network';
import { CoreConfig } from '@services/config';
import { CoreSites, CoreSiteCheckResponse, CoreLoginSiteInfo, CoreSitesDemoSiteData } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreDomUtils } from '@services/utils/dom';
import {
CoreLoginHelper,

View File

@ -21,7 +21,7 @@ import { CoreEvents, CoreEventObserver } from '@singletons/events';
import { CoreMainMenu } from '../../services/mainmenu';
import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from '../../services/mainmenu-delegate';
import { Router } from '@singletons';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreAriaRoleTab, CoreAriaRoleTabFindable } from '@classes/aria-role-tab';
import { CoreNavigator } from '@services/navigator';
import { filter } from 'rxjs/operators';

View File

@ -20,7 +20,7 @@ import { CoreAppDB } from '@services/app-db';
import { CoreSites } from '@services/sites';
import { CorePushNotificationsDelegate } from './push-delegate';
import { CoreLocalNotifications } from '@services/local-notifications';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreText } from '@singletons/text';
import { CoreConfig } from '@services/config';
import { CoreConstants } from '@/core/constants';

View File

@ -21,7 +21,7 @@ import { CoreFilepool } from '@services/filepool';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreWSFile } from '@services/ws';
import { makeSingleton, Translate } from '@singletons';
import { CoreQuestion, CoreQuestionProvider, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from './question';

View File

@ -16,7 +16,7 @@ import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild } from '@angular
import { CoreDomUtils } from '@services/utils/dom';
import { CoreSearchGlobalSearchResultsSource } from '@features/search/classes/global-search-results-source';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { Translate } from '@singletons';
import { CoreUrl } from '@singletons/url';

View File

@ -29,7 +29,7 @@ import {
CoreSitePluginsCourseModuleHandlerData,
} from '@features/siteplugins/services/siteplugins';
import { CoreModals } from '@services/modals';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreSitePluginsPluginContentComponent, CoreSitePluginsPluginContentLoadedData } from '../plugin-content/plugin-content';
import { CoreCompileHtmlComponentModule } from '@features/compile/components/compile-html/compile-html.module';
import { CoreCourseComponentsModule } from '@features/course/components/components.module';

View File

@ -16,7 +16,7 @@ import { Component, OnInit, ViewChild } from '@angular/core';
import { CoreSitePluginsPluginContentComponent } from '@features/siteplugins/components/plugin-content/plugin-content';
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreNavigator } from '@services/navigator';
import { CoreSharedModule } from '@/core/shared.module';

View File

@ -17,7 +17,7 @@ import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
import { CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
import { CanLeave } from '@guards/can-leave';
import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreSitePluginsPluginContentComponent } from '../../components/plugin-content/plugin-content';
import { CoreSharedModule } from '@/core/shared.module';

View File

@ -22,7 +22,7 @@ import { CoreFilepool } from '@services/filepool';
import { CoreLang, CoreLangFormat } from '@services/lang';
import { CoreSites } from '@services/sites';
import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton } from '@singletons';
import { CoreEvents } from '@singletons/events';

View File

@ -18,7 +18,7 @@ import { CoreLang } from '@services/lang';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user';
import { CoreUserProfileFieldDelegate } from '@features/user/services/user-profile-field-delegate';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { ContextLevel } from '@/core/constants';
import { toBoolean } from '@/core/transforms/boolean';

View File

@ -21,7 +21,7 @@ import { CoreConstants } from '@/core/constants';
import { CoreMainMenu } from '@features/mainmenu/services/mainmenu';
import { CoreObject } from '@singletons/object';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
import { CoreText } from '@singletons/text';
import { makeSingleton, NavController, Router } from '@singletons';

View File

@ -21,7 +21,6 @@ import { CoreEvents } from '@singletons/events';
import { CoreWS } from '@services/ws';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreConstants, MINIMUM_MOODLE_VERSION, MOODLE_RELEASES } from '@/core/constants';
import {
CoreSite,
@ -466,7 +465,7 @@ export class CoreSitesProvider {
if (error.debug?.code === 'codingerror') {
// This could be caused by a redirect. Check if it's the case.
const redirect = await CoreUtils.checkRedirect(siteUrl);
const redirect = await CoreRedirects.checkRedirect(siteUrl);
options.message = Translate.instant('core.siteunavailablehelp', { site: siteUrl });
@ -557,9 +556,9 @@ export class CoreSitesProvider {
return this.getUserToken(siteUrl, username, password, service, true);
}
if (data.errorcode == 'missingparam') {
if (data.errorcode === 'missingparam') {
// It seems the server didn't receive all required params, it could be due to a redirect.
const redirect = await CoreUtils.checkRedirect(loginUrl);
const redirect = await CoreRedirects.checkRedirect(loginUrl);
if (redirect) {
throw this.createCannotConnectLoginError(siteUrl, {
@ -2217,6 +2216,47 @@ export class CoreSitesProvider {
this.afterLoginNavigationQueue = [];
}
/**
* Filter the list of site IDs based on a isEnabled function.
*
* @param siteIds Site IDs to filter.
* @param isEnabledFn Function to call for each site. It receives a siteId param and all the params sent to this function
* after 'checkAll'.
* @param checkAll True if it should check all the sites, false if it should check only 1 and treat them all
* depending on this result.
* @returns Promise resolved with the list of enabled sites.
*/
async filterEnabledSites<P extends unknown[]>(
siteIds: string[],
isEnabledFn: (siteId: string, ...args: P) => boolean | Promise<boolean>,
checkAll?: boolean,
...args: P
): Promise<string[]> {
const promises: Promise<false | number>[] = [];
const enabledSites: string[] = [];
for (const i in siteIds) {
const siteId = siteIds[i];
const pushIfEnabled = enabled => enabled && enabledSites.push(siteId);
if (checkAll || !promises.length) {
promises.push(
Promise
.resolve(isEnabledFn(siteId, ...args))
.then(pushIfEnabled),
);
}
}
await CorePromiseUtils.allPromisesIgnoringErrors(promises);
if (!checkAll) {
// Checking 1 was enough, so it will either return all the sites or none.
return enabledSites.length ? siteIds : [];
}
return enabledSites;
}
}
export const CoreSites = makeSingleton(CoreSitesProvider);

View File

@ -16,10 +16,9 @@ import { Injectable } from '@angular/core';
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
import { CoreFileUtils } from '@singletons/file-utils';
import { CoreWS } from '@services/ws';
import { CoreRedirects } from '@singletons/redirects';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { makeSingleton, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { makeSingleton } from '@singletons';
import { CoreFileEntry } from '@services/file-helper';
import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreArray } from '@singletons/array';
@ -31,8 +30,9 @@ import { CorePromiseUtils, OrderedPromiseData } from '@singletons/promise-utils'
import { CoreOpener, CoreOpenerOpenFileOptions, CoreOpenerOpenInBrowserOptions } from '@singletons/opener';
import { CoreCountries, CoreCountry } from '@singletons/countries';
import { CoreObject } from '@singletons/object';
export type TreeNode<T> = T & { children: TreeNode<T>[] };
import { CoreSites } from '@services/sites';
import { CoreMenuItem, CoreUtils as CoreUtilsSingleton, TreeNode } from '@singletons/utils';
import { CoreWSError } from '@classes/errors/wserror';
/*
* "Utils" service with helper functions.
@ -40,15 +40,6 @@ export type TreeNode<T> = T & { children: TreeNode<T>[] };
@Injectable({ providedIn: 'root' })
export class CoreUtilsProvider {
protected readonly DONT_CLONE = ['[object FileEntry]', '[object DirectoryEntry]', '[object DOMFileSystem]'];
protected logger: CoreLogger;
protected uniqueIds: {[name: string]: number} = {};
constructor() {
this.logger = CoreLogger.getInstance('CoreUtilsProvider');
}
/**
* Given an error, add an extra warning to the error message and return the new error message.
*
@ -158,35 +149,10 @@ export class CoreUtilsProvider {
*
* @param url The URL to check.
* @returns Promise resolved with boolean_ whether there is a redirect.
* @deprecated since 5.0. Use CoreRedirects.checkRedirect instead.
*/
async checkRedirect(url: string): Promise<boolean> {
if (!window.fetch) {
// Cannot check if there is a redirect, assume it's false.
return false;
}
const initOptions: RequestInit = { redirect: 'follow' };
// Some browsers implement fetch but no AbortController.
const controller = AbortController ? new AbortController() : false;
if (controller) {
initOptions.signal = controller.signal;
}
try {
const response = await CorePromiseUtils.timeoutPromise(window.fetch(url, initOptions), CoreWS.getRequestTimeout());
return response.redirected;
} catch (error) {
if (error.timeout && controller) {
// Timeout, abort the request.
controller.abort();
}
// There was a timeout, cannot determine if there's a redirect. Assume it's false.
return false;
}
return CoreRedirects.checkRedirect(url);
}
/**
@ -224,44 +190,10 @@ export class CoreUtilsProvider {
* @param source The variable to clone.
* @param level Depth we are right now inside a cloned object. It's used to prevent reaching max call stack size.
* @returns Cloned variable.
* @deprecated since 5.0. Use CoreUtils.clone instead.
*/
clone<T>(source: T, level: number = 0): T {
if (level >= 20) {
// Max 20 levels.
this.logger.error('Max depth reached when cloning object.', source);
return source;
}
if (CoreFileUtils.valueIsFileEntry(source)) {
// Don't clone FileEntry. It has a lot of depth and they shouldn't be modified.
return source;
} else if (Array.isArray(source)) {
// Clone the array and all the entries.
const newArray = [] as unknown as T;
for (let i = 0; i < source.length; i++) {
newArray[i] = this.clone(source[i], level + 1);
}
return newArray;
} else if (CoreObject.isObject(source)) {
// Check if the object shouldn't be copied.
if (source.toString && this.DONT_CLONE.indexOf(source.toString()) != -1) {
// Object shouldn't be copied, return it as it is.
return source;
}
// Clone the object and all the subproperties.
const newObject = {} as T;
for (const name in source) {
newObject[name] = this.clone(source[name], level + 1);
}
return newObject;
} else {
// Primitive type or unknown, return it as it is.
return source;
}
return CoreUtilsSingleton.clone(source, level);
}
/**
@ -275,7 +207,7 @@ export class CoreUtilsProvider {
copyProperties(from: Record<string, unknown>, to: Record<string, unknown>, clone: boolean = true): void {
for (const name in from) {
if (clone) {
to[name] = this.clone(from[name]);
to[name] = CoreUtilsSingleton.clone(from[name]);
} else {
to[name] = from[name];
}
@ -363,6 +295,7 @@ export class CoreUtilsProvider {
* @param checkAll True if it should check all the sites, false if it should check only 1 and treat them all
* depending on this result.
* @returns Promise resolved with the list of enabled sites.
* @deprecated since 5.0. Use CoreSites.filterEnabledSites instead.
*/
async filterEnabledSites<P extends unknown[]>(
siteIds: string[],
@ -370,29 +303,7 @@ export class CoreUtilsProvider {
checkAll?: boolean,
...args: P
): Promise<string[]> {
const promises: Promise<false | number>[] = [];
const enabledSites: string[] = [];
for (const i in siteIds) {
const siteId = siteIds[i];
const pushIfEnabled = enabled => enabled && enabledSites.push(siteId);
if (checkAll || !promises.length) {
promises.push(
Promise
.resolve(isEnabledFn(siteId, ...args))
.then(pushIfEnabled),
);
}
}
await CorePromiseUtils.allPromisesIgnoringErrors(promises);
if (!checkAll) {
// Checking 1 was enough, so it will either return all the sites or none.
return enabledSites.length ? siteIds : [];
} else {
return enabledSites;
}
return CoreSites.filterEnabledSites(siteIds, isEnabledFn, checkAll, ...args);
}
/**
@ -401,17 +312,10 @@ export class CoreUtilsProvider {
*
* @param float The float to print.
* @returns Locale float.
* @deprecated since 5.0. Use CoreUtils.formatFloat on singletons instead.
*/
formatFloat(float: unknown): string {
if (float === undefined || float === null || typeof float == 'boolean') {
return '';
}
const localeSeparator = Translate.instant('core.decsep');
const floatString = String(float);
return floatString.replace('.', localeSeparator);
return CoreUtilsSingleton.formatFloat(float);
}
/**
@ -425,6 +329,7 @@ export class CoreUtilsProvider {
* @param rootParentId The id of the root.
* @param maxDepth Max Depth to convert to tree. Children found will be in the last level of depth.
* @returns Array with the formatted tree, children will be on each node under children field.
* @deprecated since 5.0. Use CoreUtils.formatTree on singletons instead.
*/
formatTree<T>(
list: T[],
@ -433,67 +338,7 @@ export class CoreUtilsProvider {
rootParentId: number = 0,
maxDepth: number = 5,
): TreeNode<T>[] {
const map = {};
const mapDepth = {};
const tree: TreeNode<T>[] = [];
// Create a map first to avoid problems with not sorted.
list.forEach((node: TreeNode<T>, index): void => {
const id = node[idFieldName];
if (id === undefined) {
this.logger.error(`Node with incorrect ${idFieldName}:${id} found on formatTree`);
}
if (node.children === undefined) {
node.children = [];
}
map[id] = index;
});
list.forEach((node: TreeNode<T>): void => {
const id = node[idFieldName];
const parent = node[parentFieldName];
if (id === undefined || parent === undefined) {
this.logger.error(`Node with incorrect ${idFieldName}:${id} or ${parentFieldName}:${parent} found on formatTree`);
}
// Use map to look-up the parents.
if (parent !== rootParentId) {
const parentNode = list[map[parent]] as TreeNode<T>;
if (parentNode) {
if (mapDepth[parent] == maxDepth) {
// Reached max level of depth. Proceed with flat order. Find parent object of the current node.
const parentOfParent = parentNode[parentFieldName];
if (parentOfParent) {
// This element will be the child of the node that is two levels up the hierarchy
// (i.e. the child of node.parent.parent).
(list[map[parentOfParent]] as TreeNode<T>).children.push(node);
// Assign depth level to the same depth as the parent (i.e. max depth level).
mapDepth[id] = mapDepth[parent];
// Change the parent to be the one that is two levels up the hierarchy.
node[parentFieldName] = parentOfParent;
} else {
this.logger.error(`Node parent of parent:${parentOfParent} not found on formatTree`);
}
} else {
parentNode.children.push(node);
// Increase the depth level.
mapDepth[id] = mapDepth[parent] + 1;
}
} else {
this.logger.error(`Node parent:${parent} not found on formatTree`);
}
} else {
tree.push(node);
// Root elements are the first elements in the tree structure, therefore have the depth level 1.
mapDepth[id] = 1;
}
});
return tree;
return CoreUtilsSingleton.formatTree(list, parentFieldName, idFieldName, rootParentId, maxDepth);
}
/**
@ -545,13 +390,10 @@ export class CoreUtilsProvider {
*
* @param name The name to get the ID for.
* @returns Unique ID.
* @deprecated since 5.0. Use CoreUtils.getUniqueId singleton instead.
*/
getUniqueId(name: string): number {
if (!this.uniqueIds[name]) {
this.uniqueIds[name] = 0;
}
return ++this.uniqueIds[name];
return CoreUtilsSingleton.getUniqueId(name);
}
/**
@ -615,10 +457,11 @@ export class CoreUtilsProvider {
*
* @param value Value to check.
* @returns Whether the value is false, 0 or "0".
* @deprecated since 5.0. Use CoreUtils.isFalseOrZero singleton instead.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isFalseOrZero(value: any): boolean {
return value !== undefined && (value === false || value === 'false' || parseInt(value, 10) === 0);
return CoreUtilsSingleton.isFalseOrZero(value);
}
/**
@ -626,10 +469,11 @@ export class CoreUtilsProvider {
*
* @param value Value to check.
* @returns Whether the value is true, 1 or "1".
* @deprecated since 5.0. Use CoreUtils.isTrueOrOne singleton instead.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isTrueOrOne(value: any): boolean {
return value !== undefined && (value === true || value === 'true' || parseInt(value, 10) === 1);
return CoreUtilsSingleton.isTrueOrOne(value);
}
/**
@ -641,18 +485,7 @@ export class CoreUtilsProvider {
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isWebServiceError(error: any): boolean {
return error && (
error.warningcode !== undefined ||
(
error.errorcode !== undefined && error.errorcode != 'userdeleted' && error.errorcode != 'upgraderunning' &&
error.errorcode != 'forcepasswordchangenotice' && error.errorcode != 'usernotfullysetup' &&
error.errorcode != 'sitepolicynotagreed' && error.errorcode != 'sitemaintenance' &&
error.errorcode != 'wsaccessusersuspended' && error.errorcode != 'wsaccessuserdeleted' &&
// eslint-disable-next-line deprecation/deprecation
!this.isExpiredTokenError(error)
) ||
error.status && error.status >= 400 // CoreHttpError, assume status 400 and above are like WebService errors.
);
return CoreWSError.isWebServiceError(error);
}
/**
@ -664,8 +497,7 @@ export class CoreUtilsProvider {
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isExpiredTokenError(error: any): boolean {
return error.errorcode === 'invalidtoken' ||
(error.errorcode === 'accessexception' && error.message.includes('Invalid token - token expired'));
return CoreWSError.isExpiredTokenError(error);
}
/**
@ -677,6 +509,7 @@ export class CoreUtilsProvider {
* @param separator The separator used within the list string. Default ','.
* @param defaultValue Element that will become default option value. Default 0.
* @returns The now assembled array
* @deprecated since 5.0. Use CoreUtils.makeMenuFromList singleton instead.
*/
makeMenuFromList<T>(
list: string,
@ -684,20 +517,7 @@ export class CoreUtilsProvider {
separator: string = ',',
defaultValue?: T,
): CoreMenuItem<T>[] {
// Split and format the list.
const split = list.split(separator).map((label, index) => ({
label: label.trim(),
value: index + 1,
})) as { label: string; value: T | number }[];
if (defaultLabel) {
split.unshift({
label: defaultLabel,
value: defaultValue || 0,
});
}
return split;
return CoreUtilsSingleton.makeMenuFromList(list, defaultLabel, separator, defaultValue);
}
/**
@ -718,6 +538,7 @@ export class CoreUtilsProvider {
*
* @param value Value to check.
* @returns True if not null and not undefined.
* @deprecated since 5.0. Use ?? instead.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
notNullOrUndefined(value: any): boolean {
@ -967,39 +788,10 @@ export class CoreUtilsProvider {
* @param localeFloat Locale aware float representation.
* @param strict If true, then check the input and return false if it is not a valid number.
* @returns False if bad format, empty string if empty value or the parsed float if not.
* @deprecated since 5.0. Use CoreUtils.unformatFloat on singletons instead.
*/
unformatFloat(localeFloat: string | number | null | undefined, strict?: boolean): false | '' | number {
// Bad format on input type number.
if (localeFloat === undefined) {
return false;
}
// Empty (but not zero).
if (localeFloat == null) {
return '';
}
// Convert float to string.
localeFloat = String(localeFloat);
localeFloat = localeFloat.trim();
if (localeFloat == '') {
return '';
}
localeFloat = localeFloat.replace(' ', ''); // No spaces - those might be used as thousand separators.
localeFloat = localeFloat.replace(Translate.instant('core.decsep'), '.');
// Use Number instead of parseFloat because the latter truncates the number when it finds ",", while Number returns NaN.
// If the number still has "," then it means it's not a valid separator.
const parsedFloat = Number(localeFloat);
// Bad format.
if (strict && (!isFinite(parsedFloat) || isNaN(parsedFloat))) {
return false;
}
return parsedFloat;
return CoreUtilsSingleton.unformatFloat(localeFloat, strict);
}
/**
@ -1020,17 +812,10 @@ export class CoreUtilsProvider {
* @param fn Function to debounce.
* @param delay Time that must pass until the function is called.
* @returns Debounced function.
* @deprecated since 5.0. Use CoreUtils.debounce on singletons instead.
*/
debounce<T extends unknown[]>(fn: (...args: T) => unknown, delay: number): (...args: T) => void {
let timeoutID: number;
const debounced = (...args: T): void => {
clearTimeout(timeoutID);
timeoutID = window.setTimeout(() => fn.apply(null, args), delay);
};
return debounced;
return CoreUtilsSingleton.debounce(fn, delay);
}
/**
@ -1039,23 +824,10 @@ export class CoreUtilsProvider {
* @param fn Function to throttle.
* @param duration Time that must pass until the function is called.
* @returns Throttled function.
* @deprecated since 5.0. Use CoreUtils.throttle on singletons instead.
*/
throttle<T extends unknown[]>(fn: (...args: T) => unknown, duration: number): (...args: T) => void {
let shouldWait = false;
const throttled = (...args: T): void => {
if (!shouldWait) {
fn.apply(null, args);
shouldWait = true;
setTimeout(() => {
shouldWait = false;
}, duration);
}
};
return throttled;
return CoreUtilsSingleton.throttle(fn, duration);
}
/**
@ -1182,14 +954,6 @@ export class CoreUtilsProvider {
export const CoreUtils = makeSingleton(CoreUtilsProvider);
/**
* Menu item.
*/
export type CoreMenuItem<T = number> = {
label: string;
value: T | number;
};
/**
* Options for waiting.
*

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreUtils } from '@services/utils/utils';
import { CoreUtils } from '@singletons/utils';
import { CoreEventObserver } from '@singletons/events';
import { CorePlatform } from '@services/platform';
import { CoreWait } from './wait';

View File

@ -15,6 +15,8 @@
import { CoreRedirectPayload } from '@services/navigator';
import { CoreLogger } from './logger';
import { CoreObject } from './object';
import { CoreWS } from '@services/ws';
import { CorePromiseUtils } from './promise-utils';
/**
* Singleton with helper functions to manage redirects.
@ -119,6 +121,42 @@ export class CoreRedirects {
}
}
/**
* Check if a URL has a redirect.
*
* @param url The URL to check.
* @returns Promise resolved with boolean_ whether there is a redirect.
*/
static async checkRedirect(url: string): Promise<boolean> {
if (!window.fetch) {
// Cannot check if there is a redirect, assume it's false.
return false;
}
const initOptions: RequestInit = { redirect: 'follow' };
// Some browsers implement fetch but no AbortController.
const controller = AbortController ? new AbortController() : false;
if (controller) {
initOptions.signal = controller.signal;
}
try {
const response = await CorePromiseUtils.timeoutPromise(window.fetch(url, initOptions), CoreWS.getRequestTimeout());
return response.redirected;
} catch (error) {
if (error.timeout && controller) {
// Timeout, abort the request.
controller.abort();
}
// There was a timeout, cannot determine if there's a redirect. Assume it's false.
return false;
}
}
}
/**

View File

@ -0,0 +1,348 @@
// (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 { Translate } from '@singletons';
import { CoreLogger } from './logger';
import { CoreObject } from './object';
import { CoreFileUtils } from './file-utils';
/**
* Singleton with utils helper functions.
*/
export class CoreUtils {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
protected static readonly DONT_CLONE = ['[object FileEntry]', '[object DirectoryEntry]', '[object DOMFileSystem]'];
protected static logger = CoreLogger.getInstance('CoreUtils');
protected static uniqueIds: {[name: string]: number} = {};
/**
* Clone a variable. It should be an object, array or primitive type.
*
* @param source The variable to clone.
* @param level Depth we are right now inside a cloned object. It's used to prevent reaching max call stack size.
* @returns Cloned variable.
*/
static clone<T>(source: T, level: number = 0): T {
if (level >= 20) {
// Max 20 levels.
CoreUtils.logger.error('Max depth reached when cloning object.', source);
return source;
}
if (CoreFileUtils.valueIsFileEntry(source)) {
// Don't clone FileEntry. It has a lot of depth and they shouldn't be modified.
return source;
} else if (Array.isArray(source)) {
// Clone the array and all the entries.
const newArray = [] as unknown as T;
for (let i = 0; i < source.length; i++) {
newArray[i] = CoreUtils.clone(source[i], level + 1);
}
return newArray;
} else if (CoreObject.isObject(source)) {
// Check if the object shouldn't be copied.
if (source.toString && CoreUtils.DONT_CLONE.indexOf(source.toString()) != -1) {
// Object shouldn't be copied, return it as it is.
return source;
}
// Clone the object and all the subproperties.
const newObject = {} as T;
for (const name in source) {
newObject[name] = CoreUtils.clone(source[name], level + 1);
}
return newObject;
} else {
// Primitive type or unknown, return it as it is.
return source;
}
}
/**
* Given a float, prints it nicely. Localized floats must not be used in calculations!
* Based on Moodle's format_float.
*
* @param float The float to print.
* @returns Locale float.
*/
static formatFloat(float: unknown): string {
if (float === undefined || float === null || typeof float == 'boolean') {
return '';
}
const localeSeparator = Translate.instant('core.decsep');
const floatString = String(float);
return floatString.replace('.', localeSeparator);
}
/**
* Returns a tree formatted from a plain list.
* List has to be sorted by depth to allow this function to work correctly. Errors can be thrown if a child node is
* processed before a parent node.
*
* @param list List to format.
* @param parentFieldName Name of the parent field to match with children.
* @param idFieldName Name of the children field to match with parent.
* @param rootParentId The id of the root.
* @param maxDepth Max Depth to convert to tree. Children found will be in the last level of depth.
* @returns Array with the formatted tree, children will be on each node under children field.
*/
static formatTree<T>(
list: T[],
parentFieldName: string = 'parent',
idFieldName: string = 'id',
rootParentId: number = 0,
maxDepth: number = 5,
): TreeNode<T>[] {
const map = {};
const mapDepth = {};
const tree: TreeNode<T>[] = [];
// Create a map first to avoid problems with not sorted.
list.forEach((node: TreeNode<T>, index): void => {
const id = node[idFieldName];
if (id === undefined) {
CoreUtils.logger.error(`Node with incorrect ${idFieldName}:${id} found on formatTree`);
}
if (node.children === undefined) {
node.children = [];
}
map[id] = index;
});
list.forEach((node: TreeNode<T>): void => {
const id = node[idFieldName];
const parent = node[parentFieldName];
if (id === undefined || parent === undefined) {
CoreUtils.logger.error(`Node with incorrect ${idFieldName}:${id}
or ${parentFieldName}:${parent} found on formatTree`);
}
// Use map to look-up the parents.
if (parent !== rootParentId) {
const parentNode = list[map[parent]] as TreeNode<T>;
if (parentNode) {
if (mapDepth[parent] == maxDepth) {
// Reached max level of depth. Proceed with flat order. Find parent object of the current node.
const parentOfParent = parentNode[parentFieldName];
if (parentOfParent) {
// This element will be the child of the node that is two levels up the hierarchy
// (i.e. the child of node.parent.parent).
(list[map[parentOfParent]] as TreeNode<T>).children.push(node);
// Assign depth level to the same depth as the parent (i.e. max depth level).
mapDepth[id] = mapDepth[parent];
// Change the parent to be the one that is two levels up the hierarchy.
node[parentFieldName] = parentOfParent;
} else {
CoreUtils.logger.error(`Node parent of parent:${parentOfParent} not found on formatTree`);
}
} else {
parentNode.children.push(node);
// Increase the depth level.
mapDepth[id] = mapDepth[parent] + 1;
}
} else {
CoreUtils.logger.error(`Node parent:${parent} not found on formatTree`);
}
} else {
tree.push(node);
// Root elements are the first elements in the tree structure, therefore have the depth level 1.
mapDepth[id] = 1;
}
});
return tree;
}
/**
* Get a unique ID for a certain name.
*
* @param name The name to get the ID for.
* @returns Unique ID.
*/
static getUniqueId(name: string): number {
if (!CoreUtils.uniqueIds[name]) {
CoreUtils.uniqueIds[name] = 0;
}
return ++CoreUtils.uniqueIds[name];
}
/**
* Return true if the param is false (bool), 0 (number) or "0" (string).
*
* @param value Value to check.
* @returns Whether the value is false, 0 or "0".
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static isFalseOrZero(value: any): boolean {
return value !== undefined && (value === false || value === 'false' || parseInt(value, 10) === 0);
}
/**
* Return true if the param is true (bool), 1 (number) or "1" (string).
*
* @param value Value to check.
* @returns Whether the value is true, 1 or "1".
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static isTrueOrOne(value: any): boolean {
return value !== undefined && (value === true || value === 'true' || parseInt(value, 10) === 1);
}
/**
* Given a list (e.g. a,b,c,d,e) this function returns an array of 1->a, 2->b, 3->c etc.
* Taken from make_menu_from_list on moodlelib.php (not the same but similar).
*
* @param list The string to explode into array bits
* @param defaultLabel Element that will become default option, if not defined, it won't be added.
* @param separator The separator used within the list string. Default ','.
* @param defaultValue Element that will become default option value. Default 0.
* @returns The now assembled array
*/
static makeMenuFromList<T>(
list: string,
defaultLabel?: string,
separator: string = ',',
defaultValue?: T,
): CoreMenuItem<T>[] {
// Split and format the list.
const split = list.split(separator).map((label, index) => ({
label: label.trim(),
value: index + 1,
})) as { label: string; value: T | number }[];
if (defaultLabel) {
split.unshift({
label: defaultLabel,
value: defaultValue || 0,
});
}
return split;
}
/**
* Converts locale specific floating point/comma number back to a standard float number.
* Do NOT try to do any math operations before this conversion on any user submitted floats!
* Based on Moodle's unformat_float function.
*
* @param localeFloat Locale aware float representation.
* @param strict If true, then check the input and return false if it is not a valid number.
* @returns False if bad format, empty string if empty value or the parsed float if not.
*/
static unformatFloat(localeFloat: string | number | null | undefined, strict?: boolean): false | '' | number {
// Bad format on input type number.
if (localeFloat === undefined) {
return false;
}
// Empty (but not zero).
if (localeFloat == null) {
return '';
}
// Convert float to string.
localeFloat = String(localeFloat);
localeFloat = localeFloat.trim();
if (localeFloat == '') {
return '';
}
localeFloat = localeFloat.replace(' ', ''); // No spaces - those might be used as thousand separators.
localeFloat = localeFloat.replace(Translate.instant('core.decsep'), '.');
// Use Number instead of parseFloat because the latter truncates the number when it finds ",", while Number returns NaN.
// If the number still has "," then it means it's not a valid separator.
const parsedFloat = Number(localeFloat);
// Bad format.
if (strict && (!isFinite(parsedFloat) || isNaN(parsedFloat))) {
return false;
}
return parsedFloat;
}
/**
* Debounce a function so consecutive calls are ignored until a certain time has passed since the last call.
*
* @param fn Function to debounce.
* @param delay Time that must pass until the function is called.
* @returns Debounced function.
*/
static debounce<T extends unknown[]>(fn: (...args: T) => unknown, delay: number): (...args: T) => void {
let timeoutID: number;
const debounced = (...args: T): void => {
clearTimeout(timeoutID);
timeoutID = window.setTimeout(() => fn.apply(null, args), delay);
};
return debounced;
}
/**
* Throttle a function so consecutive calls are ignored until a certain time has passed since the last executed call.
*
* @param fn Function to throttle.
* @param duration Time that must pass until the function is called.
* @returns Throttled function.
*/
static throttle<T extends unknown[]>(fn: (...args: T) => unknown, duration: number): (...args: T) => void {
let shouldWait = false;
const throttled = (...args: T): void => {
if (!shouldWait) {
fn.apply(null, args);
shouldWait = true;
setTimeout(() => {
shouldWait = false;
}, duration);
}
};
return throttled;
}
}
export type TreeNode<T> = T & { children: TreeNode<T>[] };
/**
* Menu item.
*/
export type CoreMenuItem<T = number> = {
label: string;
value: T | number;
};

View File

@ -15,7 +15,7 @@
import { CoreColorScheme, CoreZoomLevel } from '@features/settings/services/settings-helper';
import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mainmenu';
import { CoreLoginSiteInfo, CoreSitesDemoSiteData } from '@services/sites';
import { OpenFileAction } from '@services/utils/utils';
import { OpenFileAction } from '@singletons/opener';
import { CoreLoginSiteFinderSettings, CoreLoginSiteSelectorListMethod } from '@features/login/services/login-helper';
import { CoreDatabaseConfiguration } from '@classes/database/database-table';
import { ToastDuration } from '@services/toasts';