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 { Injectable } from '@angular/core';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate'; import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { AddonBadges } from '../badges'; import { AddonBadges } from '../badges';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ import { CoreMainMenuHandler, CoreMainMenuHandlerToDisplay } from '@features/mai
import { CoreCronHandler } from '@services/cron'; import { CoreCronHandler } from '@services/cron';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { import {
CorePushNotificationsNotificationBasicData, CorePushNotificationsNotificationBasicData,
} from '@features/pushnotifications/services/pushnotifications'; } 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 { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { AddonMessages } from '../messages'; import { AddonMessages } from '../messages';
import { AddonMessagesMainMenuHandlerService } from './mainmenu'; import { AddonMessagesMainMenuHandlerService } from './mainmenu';

View File

@ -37,7 +37,7 @@ import { CoreTabsComponent } from '@components/tabs/tabs';
import { CoreTabComponent } from '@components/tabs/tab'; import { CoreTabComponent } from '@components/tabs/tab';
import { CoreSplitViewComponent } from '@components/split-view/split-view'; import { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreGradesFormattedItem, CoreGradesHelper } from '@features/grades/services/grades-helper'; 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 { AddonModAssignHelper, AddonModAssignSubmissionFormatted } from '../../services/assign-helper';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { Translate } from '@singletons'; 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 { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { AddonModAssign } from '../assign'; import { AddonModAssign } from '../assign';
import { ADDON_MOD_ASSIGN_FEATURE_NAME } from '../../constants'; 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 { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreForms } from '@singletons/form'; import { CoreForms } from '@singletons/form';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { AddonModDataComponentsCompileModule } from '../../components/components-compile.module'; import { AddonModDataComponentsCompileModule } from '../../components/components-compile.module';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ import { CoreNavigator } from '@services/navigator';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate'; import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { isSafeNumber } from '@/core/utils/types'; 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 { CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate'; import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
/** /**

View File

@ -26,7 +26,7 @@ import {
AddonModLessonGetPageDataWSResponse, AddonModLessonGetPageDataWSResponse,
} from './lesson'; } from './lesson';
import { CoreTime } from '@singletons/time'; import { CoreTime } from '@singletons/time';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { AddonModLessonPageSubtype } from '../constants'; import { AddonModLessonPageSubtype } from '../constants';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; 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 { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; 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 { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { AddonModPagePage, AddonModPage } from '../../services/page'; import { AddonModPagePage, AddonModPage } from '../../services/page';
import { AddonModPageHelper } from '../../services/page-helper'; import { AddonModPageHelper } from '../../services/page-helper';
import { ADDON_MOD_PAGE_COMPONENT } from '../../constants'; 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 { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { AddonModQuiz } from '../quiz'; import { AddonModQuiz } from '../quiz';
import { AddonModQuizHelper } from '../quiz-helper'; 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 { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
import { CoreTimeUtils } from '@services/utils/time'; 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 { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { import {
AddonModScorm, AddonModScorm,

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ import { CoreFile } from '@services/file';
import { CoreFileEntry } from '@services/file-helper'; import { CoreFileEntry } from '@services/file-helper';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreText, CoreTextFormat } from '@singletons/text'; import { CoreText, CoreTextFormat } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreFormFields } from '@singletons/form'; import { CoreFormFields } from '@singletons/form';
import { AddonModWorkshopAssessmentStrategyFieldErrors } from '../components/assessment-strategy/assessment-strategy'; 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 { Subscription } from 'rxjs';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { import {
AddonNotifications, AddonNotificationsNotificationMessageFormatted, AddonNotificationsProvider, AddonNotifications, AddonNotificationsNotificationMessageFormatted, AddonNotificationsProvider,

View File

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

View File

@ -15,7 +15,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate'; import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; 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 { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component'; 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. * 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 { Component } from '@angular/core';
import { CoreTimeUtils } from '@services/utils/time'; 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 { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user'; import { CoreUserProfileField } from '@features/user/services/user';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component'; 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 { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component'; 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. * 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 { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreRoutedItemsManagerSource } from './routed-items-manager-source'; import { CoreRoutedItemsManagerSource } from './routed-items-manager-source';
import { CoreRoutedItemsManager } from './routed-items-manager'; import { CoreRoutedItemsManager } from './routed-items-manager';

View File

@ -23,7 +23,7 @@ import {
} from '@services/ws'; } from '@services/ws';
import { CoreToasts, ToastDuration } from '@services/toasts'; import { CoreToasts, ToastDuration } from '@services/toasts';
import { CoreText } from '@singletons/text'; 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 { CoreCacheUpdateFrequency, CoreConstants, MINIMUM_MOODLE_VERSION, MOODLE_RELEASES } from '@/core/constants';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
import { CoreWSError } from '@classes/errors/wserror'; 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 { Subject, Subscription } from 'rxjs';
import { auditTime } from 'rxjs/operators'; import { auditTime } from 'rxjs/operators';
import { CorePopovers } from '@services/popovers'; import { CorePopovers } from '@services/popovers';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreContextMenuItemComponent } from './context-menu-item'; import { CoreContextMenuItemComponent } from './context-menu-item';
import { CoreDirectivesRegistry } from '@singletons/directives-registry'; 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 { 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 { CoreAnimations } from '@components/animations';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDirectivesRegistry } from '@singletons/directives-registry';

View File

@ -23,7 +23,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { IonRouterOutlet, IonTabs, ViewDidEnter, ViewDidLeave } from '@ionic/angular'; 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 { Params } from '@angular/router';
import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons';
import { StackDidChangeEvent } from '@ionic/angular/common/directives/navigation/stack-utils'; 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 { Component, Input, Output, OnInit, OnDestroy, ElementRef, EventEmitter, ContentChild, TemplateRef } from '@angular/core';
import { CoreTabBase } from '@classes/tabs'; import { CoreTabBase } from '@classes/tabs';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDirectivesRegistry } from '@singletons/directives-registry';
import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons';
import { CoreTabsComponent } from './tabs'; import { CoreTabsComponent } from './tabs';

View File

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

View File

@ -15,7 +15,7 @@
import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
import { ScrollDetail } from '@ionic/core'; import { ScrollDetail } from '@ionic/core';
import { IonContent } from '@ionic/angular'; import { IonContent } from '@ionic/angular';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreMath } from '@singletons/math'; import { CoreMath } from '@singletons/math';
import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDirectivesRegistry } from '@singletons/directives-registry';
import { CoreFormatTextDirective } from './format-text'; 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 { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreLoadingComponent } from '@components/loading/loading'; import { CoreLoadingComponent } from '@components/loading/loading';
import { CoreSettingsHelper } from '@features/settings/services/settings-helper'; import { CoreSettingsHelper } from '@features/settings/services/settings-helper';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreColors } from '@singletons/colors'; import { CoreColors } from '@singletons/colors';
import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDirectivesRegistry } from '@singletons/directives-registry';

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import { Directive, ElementRef, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core'; 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. * Directive to listen for element resize events.

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ import { Component, ViewChild, OnInit, OnDestroy, forwardRef, ChangeDetectorRef
import { IonContent } from '@ionic/angular'; import { IonContent } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom'; 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 { CoreCourses, CoreCourseAnyCourseData } from '@features/courses/services/courses';
import { import {
CoreCourse, CoreCourse,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@ import {
} from '@features/grades/services/grades'; } from '@features/grades/services/grades';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUrl } from '@singletons/url'; 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 { CoreDomUtils } from '@services/utils/dom';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreH5P } from '@features/h5p/services/h5p'; import { CoreH5P } from '@features/h5p/services/h5p';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreH5PCore, CoreH5PLibraryData, CoreH5PLibraryAddonData, CoreH5PContentDepsTreeDependency } from './core'; 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 { CoreSites } from '@services/sites';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreH5P } from '@features/h5p/services/h5p'; import { CoreH5P } from '@features/h5p/services/h5p';
import { CoreH5PFileStorage } from './file-storage'; import { CoreH5PFileStorage } from './file-storage';
import { CoreH5PFramework } from './framework'; 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 { CoreFile, CoreFileProvider } from '@services/file';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreUtils } from '@services/utils/utils';
import { CoreH5P } from '../services/h5p'; import { CoreH5P } from '../services/h5p';
import { CoreH5PCore, CoreH5PDisplayOptions, CoreH5PLocalization } from './core'; import { CoreH5PCore, CoreH5PDisplayOptions, CoreH5PLocalization } from './core';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
@ -56,10 +55,8 @@ export class CoreH5PHelper {
const config: CoreH5PDisplayOptions = { const config: CoreH5PDisplayOptions = {
export: false, // Don't allow downloading in the app. export: false, // Don't allow downloading in the app.
embed: false, // Don't display the embed button in the app. embed: false, // Don't display the embed button in the app.
copyright: CoreUtils.notNullOrUndefined(displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT]) ? copyright: displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT] ?? false,
displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT] : false, icon: displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_ABOUT] ?? false,
icon: CoreUtils.notNullOrUndefined(displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_ABOUT]) ?
displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_ABOUT] : false,
}; };
config.frame = config.copyright || config.export || config.embed; config.frame = config.copyright || config.export || config.embed;

View File

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

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@ import { CoreFilepool } from '@services/filepool';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreWSFile } from '@services/ws'; import { CoreWSFile } from '@services/ws';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreQuestion, CoreQuestionProvider, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from './question'; 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 { CoreDomUtils } from '@services/utils/dom';
import { CoreSearchGlobalSearchResultsSource } from '@features/search/classes/global-search-results-source'; import { CoreSearchGlobalSearchResultsSource } from '@features/search/classes/global-search-results-source';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';

View File

@ -29,7 +29,7 @@ import {
CoreSitePluginsCourseModuleHandlerData, CoreSitePluginsCourseModuleHandlerData,
} from '@features/siteplugins/services/siteplugins'; } from '@features/siteplugins/services/siteplugins';
import { CoreModals } from '@services/modals'; 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 { CoreSitePluginsPluginContentComponent, CoreSitePluginsPluginContentLoadedData } from '../plugin-content/plugin-content';
import { CoreCompileHtmlComponentModule } from '@features/compile/components/compile-html/compile-html.module'; import { CoreCompileHtmlComponentModule } from '@features/compile/components/compile-html/compile-html.module';
import { CoreCourseComponentsModule } from '@features/course/components/components.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 { CoreSitePluginsPluginContentComponent } from '@features/siteplugins/components/plugin-content/plugin-content';
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins'; 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 { CoreNavigator } from '@services/navigator';
import { CoreSharedModule } from '@/core/shared.module'; 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 { CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
import { CanLeave } from '@guards/can-leave'; import { CanLeave } from '@guards/can-leave';
import { CoreNavigator } from '@services/navigator'; 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 { CoreSitePluginsPluginContentComponent } from '../../components/plugin-content/plugin-content';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';

View File

@ -22,7 +22,7 @@ import { CoreFilepool } from '@services/filepool';
import { CoreLang, CoreLangFormat } from '@services/lang'; import { CoreLang, CoreLangFormat } from '@services/lang';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreEvents } from '@singletons/events'; 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 { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user'; import { CoreUserProfileField } from '@features/user/services/user';
import { CoreUserProfileFieldDelegate } from '@features/user/services/user-profile-field-delegate'; 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 { ContextLevel } from '@/core/constants';
import { toBoolean } from '@/core/transforms/boolean'; 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 { CoreMainMenu } from '@features/mainmenu/services/mainmenu';
import { CoreObject } from '@singletons/object'; import { CoreObject } from '@singletons/object';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@singletons/utils';
import { CoreUrl, CoreUrlPartNames } from '@singletons/url'; import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { makeSingleton, NavController, Router } from '@singletons'; import { makeSingleton, NavController, Router } from '@singletons';

View File

@ -21,7 +21,6 @@ import { CoreEvents } from '@singletons/events';
import { CoreWS } from '@services/ws'; import { CoreWS } from '@services/ws';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl, CoreUrlPartNames } from '@singletons/url'; import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreConstants, MINIMUM_MOODLE_VERSION, MOODLE_RELEASES } from '@/core/constants'; import { CoreConstants, MINIMUM_MOODLE_VERSION, MOODLE_RELEASES } from '@/core/constants';
import { import {
CoreSite, CoreSite,
@ -466,7 +465,7 @@ export class CoreSitesProvider {
if (error.debug?.code === 'codingerror') { if (error.debug?.code === 'codingerror') {
// This could be caused by a redirect. Check if it's the case. // 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 }); options.message = Translate.instant('core.siteunavailablehelp', { site: siteUrl });
@ -557,9 +556,9 @@ export class CoreSitesProvider {
return this.getUserToken(siteUrl, username, password, service, true); 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. // 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) { if (redirect) {
throw this.createCannotConnectLoginError(siteUrl, { throw this.createCannotConnectLoginError(siteUrl, {
@ -2217,6 +2216,47 @@ export class CoreSitesProvider {
this.afterLoginNavigationQueue = []; 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); 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 { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
import { FileEntry } from '@awesome-cordova-plugins/file/ngx'; import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
import { CoreFileUtils } from '@singletons/file-utils'; import { CoreFileUtils } from '@singletons/file-utils';
import { CoreWS } from '@services/ws'; import { CoreRedirects } from '@singletons/redirects';
import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { CoreFileEntry } from '@services/file-helper'; import { CoreFileEntry } from '@services/file-helper';
import { CoreCancellablePromise } from '@classes/cancellable-promise'; import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreArray } from '@singletons/array'; import { CoreArray } from '@singletons/array';
@ -31,8 +30,9 @@ import { CorePromiseUtils, OrderedPromiseData } from '@singletons/promise-utils'
import { CoreOpener, CoreOpenerOpenFileOptions, CoreOpenerOpenInBrowserOptions } from '@singletons/opener'; import { CoreOpener, CoreOpenerOpenFileOptions, CoreOpenerOpenInBrowserOptions } from '@singletons/opener';
import { CoreCountries, CoreCountry } from '@singletons/countries'; import { CoreCountries, CoreCountry } from '@singletons/countries';
import { CoreObject } from '@singletons/object'; import { CoreObject } from '@singletons/object';
import { CoreSites } from '@services/sites';
export type TreeNode<T> = T & { children: TreeNode<T>[] }; import { CoreMenuItem, CoreUtils as CoreUtilsSingleton, TreeNode } from '@singletons/utils';
import { CoreWSError } from '@classes/errors/wserror';
/* /*
* "Utils" service with helper functions. * "Utils" service with helper functions.
@ -40,15 +40,6 @@ export type TreeNode<T> = T & { children: TreeNode<T>[] };
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class CoreUtilsProvider { 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. * 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. * @param url The URL to check.
* @returns Promise resolved with boolean_ whether there is a redirect. * @returns Promise resolved with boolean_ whether there is a redirect.
* @deprecated since 5.0. Use CoreRedirects.checkRedirect instead.
*/ */
async checkRedirect(url: string): Promise<boolean> { async checkRedirect(url: string): Promise<boolean> {
if (!window.fetch) { return CoreRedirects.checkRedirect(url);
// 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;
}
} }
/** /**
@ -224,44 +190,10 @@ export class CoreUtilsProvider {
* @param source The variable to clone. * @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. * @param level Depth we are right now inside a cloned object. It's used to prevent reaching max call stack size.
* @returns Cloned variable. * @returns Cloned variable.
* @deprecated since 5.0. Use CoreUtils.clone instead.
*/ */
clone<T>(source: T, level: number = 0): T { clone<T>(source: T, level: number = 0): T {
if (level >= 20) { return CoreUtilsSingleton.clone(source, level);
// 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;
}
} }
/** /**
@ -275,7 +207,7 @@ export class CoreUtilsProvider {
copyProperties(from: Record<string, unknown>, to: Record<string, unknown>, clone: boolean = true): void { copyProperties(from: Record<string, unknown>, to: Record<string, unknown>, clone: boolean = true): void {
for (const name in from) { for (const name in from) {
if (clone) { if (clone) {
to[name] = this.clone(from[name]); to[name] = CoreUtilsSingleton.clone(from[name]);
} else { } else {
to[name] = from[name]; 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 * @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. * depending on this result.
* @returns Promise resolved with the list of enabled sites. * @returns Promise resolved with the list of enabled sites.
* @deprecated since 5.0. Use CoreSites.filterEnabledSites instead.
*/ */
async filterEnabledSites<P extends unknown[]>( async filterEnabledSites<P extends unknown[]>(
siteIds: string[], siteIds: string[],
@ -370,29 +303,7 @@ export class CoreUtilsProvider {
checkAll?: boolean, checkAll?: boolean,
...args: P ...args: P
): Promise<string[]> { ): Promise<string[]> {
const promises: Promise<false | number>[] = []; return CoreSites.filterEnabledSites(siteIds, isEnabledFn, checkAll, ...args);
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;
}
} }
/** /**
@ -401,17 +312,10 @@ export class CoreUtilsProvider {
* *
* @param float The float to print. * @param float The float to print.
* @returns Locale float. * @returns Locale float.
* @deprecated since 5.0. Use CoreUtils.formatFloat on singletons instead.
*/ */
formatFloat(float: unknown): string { formatFloat(float: unknown): string {
if (float === undefined || float === null || typeof float == 'boolean') { return CoreUtilsSingleton.formatFloat(float);
return '';
}
const localeSeparator = Translate.instant('core.decsep');
const floatString = String(float);
return floatString.replace('.', localeSeparator);
} }
/** /**
@ -425,6 +329,7 @@ export class CoreUtilsProvider {
* @param rootParentId The id of the root. * @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. * @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. * @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>( formatTree<T>(
list: T[], list: T[],
@ -433,67 +338,7 @@ export class CoreUtilsProvider {
rootParentId: number = 0, rootParentId: number = 0,
maxDepth: number = 5, maxDepth: number = 5,
): TreeNode<T>[] { ): TreeNode<T>[] {
const map = {}; return CoreUtilsSingleton.formatTree(list, parentFieldName, idFieldName, rootParentId, maxDepth);
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;
} }
/** /**
@ -545,13 +390,10 @@ export class CoreUtilsProvider {
* *
* @param name The name to get the ID for. * @param name The name to get the ID for.
* @returns Unique ID. * @returns Unique ID.
* @deprecated since 5.0. Use CoreUtils.getUniqueId singleton instead.
*/ */
getUniqueId(name: string): number { getUniqueId(name: string): number {
if (!this.uniqueIds[name]) { return CoreUtilsSingleton.getUniqueId(name);
this.uniqueIds[name] = 0;
}
return ++this.uniqueIds[name];
} }
/** /**
@ -615,10 +457,11 @@ export class CoreUtilsProvider {
* *
* @param value Value to check. * @param value Value to check.
* @returns Whether the value is false, 0 or "0". * @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 // eslint-disable-next-line @typescript-eslint/no-explicit-any
isFalseOrZero(value: any): boolean { 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. * @param value Value to check.
* @returns Whether the value is true, 1 or "1". * @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 // eslint-disable-next-line @typescript-eslint/no-explicit-any
isTrueOrOne(value: any): boolean { 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 // eslint-disable-next-line @typescript-eslint/no-explicit-any
isWebServiceError(error: any): boolean { isWebServiceError(error: any): boolean {
return error && ( return CoreWSError.isWebServiceError(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.
);
} }
/** /**
@ -664,8 +497,7 @@ export class CoreUtilsProvider {
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
isExpiredTokenError(error: any): boolean { isExpiredTokenError(error: any): boolean {
return error.errorcode === 'invalidtoken' || return CoreWSError.isExpiredTokenError(error);
(error.errorcode === 'accessexception' && error.message.includes('Invalid token - token expired'));
} }
/** /**
@ -677,6 +509,7 @@ export class CoreUtilsProvider {
* @param separator The separator used within the list string. Default ','. * @param separator The separator used within the list string. Default ','.
* @param defaultValue Element that will become default option value. Default 0. * @param defaultValue Element that will become default option value. Default 0.
* @returns The now assembled array * @returns The now assembled array
* @deprecated since 5.0. Use CoreUtils.makeMenuFromList singleton instead.
*/ */
makeMenuFromList<T>( makeMenuFromList<T>(
list: string, list: string,
@ -684,20 +517,7 @@ export class CoreUtilsProvider {
separator: string = ',', separator: string = ',',
defaultValue?: T, defaultValue?: T,
): CoreMenuItem<T>[] { ): CoreMenuItem<T>[] {
// Split and format the list. return CoreUtilsSingleton.makeMenuFromList(list, defaultLabel, separator, defaultValue);
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;
} }
/** /**
@ -718,6 +538,7 @@ export class CoreUtilsProvider {
* *
* @param value Value to check. * @param value Value to check.
* @returns True if not null and not undefined. * @returns True if not null and not undefined.
* @deprecated since 5.0. Use ?? instead.
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
notNullOrUndefined(value: any): boolean { notNullOrUndefined(value: any): boolean {
@ -967,39 +788,10 @@ export class CoreUtilsProvider {
* @param localeFloat Locale aware float representation. * @param localeFloat Locale aware float representation.
* @param strict If true, then check the input and return false if it is not a valid number. * @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. * @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 { unformatFloat(localeFloat: string | number | null | undefined, strict?: boolean): false | '' | number {
// Bad format on input type number. return CoreUtilsSingleton.unformatFloat(localeFloat, strict);
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;
} }
/** /**
@ -1020,17 +812,10 @@ export class CoreUtilsProvider {
* @param fn Function to debounce. * @param fn Function to debounce.
* @param delay Time that must pass until the function is called. * @param delay Time that must pass until the function is called.
* @returns Debounced function. * @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 { debounce<T extends unknown[]>(fn: (...args: T) => unknown, delay: number): (...args: T) => void {
let timeoutID: number; return CoreUtilsSingleton.debounce(fn, delay);
const debounced = (...args: T): void => {
clearTimeout(timeoutID);
timeoutID = window.setTimeout(() => fn.apply(null, args), delay);
};
return debounced;
} }
/** /**
@ -1039,23 +824,10 @@ export class CoreUtilsProvider {
* @param fn Function to throttle. * @param fn Function to throttle.
* @param duration Time that must pass until the function is called. * @param duration Time that must pass until the function is called.
* @returns Throttled function. * @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 { throttle<T extends unknown[]>(fn: (...args: T) => unknown, duration: number): (...args: T) => void {
let shouldWait = false; return CoreUtilsSingleton.throttle(fn, duration);
const throttled = (...args: T): void => {
if (!shouldWait) {
fn.apply(null, args);
shouldWait = true;
setTimeout(() => {
shouldWait = false;
}, duration);
}
};
return throttled;
} }
/** /**
@ -1182,14 +954,6 @@ export class CoreUtilsProvider {
export const CoreUtils = makeSingleton(CoreUtilsProvider); export const CoreUtils = makeSingleton(CoreUtilsProvider);
/**
* Menu item.
*/
export type CoreMenuItem<T = number> = {
label: string;
value: T | number;
};
/** /**
* Options for waiting. * Options for waiting.
* *

View File

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

View File

@ -15,6 +15,8 @@
import { CoreRedirectPayload } from '@services/navigator'; import { CoreRedirectPayload } from '@services/navigator';
import { CoreLogger } from './logger'; import { CoreLogger } from './logger';
import { CoreObject } from './object'; import { CoreObject } from './object';
import { CoreWS } from '@services/ws';
import { CorePromiseUtils } from './promise-utils';
/** /**
* Singleton with helper functions to manage redirects. * 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 { CoreColorScheme, CoreZoomLevel } from '@features/settings/services/settings-helper';
import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mainmenu'; import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mainmenu';
import { CoreLoginSiteInfo, CoreSitesDemoSiteData } from '@services/sites'; 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 { CoreLoginSiteFinderSettings, CoreLoginSiteSelectorListMethod } from '@features/login/services/login-helper';
import { CoreDatabaseConfiguration } from '@classes/database/database-table'; import { CoreDatabaseConfiguration } from '@classes/database/database-table';
import { ToastDuration } from '@services/toasts'; import { ToastDuration } from '@services/toasts';