diff --git a/src/addons/calendar/services/calendar.ts b/src/addons/calendar/services/calendar.ts index fe6166ed9..67a808231 100644 --- a/src/addons/calendar/services/calendar.ts +++ b/src/addons/calendar/services/calendar.ts @@ -32,7 +32,7 @@ import { AddonCalendarEventDBRecord, AddonCalendarReminderDBRecord, EVENTS_TABLE import { CoreCourses } from '@features/courses/services/courses'; import { ContextLevel, CoreConstants } from '@/core/constants'; import { CoreWSError } from '@classes/errors/wserror'; -import { ApplicationInit, makeSingleton, Translate, Platform } from '@singletons'; +import { ApplicationInit, makeSingleton, Translate } from '@singletons'; import { AddonCalendarOfflineEventDBRecord } from './database/calendar-offline'; import { AddonCalendarMainMenuHandlerService } from './handlers/mainmenu'; import { SafeUrl } from '@angular/platform-browser'; @@ -41,6 +41,7 @@ import { AddonCalendarFilter } from './calendar-helper'; import { AddonCalendarSyncEvents, AddonCalendarSyncProvider } from './calendar-sync'; import { CoreEvents } from '@singletons/events'; import { CoreText } from '@singletons/text'; +import { CorePlatform } from '@services/platform'; const ROOT_CACHE_KEY = 'mmaCalendar:'; @@ -1429,7 +1430,7 @@ export class AddonCalendarProvider { * @return Promise resolved when all the notifications have been scheduled. */ async scheduleAllSitesEventsNotifications(): Promise { - await Platform.ready(); + await CorePlatform.ready(); const notificationsEnabled = CoreLocalNotifications.isAvailable(); diff --git a/src/addons/messages/pages/discussions-35/discussions.page.ts b/src/addons/messages/pages/discussions-35/discussions.page.ts index 58d52fd6e..a690647a0 100644 --- a/src/addons/messages/pages/discussions-35/discussions.page.ts +++ b/src/addons/messages/pages/discussions-35/discussions.page.ts @@ -28,11 +28,12 @@ import { ActivatedRoute, Params } from '@angular/router'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { Subscription } from 'rxjs'; -import { Translate, Platform } from '@singletons'; +import { Translate } from '@singletons'; import { IonRefresher } from '@ionic/angular'; import { CoreNavigator } from '@services/navigator'; import { CoreScreen } from '@services/screen'; import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager'; +import { CorePlatform } from '@services/platform'; /** * Page that displays the list of discussions. @@ -114,7 +115,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { ); // Refresh the view when the app is resumed. - this.appResumeSubscription = Platform.resume.subscribe(() => { + this.appResumeSubscription = CorePlatform.resume.subscribe(() => { if (!this.loaded) { return; } diff --git a/src/addons/messages/pages/group-conversations/group-conversations.page.ts b/src/addons/messages/pages/group-conversations/group-conversations.page.ts index 73ff7d7e1..e5175dfa7 100644 --- a/src/addons/messages/pages/group-conversations/group-conversations.page.ts +++ b/src/addons/messages/pages/group-conversations/group-conversations.page.ts @@ -29,7 +29,7 @@ import { import { CoreDomUtils } from '@services/utils/dom'; import { CoreUser } from '@features/user/services/user'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; -import { Platform, Translate } from '@singletons'; +import { Translate } from '@singletons'; import { Subscription } from 'rxjs'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { ActivatedRoute, Params } from '@angular/router'; @@ -37,6 +37,7 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreNavigator } from '@services/navigator'; import { CoreScreen } from '@services/screen'; import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager'; +import { CorePlatform } from '@services/platform'; /** * Page that displays the list of conversations, including group conversations. @@ -176,7 +177,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { ); // Refresh the view when the app is resumed. - this.appResumeSubscription = Platform.resume.subscribe(() => { + this.appResumeSubscription = CorePlatform.resume.subscribe(() => { if (!this.loaded) { return; } diff --git a/src/addons/mod/lti/services/lti-helper.ts b/src/addons/mod/lti/services/lti-helper.ts index 74d28a689..dcb3ac154 100644 --- a/src/addons/mod/lti/services/lti-helper.ts +++ b/src/addons/mod/lti/services/lti-helper.ts @@ -16,9 +16,10 @@ import { Injectable } from '@angular/core'; import { CoreCourse } from '@features/course/services/course'; import { CoreCourseModuleData } from '@features/course/services/course-helper'; +import { CorePlatform } from '@services/platform'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { makeSingleton, Platform } from '@singletons'; +import { makeSingleton } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { AddonModLti, AddonModLtiLti } from './lti'; @@ -38,7 +39,7 @@ export class AddonModLtiHelperProvider { } watchPendingCompletions(): void { - Platform.resume.subscribe(() => { + CorePlatform.resume.subscribe(() => { // User went back to the app, check pending completions. for (const moduleId in this.pendingCheckCompletion) { const data = this.pendingCheckCompletion[moduleId]; diff --git a/src/addons/mod/workshop/components/index/index.ts b/src/addons/mod/workshop/components/index/index.ts index 52808f0a9..1059ca513 100644 --- a/src/addons/mod/workshop/components/index/index.ts +++ b/src/addons/mod/workshop/components/index/index.ts @@ -19,9 +19,9 @@ import { CoreCourseContentsPage } from '@features/course/pages/contents/contents import { IonContent } from '@ionic/angular'; import { CoreGroupInfo, CoreGroups } from '@services/groups'; import { CoreNavigator } from '@services/navigator'; +import { CorePlatform } from '@services/platform'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { Platform } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { Subscription } from 'rxjs'; import { AddonModWorkshopModuleHandlerService } from '../../services/handlers/module'; @@ -119,7 +119,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity }, this.siteId); // Since most actions will take the user out of the app, we should refresh the view when the app is resumed. - this.appResumeSubscription = Platform.resume.subscribe(() => { + this.appResumeSubscription = CorePlatform.resume.subscribe(() => { this.showLoadingAndRefresh(true); }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 25dbce527..912c8b785 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -19,7 +19,7 @@ import { BackButtonEvent, ScrollDetail } from '@ionic/core'; import { CoreLang } from '@services/lang'; import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreEvents } from '@singletons/events'; -import { NgZone, Platform, SplashScreen, Translate } from '@singletons'; +import { NgZone, SplashScreen, Translate } from '@singletons'; import { CoreNetwork } from '@services/network'; import { CoreApp, CoreAppProvider } from '@services/app'; import { CoreSites } from '@services/sites'; @@ -33,6 +33,7 @@ import { CoreConstants } from '@/core/constants'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreDom } from '@singletons/dom'; +import { CorePlatform } from '@services/platform'; const MOODLE_VERSION_PREFIX = 'version-'; const MOODLEAPP_VERSION_PREFIX = 'moodleapp-'; @@ -181,7 +182,7 @@ export class AppComponent implements OnInit, AfterViewInit { } }); - Platform.resume.subscribe(() => { + CorePlatform.resume.subscribe(() => { // Wait a second before setting it to false since in iOS there could be some frozen WS calls. setTimeout(() => { if (CoreLoginHelper.isWaitingForBrowser()) { @@ -305,7 +306,7 @@ export class AppComponent implements OnInit, AfterViewInit { * Async init function on platform ready. */ protected async onPlatformReady(): Promise { - await Platform.ready(); + await CorePlatform.ready(); // Refresh online status when changes. CoreNetwork.onChange().subscribe(() => { diff --git a/src/core/classes/modal-lateral-transition.ts b/src/core/classes/modal-lateral-transition.ts index bc481f705..12f3327a2 100644 --- a/src/core/classes/modal-lateral-transition.ts +++ b/src/core/classes/modal-lateral-transition.ts @@ -14,13 +14,13 @@ import { createAnimation } from '@ionic/angular'; import { Animation } from '@ionic/core'; -import { Platform } from '@singletons'; +import { CorePlatform } from '@services/platform'; /** * Sliding transition for lateral modals. */ export function CoreModalLateralTransitionEnter(baseEl: HTMLElement): Animation { - const OFF_RIGHT = Platform.isRTL ? '-100%' : '100%'; + const OFF_RIGHT = CorePlatform.isRTL ? '-100%' : '100%'; const otherAnimations: Animation[] = []; @@ -51,7 +51,7 @@ export function CoreModalLateralTransitionEnter(baseEl: HTMLElement): Animation } export function CoreModalLateralTransitionLeave(baseEl: HTMLElement): Animation { - const OFF_RIGHT = Platform.isRTL ? '-100%' : '100%'; + const OFF_RIGHT = CorePlatform.isRTL ? '-100%' : '100%'; const otherAnimations: Animation[] = []; diff --git a/src/core/classes/sqlitedb.ts b/src/core/classes/sqlitedb.ts index 649e81cc9..1021c07d9 100644 --- a/src/core/classes/sqlitedb.ts +++ b/src/core/classes/sqlitedb.ts @@ -14,9 +14,10 @@ import { SQLiteObject } from '@ionic-native/sqlite/ngx'; -import { SQLite, Platform } from '@singletons'; +import { SQLite } from '@singletons'; import { CoreError } from '@classes/errors/error'; import { CoreDB } from '@services/db'; +import { CorePlatform } from '@services/platform'; type SQLiteDBColumnType = 'INTEGER' | 'REAL' | 'TEXT' | 'BLOB'; @@ -1157,7 +1158,7 @@ export class SQLiteDB { * @returns Database. */ protected async createDatabase(): Promise { - await Platform.ready(); + await CorePlatform.ready(); return SQLite.create({ name: this.name, location: 'default' }); } diff --git a/src/core/classes/tabs.ts b/src/core/classes/tabs.ts index 166711854..6e741e934 100644 --- a/src/core/classes/tabs.ts +++ b/src/core/classes/tabs.ts @@ -29,7 +29,7 @@ import { IonSlides } from '@ionic/angular'; import { BackButtonEvent } from '@ionic/core'; import { Subscription } from 'rxjs'; -import { Platform, Translate } from '@singletons'; +import { Translate } from '@singletons'; import { CoreSettingsHelper } from '@features/settings/services/settings-helper'; import { CoreAriaRoleTab, CoreAriaRoleTabFindable } from './aria-role-tab'; import { CoreEventObserver } from '@singletons/events'; @@ -39,6 +39,7 @@ import { CoreError } from './errors/error'; import { CorePromisedValue } from './promised-value'; import { AsyncComponent } from './async-component'; import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CorePlatform } from '@services/platform'; /** * Class to abstract some common code for tabs. @@ -105,12 +106,12 @@ export class CoreTabsBaseComponent implements OnInit, Aft * @inheritdoc */ async ngOnInit(): Promise { - this.direction = Platform.isRTL ? 'rtl' : 'ltr'; + this.direction = CorePlatform.isRTL ? 'rtl' : 'ltr'; // Change the side when the language changes. this.subscriptions.push(Translate.onLangChange.subscribe(() => { setTimeout(() => { - this.direction = Platform.isRTL ? 'rtl' : 'ltr'; + this.direction = CorePlatform.isRTL ? 'rtl' : 'ltr'; }); })); } diff --git a/src/core/components/horizontal-scroll-controls/horizontal-scroll-controls.ts b/src/core/components/horizontal-scroll-controls/horizontal-scroll-controls.ts index ccce235d1..1842b0229 100644 --- a/src/core/components/horizontal-scroll-controls/horizontal-scroll-controls.ts +++ b/src/core/components/horizontal-scroll-controls/horizontal-scroll-controls.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Component, Input } from '@angular/core'; -import { Platform } from '@singletons'; +import { CorePlatform } from '@services/platform'; const enum ScrollPosition { START = 'start', @@ -89,14 +89,14 @@ export class CoreHorizontalScrollControlsComponent { } if (scrollLeft === 0) { - return Platform.isRTL ? ScrollPosition.END : ScrollPosition.START; + return CorePlatform.isRTL ? ScrollPosition.END : ScrollPosition.START; } - if (!Platform.isRTL && this.target.scrollWidth - scrollLeft === this.target.clientWidth) { + if (!CorePlatform.isRTL && this.target.scrollWidth - scrollLeft === this.target.clientWidth) { return ScrollPosition.END; } - if (Platform.isRTL && this.target.scrollWidth + scrollLeft === this.target.clientWidth) { + if (CorePlatform.isRTL && this.target.scrollWidth + scrollLeft === this.target.clientWidth) { return ScrollPosition.START; } diff --git a/src/core/core.module.ts b/src/core/core.module.ts index 2376f3db4..44ca6128e 100644 --- a/src/core/core.module.ts +++ b/src/core/core.module.ts @@ -50,8 +50,6 @@ import { CoreUpdateManagerProvider } from '@services/update-manager'; import { CoreUrlUtilsProvider } from '@services/utils/url'; import { CoreUtilsProvider } from '@services/utils/utils'; import { CoreWSProvider } from '@services/ws'; -import { CoreNetworkService } from '@services/network'; -import { CorePlatformService } from '@services/platform'; export const CORE_SERVICES: Type[] = [ CoreAppProvider, @@ -71,8 +69,6 @@ export const CORE_SERVICES: Type[] = [ CoreLocalNotificationsProvider, CoreMimetypeUtilsProvider, CoreNavigatorService, - CoreNetworkService, - CorePlatformService, CorePluginFileDelegateService, CoreScreenService, CoreSitesProvider, diff --git a/src/core/directives/format-text.ts b/src/core/directives/format-text.ts index 87d6d3988..74eef5ace 100644 --- a/src/core/directives/format-text.ts +++ b/src/core/directives/format-text.ts @@ -34,7 +34,7 @@ import { CoreIframeUtils, CoreIframeUtilsProvider } from '@services/utils/iframe import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { CoreSite } from '@classes/site'; -import { NgZone, Platform, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { CoreExternalContentDirective } from './external-content'; import { CoreLinkDirective } from './link'; import { CoreFilter, CoreFilterFilter, CoreFilterFormatTextOptions } from '@features/filter/services/filter'; @@ -49,6 +49,7 @@ import { CoreText } from '@singletons/text'; import { CoreDom } from '@singletons/dom'; import { CoreEvents } from '@singletons/events'; import { CoreRefreshContext, CORE_REFRESH_CONTEXT } from '@/core/utils/refresh-context'; +import { CorePlatform } from '@services/platform'; /** * Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective @@ -615,7 +616,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo if (refreshOnResume && this.refreshContext) { // Refresh the context when the app is resumed. - CoreSubscriptions.once(Platform.resume, () => { + CoreSubscriptions.once(CorePlatform.resume, () => { NgZone.run(async () => { this.refreshContext?.refreshContext(); }); diff --git a/src/core/directives/swipe-navigation.ts b/src/core/directives/swipe-navigation.ts index b2aa69c6b..e81959e56 100644 --- a/src/core/directives/swipe-navigation.ts +++ b/src/core/directives/swipe-navigation.ts @@ -17,8 +17,9 @@ import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe import { CoreSwipeNavigationTourComponent } from '@components/swipe-navigation-tour/swipe-navigation-tour'; import { CoreUserTours } from '@features/usertours/services/user-tours'; import { Gesture, GestureDetail } from '@ionic/angular'; +import { CorePlatform } from '@services/platform'; import { CoreScreen } from '@services/screen'; -import { GestureController, Platform } from '@singletons'; +import { GestureController } from '@singletons'; const ACTIVATION_THRESHOLD = 150; const SWIPE_FRICTION = 0.6; @@ -105,7 +106,7 @@ export class CoreSwipeNavigationDirective implements AfterViewInit, OnDestroy { return; } - Platform.isRTL + CorePlatform.isRTL ? this.manager?.navigateToPreviousItem() : this.manager?.navigateToNextItem(); } @@ -118,7 +119,7 @@ export class CoreSwipeNavigationDirective implements AfterViewInit, OnDestroy { return; } - Platform.isRTL + CorePlatform.isRTL ? this.manager?.navigateToNextItem() : this.manager?.navigateToPreviousItem(); } @@ -131,7 +132,7 @@ export class CoreSwipeNavigationDirective implements AfterViewInit, OnDestroy { return false; } - return Platform.isRTL + return CorePlatform.isRTL ? await this.manager.hasNextItem() : await this.manager.hasPreviousItem(); } @@ -144,7 +145,7 @@ export class CoreSwipeNavigationDirective implements AfterViewInit, OnDestroy { return false; } - return Platform.isRTL + return CorePlatform.isRTL ? await this.manager.hasPreviousItem() : await this.manager.hasNextItem(); } diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 82fafd18b..204ec0408 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -26,7 +26,6 @@ import { } from '@angular/core'; import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; import { - Platform, ActionSheetController, AlertController, LoadingController, @@ -48,7 +47,7 @@ import { CORE_CONTENTLINKS_SERVICES } from '@features/contentlinks/contentlinks. import { CORE_COURSE_SERVICES } from '@features/course/course.module'; import { CORE_COURSES_SERVICES } from '@features/courses/courses.module'; import { CORE_EDITOR_SERVICES } from '@features/editor/editor.module'; -import { IONIC_NATIVE_SERVICES } from '@features/emulator/emulator.module'; +import { CORE_NATIVE_SERVICES } from '@features/native/native.module'; import { CORE_FILEUPLOADER_SERVICES } from '@features/fileuploader/fileuploader.module'; import { CORE_FILTER_SERVICES } from '@features/filter/filter.module'; import { CORE_GRADES_SERVICES } from '@features/grades/grades.module'; @@ -156,6 +155,7 @@ import { ADDON_PRIVATEFILES_SERVICES } from '@addons/privatefiles/privatefiles.m import { AddonModAssignComponentsModule } from '@addons/mod/assign/components/components.module'; import { AddonModWorkshopComponentsModule } from '@addons/mod/workshop/components/components.module'; import { CorePromisedValue } from '@classes/promised-value'; +import { CorePlatform } from '@services/platform'; /** * Service to provide functionalities regarding compiling dynamic HTML and Javascript. @@ -168,7 +168,7 @@ export class CoreCompileProvider { // Other Ionic/Angular providers that don't depend on where they are injected. protected readonly OTHER_SERVICES: unknown[] = [ - TranslateService, HttpClient, Platform, DomSanitizer, ActionSheetController, AlertController, LoadingController, + TranslateService, HttpClient, DomSanitizer, ActionSheetController, AlertController, LoadingController, ModalController, PopoverController, ToastController, FormBuilder, ]; @@ -285,7 +285,7 @@ export class CoreCompileProvider { ...CORE_STYLE_SERVICES, ...CORE_USER_SERVICES, ...CORE_XAPI_SERVICES, - ...IONIC_NATIVE_SERVICES, + ...CORE_NATIVE_SERVICES, ...this.OTHER_SERVICES, ...extraProviders, ...ADDON_BADGES_SERVICES, @@ -344,10 +344,13 @@ export class CoreCompileProvider { instance['CoreLoggerProvider'] = CoreLogger; instance['moment'] = moment; instance['Md5'] = Md5; - instance['Network'] = CoreNetwork.instance; // @deprecated on 4.1, plugins should use CoreNetworkService instead. + instance['Network'] = CoreNetwork.instance; // @deprecated on 4.1, plugins should use CoreNetwork instead. + instance['Platform'] = CorePlatform.instance; // @deprecated on 4.1, plugins should use CorePlatform instead. instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider; instance['CoreArray'] = CoreArray; instance['CoreComponentsRegistry'] = CoreComponentsRegistry; + instance['CoreNetwork'] = CoreNetwork.instance; + instance['CorePlatform'] = CorePlatform.instance; instance['CoreDom'] = CoreDom; instance['CoreForms'] = CoreForms; instance['CoreText'] = CoreText; diff --git a/src/core/features/course/pages/course-summary/course-summary.ts b/src/core/features/course/pages/course-summary/course-summary.ts index 1adcc8c72..d9b6e719a 100644 --- a/src/core/features/course/pages/course-summary/course-summary.ts +++ b/src/core/features/course/pages/course-summary/course-summary.ts @@ -30,7 +30,7 @@ import { CoreCourseOptionsMenuHandlerToDisplay, } from '@features/course/services/course-options-delegate'; import { CoreCourseHelper } from '@features/course/services/course-helper'; -import { ActionSheetController, ModalController, NgZone, Platform, Translate } from '@singletons'; +import { ActionSheetController, ModalController, NgZone, Translate } from '@singletons'; import { CoreCoursesSelfEnrolPasswordComponent } from '../../../courses/components/self-enrol-password/self-enrol-password'; import { CoreNavigator } from '@services/navigator'; import { CoreUtils } from '@services/utils/utils'; @@ -39,6 +39,7 @@ import { Subscription } from 'rxjs'; import { CoreColors } from '@singletons/colors'; import { CoreText } from '@singletons/text'; import { CorePromisedValue } from '@classes/promised-value'; +import { CorePlatform } from '@services/platform'; const ENROL_BROWSER_METHODS = ['fee', 'paypal']; @@ -84,7 +85,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { constructor() { // Refresh the view when the app is resumed. - this.appResumeSubscription = Platform.resume.subscribe(() => { + this.appResumeSubscription = CorePlatform.resume.subscribe(() => { if (!this.waitingForBrowserEnrol || !this.dataLoaded) { return; } diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index 67cd03a3e..9ad406cd8 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -23,7 +23,7 @@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; import { CoreSiteWSPreSets, CoreSite } from '@classes/site'; import { CoreConstants } from '@/core/constants'; -import { makeSingleton, Platform, Translate } from '@singletons'; +import { makeSingleton, Translate } from '@singletons'; import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { @@ -52,6 +52,7 @@ import { asyncInstance, AsyncInstance } from '@/core/utils/async-instance'; import { CoreDatabaseTable } from '@classes/database/database-table'; import { CoreDatabaseCachingStrategy } from '@classes/database/database-table-proxy'; import { SQLiteDB } from '@classes/sqlitedb'; +import { CorePlatform } from '@services/platform'; const ROOT_CACHE_KEY = 'mmCourse:'; @@ -173,7 +174,7 @@ export class CoreCourseProvider { * Initialize. */ initialize(): void { - Platform.resume.subscribe(() => { + CorePlatform.resume.subscribe(() => { // Run the handler the app is open to keep user in online status. setTimeout(() => { CoreCronDelegate.forceCronHandlerExecution(CoreCourseLogCronHandler.name); diff --git a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts index 3c444a4ef..44a06bb56 100644 --- a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts +++ b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts @@ -33,7 +33,7 @@ import { CoreFilepool } from '@services/filepool'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; -import { Platform, Translate } from '@singletons'; +import { Translate } from '@singletons'; import { CoreEventFormActionData, CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEditorOffline } from '../../services/editor-offline'; import { CoreComponentsRegistry } from '@singletons/components-registry'; @@ -155,7 +155,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, this.canScanQR = CoreUtils.canScanQR(); this.isPhone = CoreScreen.isMobile; this.toolbarHidden = this.isPhone; - this.direction = Platform.isRTL ? 'rtl' : 'ltr'; + this.direction = CorePlatform.isRTL ? 'rtl' : 'ltr'; } /** @@ -269,7 +269,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, // Change the side when the language changes. this.languageChangedSubscription = Translate.onLangChange.subscribe(() => { setTimeout(() => { - this.direction = Platform.isRTL ? 'rtl' : 'ltr'; + this.direction = CorePlatform.isRTL ? 'rtl' : 'ltr'; }); }); } diff --git a/src/core/features/emulator/components/capture-media/capture-media.ts b/src/core/features/emulator/components/capture-media/capture-media.ts index 8a158181c..116ec54c4 100644 --- a/src/core/features/emulator/components/capture-media/capture-media.ts +++ b/src/core/features/emulator/components/capture-media/capture-media.ts @@ -21,7 +21,7 @@ import { CoreFile, CoreFileProvider } from '@services/file'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTimeUtils } from '@services/utils/time'; -import { Platform, ModalController, Media, Translate } from '@singletons'; +import { ModalController, Media, Translate } from '@singletons'; import { CoreError } from '@classes/errors/error'; import { CoreCaptureError } from '@classes/errors/captureerror'; import { CoreCanceledError } from '@classes/errors/cancelederror'; @@ -119,7 +119,7 @@ export class CoreEmulatorCaptureMediaComponent implements OnInit, OnDestroy { this.isCordovaAudioCapture = CorePlatform.isMobile() && this.isAudio; if (this.isCordovaAudioCapture) { - this.extension = Platform.is('ios') ? 'wav' : 'aac'; + this.extension = CorePlatform.is('ios') ? 'wav' : 'aac'; this.returnDataUrl = false; } } @@ -153,7 +153,7 @@ export class CoreEmulatorCaptureMediaComponent implements OnInit, OnDestroy { // Now create the media instance. let absolutePath = CoreText.concatenatePaths(CoreFile.getBasePathInstant(), this.filePath); - if (Platform.is('ios')) { + if (CorePlatform.is('ios')) { // In iOS we need to remove the file:// part. absolutePath = absolutePath.replace(/^file:\/\//, ''); } diff --git a/src/core/features/emulator/emulator.module.ts b/src/core/features/emulator/emulator.module.ts index 70d1ae44b..227648524 100644 --- a/src/core/features/emulator/emulator.module.ts +++ b/src/core/features/emulator/emulator.module.ts @@ -13,63 +13,21 @@ // limitations under the License. import { APP_INITIALIZER, NgModule } from '@angular/core'; -import { Platform } from '@ionic/angular'; -import { CoreEmulatorHelperProvider } from './services/emulator-helper'; +import { CoreEmulatorHelper } from './services/emulator-helper'; import { CoreEmulatorComponentsModule } from './components/components.module'; // Ionic Native services. -import { Badge } from '@ionic-native/badge/ngx'; import { Camera } from '@ionic-native/camera/ngx'; -import { Chooser } from '@ionic-native/chooser/ngx'; import { Clipboard } from '@ionic-native/clipboard/ngx'; -import { Device } from '@ionic-native/device/ngx'; -import { Diagnostic } from '@ionic-native/diagnostic/ngx'; import { File } from '@ionic-native/file/ngx'; import { FileOpener } from '@ionic-native/file-opener/ngx'; import { FileTransfer } from '@ionic-native/file-transfer/ngx'; import { Geolocation } from '@ionic-native/geolocation/ngx'; -import { HTTP } from '@ionic-native/http/ngx'; import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; -import { WebView } from '@ionic-native/ionic-webview/ngx'; -import { Keyboard } from '@ionic-native/keyboard/ngx'; -import { LocalNotifications } from '@ionic-native/local-notifications/ngx'; -import { Media } from '@ionic-native/media/ngx'; import { MediaCapture } from '@ionic-native/media-capture/ngx'; -import { Push } from '@ionic-native/push/ngx'; -import { QRScanner } from '@ionic-native/qr-scanner/ngx'; -import { SplashScreen } from '@ionic-native/splash-screen/ngx'; -import { SQLite } from '@ionic-native/sqlite/ngx'; -import { StatusBar } from '@ionic-native/status-bar/ngx'; -import { WebIntent } from '@ionic-native/web-intent/ngx'; import { Zip } from '@ionic-native/zip/ngx'; -export const IONIC_NATIVE_SERVICES = [ - Badge, - Camera, - Chooser, - Clipboard, - Device, - Diagnostic, - File, - FileOpener, - FileTransfer, - Geolocation, - HTTP, - InAppBrowser, - Keyboard, - LocalNotifications, - Media, - MediaCapture, - Push, - QRScanner, - SplashScreen, - StatusBar, - SQLite, - WebIntent, - WebView, - Zip, -]; // Mock services. import { CameraMock } from './services/camera'; import { ClipboardMock } from './services/clipboard'; @@ -80,6 +38,7 @@ import { GeolocationMock } from './services/geolocation'; import { InAppBrowserMock } from './services/inappbrowser'; import { MediaCaptureMock } from './services/media-capture'; import { ZipMock } from './services/zip'; +import { CorePlatform } from '@services/platform'; /** * This module handles the emulation of Cordova plugins in browser and desktop. @@ -91,81 +50,54 @@ import { ZipMock } from './services/zip'; * functions we check if the app is running in mobile or not, and then provide the right service to use. */ @NgModule({ - declarations: [ - ], imports: [ CoreEmulatorComponentsModule, ], providers: [ - Badge, { provide: Camera, - deps: [Platform], - useFactory: (platform: Platform): Camera => platform.is('cordova') ? new Camera() : new CameraMock(), + useFactory: (): Camera => CorePlatform.is('cordova') ? new Camera() : new CameraMock(), }, - Chooser, { provide: Clipboard, - deps: [Platform], // Use platform instead of AppProvider to prevent errors with singleton injection. - useFactory: (platform: Platform): Clipboard => platform.is('cordova') ? new Clipboard() : new ClipboardMock(), + useFactory: (): Clipboard => CorePlatform.is('cordova') ? new Clipboard() : new ClipboardMock(), }, - Device, - Diagnostic, { provide: File, - deps: [Platform], - useFactory: (platform: Platform): File => platform.is('cordova') ? new File() : new FileMock(), + useFactory: (): File => CorePlatform.is('cordova') ? new File() : new FileMock(), }, { provide: FileOpener, - deps: [Platform], - useFactory: (platform: Platform): FileOpener => platform.is('cordova') ? new FileOpener() : new FileOpenerMock(), + useFactory: (): FileOpener => CorePlatform.is('cordova') ? new FileOpener() : new FileOpenerMock(), }, { provide: FileTransfer, - deps: [Platform], - useFactory: (platform: Platform): FileTransfer => platform.is('cordova') ? new FileTransfer() : new FileTransferMock(), + useFactory: (): FileTransfer => CorePlatform.is('cordova') ? new FileTransfer() : new FileTransferMock(), }, { provide: Geolocation, - deps: [Platform], - useFactory: (platform: Platform): Geolocation => platform.is('cordova') ? new Geolocation() : new GeolocationMock(), + useFactory: (): Geolocation => CorePlatform.is('cordova') ? new Geolocation() : new GeolocationMock(), }, - HTTP, { provide: InAppBrowser, - deps: [Platform], - useFactory: (platform: Platform): InAppBrowser => platform.is('cordova') ? new InAppBrowser() : new InAppBrowserMock(), + useFactory: (): InAppBrowser => CorePlatform.is('cordova') ? new InAppBrowser() : new InAppBrowserMock(), }, - Keyboard, - LocalNotifications, - Media, { provide: MediaCapture, - deps: [Platform], - useFactory: (platform: Platform): MediaCapture => platform.is('cordova') ? new MediaCapture() : new MediaCaptureMock(), + useFactory: (): MediaCapture => CorePlatform.is('cordova') ? new MediaCapture() : new MediaCaptureMock(), }, - Push, - QRScanner, - SplashScreen, - SQLite, - StatusBar, - WebIntent, - WebView, { provide: Zip, - deps: [Platform, File], - useFactory: (platform: Platform, file: File): Zip => platform.is('cordova') ? new Zip() : new ZipMock(file), + useFactory: (): Zip => CorePlatform.is('cordova') ? new Zip() : new ZipMock(), }, { provide: APP_INITIALIZER, - deps: [Platform, CoreEmulatorHelperProvider], - useFactory: (platform: Platform, helperProvider: CoreEmulatorHelperProvider) => () => { - if (platform.is('cordova')) { + useFactory: () => () => { + if (CorePlatform.is('cordova')) { return; } - return helperProvider.load(); + return CoreEmulatorHelper.load(); }, multi: true, }, diff --git a/src/core/features/emulator/services/emulator-helper.ts b/src/core/features/emulator/services/emulator-helper.ts index d6cd71f86..dd9e9da64 100644 --- a/src/core/features/emulator/services/emulator-helper.ts +++ b/src/core/features/emulator/services/emulator-helper.ts @@ -13,10 +13,9 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { File } from '@ionic-native/file/ngx'; import { CoreFile } from '@services/file'; -import { CoreUtils } from '@services/utils/utils'; +import { File, makeSingleton } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { FileMock } from './file'; import { FileTransferErrorMock } from './file-transfer'; @@ -29,9 +28,7 @@ export class CoreEmulatorHelperProvider { protected logger: CoreLogger; - constructor( - protected file: File, - ) { + constructor() { this.logger = CoreLogger.getInstance('CoreEmulatorHelper'); } @@ -40,18 +37,18 @@ export class CoreEmulatorHelperProvider { * * @return Promise resolved when loaded. */ - load(): Promise { - const promises: Promise[] = []; - + async load(): Promise { window.FileTransferError = FileTransferErrorMock; - promises.push(( this.file).load().then((basePath: string) => { + const fileService = File.instance; + + if (fileService instanceof FileMock) { + const basePath = await fileService.load(); + CoreFile.setHTMLBasePath(basePath); - - return; - })); - - return CoreUtils.allPromises(promises); + } } } + +export const CoreEmulatorHelper = makeSingleton(CoreEmulatorHelperProvider); diff --git a/src/core/features/emulator/services/zip.ts b/src/core/features/emulator/services/zip.ts index 0420b2dce..bfc0a9c4e 100644 --- a/src/core/features/emulator/services/zip.ts +++ b/src/core/features/emulator/services/zip.ts @@ -13,10 +13,10 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { File } from '@ionic-native/file/ngx'; import { Zip } from '@ionic-native/zip/ngx'; import * as JSZip from 'jszip'; import { CoreText } from '@singletons/text'; +import { File } from '@singletons'; /** * Emulates the Cordova Zip plugin in browser. @@ -24,10 +24,6 @@ import { CoreText } from '@singletons/text'; @Injectable() export class ZipMock extends Zip { - constructor(private file: File) { - super(); - } - /** * Create a directory. It creates all the foldes in dirPath 1 by 1 to prevent errors. * @@ -42,7 +38,7 @@ export class ZipMock extends Zip { for (let i = 0; i < folders.length; i++) { const folder = folders[i]; - await this.file.createDir(destination, folder, true); + await File.createDir(destination, folder, true); // Folder created, add it to the destination path. destination = CoreText.concatenatePaths(destination, folder); @@ -69,7 +65,7 @@ export class ZipMock extends Zip { try { // Read the file first. - const data = await this.file.readAsArrayBuffer(sourceDir, sourceName); + const data = await File.readAsArrayBuffer(sourceDir, sourceName); // Now load the file using the JSZip library. await zip.loadAsync(data); @@ -83,7 +79,7 @@ export class ZipMock extends Zip { const destParent = destination.substring(0, destination.lastIndexOf('/')); const destFolderName = destination.substring(destination.lastIndexOf('/') + 1); - await this.file.createDir(destParent, destFolderName, true); + await File.createDir(destParent, destFolderName, true); const total = Object.keys(zip.files).length; let loaded = 0; @@ -107,7 +103,7 @@ export class ZipMock extends Zip { // File read and parent folder created, now write the file. const parentFolder = CoreText.concatenatePaths(destination, fileDir); - await this.file.writeFile(parentFolder, fileName, fileData, { replace: true }); + await File.writeFile(parentFolder, fileName, fileData, { replace: true }); } else { // It's a folder, create it if it doesn't exist. await this.createDir(destination, name); diff --git a/src/core/features/features.module.ts b/src/core/features/features.module.ts index b954b83d1..e5c8ee34f 100644 --- a/src/core/features/features.module.ts +++ b/src/core/features/features.module.ts @@ -41,6 +41,7 @@ import { CoreUserToursModule } from './usertours/user-tours.module'; import { CoreUserModule } from './user/user.module'; import { CoreViewerModule } from './viewer/viewer.module'; import { CoreXAPIModule } from './xapi/xapi.module'; +import { CoreNativeModule } from '@features/native/native.module'; @NgModule({ imports: [ @@ -50,13 +51,13 @@ import { CoreXAPIModule } from './xapi/xapi.module'; CoreCourseModule, CoreCoursesModule, CoreEditorModule, - CoreEmulatorModule, CoreFileUploaderModule, CoreFilterModule, CoreGradesModule, CoreH5PModule, CoreLoginModule, CoreMainMenuModule, + CoreNativeModule, CorePushNotificationsModule, CoreQuestionModule, CoreRatingModule, @@ -71,6 +72,9 @@ import { CoreXAPIModule } from './xapi/xapi.module'; CoreUserModule, CoreViewerModule, CoreXAPIModule, + + // Import last to allow overrides. + CoreEmulatorModule, ], }) export class CoreFeaturesModule {} diff --git a/src/core/features/fileuploader/services/fileuploader-helper.ts b/src/core/features/fileuploader/services/fileuploader-helper.ts index 6806e3122..6f160a070 100644 --- a/src/core/features/fileuploader/services/fileuploader-helper.ts +++ b/src/core/features/fileuploader/services/fileuploader-helper.ts @@ -26,7 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; -import { makeSingleton, Translate, Camera, Chooser, Platform, ActionSheetController } from '@singletons'; +import { makeSingleton, Translate, Camera, Chooser, ActionSheetController } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreCanceledError } from '@classes/errors/cancelederror'; import { CoreError } from '@classes/errors/error'; @@ -644,8 +644,8 @@ export class CoreFileUploaderHelperProvider { options.popoverOptions = { x: 10, y: 10, - width: Platform.width() - 200, - height: Platform.height() - 200, + width: CorePlatform.width() - 200, + height: CorePlatform.height() - 200, arrowDir: Camera.PopoverArrowDirection.ARROW_ANY, }; diff --git a/src/core/features/login/pages/forgotten-password/forgotten-password.ts b/src/core/features/login/pages/forgotten-password/forgotten-password.ts index e6aa8a6b0..c88c9d283 100644 --- a/src/core/features/login/pages/forgotten-password/forgotten-password.ts +++ b/src/core/features/login/pages/forgotten-password/forgotten-password.ts @@ -17,10 +17,11 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreLoginHelper } from '@features/login/services/login-helper'; -import { Translate, Platform } from '@singletons'; +import { Translate } from '@singletons'; import { CoreWSExternalWarning } from '@services/ws'; import { CoreNavigator } from '@services/navigator'; import { CoreForms } from '@singletons/form'; +import { CorePlatform } from '@services/platform'; /** * Page to recover a forgotten password. @@ -55,7 +56,7 @@ export class CoreLoginForgottenPasswordPage implements OnInit { } this.siteUrl = siteUrl; - this.autoFocus = Platform.is('tablet'); + this.autoFocus = CorePlatform.is('tablet'); this.myForm = this.formBuilder.group({ field: ['username', Validators.required], value: [CoreNavigator.getRouteParam('username') || '', Validators.required], diff --git a/src/core/features/native/native.module.ts b/src/core/features/native/native.module.ts new file mode 100644 index 000000000..3a8887ca0 --- /dev/null +++ b/src/core/features/native/native.module.ts @@ -0,0 +1,97 @@ +// (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 { NgModule } from '@angular/core'; + +import { Badge } from '@ionic-native/badge/ngx'; +import { Camera } from '@ionic-native/camera/ngx'; +import { Chooser } from '@ionic-native/chooser/ngx'; +import { Clipboard } from '@ionic-native/clipboard/ngx'; +import { Device } from '@ionic-native/device/ngx'; +import { Diagnostic } from '@ionic-native/diagnostic/ngx'; +import { File } from '@ionic-native/file/ngx'; +import { FileOpener } from '@ionic-native/file-opener/ngx'; +import { FileTransfer } from '@ionic-native/file-transfer/ngx'; +import { Geolocation } from '@ionic-native/geolocation/ngx'; +import { HTTP } from '@ionic-native/http/ngx'; +import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; +import { WebView } from '@ionic-native/ionic-webview/ngx'; +import { Keyboard } from '@ionic-native/keyboard/ngx'; +import { LocalNotifications } from '@ionic-native/local-notifications/ngx'; +import { Media } from '@ionic-native/media/ngx'; +import { MediaCapture } from '@ionic-native/media-capture/ngx'; +import { Push } from '@ionic-native/push/ngx'; +import { QRScanner } from '@ionic-native/qr-scanner/ngx'; +import { SplashScreen } from '@ionic-native/splash-screen/ngx'; +import { SQLite } from '@ionic-native/sqlite/ngx'; +import { StatusBar } from '@ionic-native/status-bar/ngx'; +import { WebIntent } from '@ionic-native/web-intent/ngx'; +import { Zip } from '@ionic-native/zip/ngx'; + +export const CORE_NATIVE_SERVICES = [ + Badge, + Camera, + Chooser, + Clipboard, + Device, + Diagnostic, + File, + FileOpener, + FileTransfer, + Geolocation, + HTTP, + InAppBrowser, + Keyboard, + LocalNotifications, + Media, + MediaCapture, + Push, + QRScanner, + SplashScreen, + StatusBar, + SQLite, + WebIntent, + WebView, + Zip, +]; + +@NgModule({ + providers: [ + Badge, + Camera, + Chooser, + Clipboard, + Device, + Diagnostic, + File, + FileOpener, + FileTransfer, + Geolocation, + HTTP, + InAppBrowser, + Keyboard, + LocalNotifications, + Media, + MediaCapture, + Push, + QRScanner, + SplashScreen, + SQLite, + StatusBar, + WebIntent, + WebView, + Zip, + ], +}) +export class CoreNativeModule {} diff --git a/src/core/features/pushnotifications/services/pushnotifications.ts b/src/core/features/pushnotifications/services/pushnotifications.ts index cae2c2b49..e817633bf 100644 --- a/src/core/features/pushnotifications/services/pushnotifications.ts +++ b/src/core/features/pushnotifications/services/pushnotifications.ts @@ -25,7 +25,7 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreConfig } from '@services/config'; import { CoreConstants } from '@/core/constants'; import { CoreSite, CoreSiteInfo } from '@classes/site'; -import { makeSingleton, Badge, Push, Device, Translate, Platform, ApplicationInit, NgZone } from '@singletons'; +import { makeSingleton, Badge, Push, Device, Translate, ApplicationInit, NgZone } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreEvents } from '@singletons/events'; import { @@ -153,7 +153,7 @@ export class CorePushNotificationsProvider { * @return Promise resolved when done. */ protected async initializeDefaultChannel(): Promise { - await Platform.ready(); + await CorePlatform.ready(); // Create the default channel. this.createDefaultChannel(); diff --git a/src/core/features/settings/pages/dev/dev.ts b/src/core/features/settings/pages/dev/dev.ts index 913708872..63be91d59 100644 --- a/src/core/features/settings/pages/dev/dev.ts +++ b/src/core/features/settings/pages/dev/dev.ts @@ -15,10 +15,10 @@ import { Component, OnInit } from '@angular/core'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; import { CoreUserTours } from '@features/usertours/services/user-tours'; +import { CorePlatform } from '@services/platform'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { Platform } from '@singletons'; /** * Page that displays the developer options. @@ -45,7 +45,7 @@ export class CoreSettingsDevPage implements OnInit { siteId: string | undefined; async ngOnInit(): Promise { - this.rtl = Platform.isRTL; + this.rtl = CorePlatform.isRTL; this.RTLChanged(); this.forceSafeAreaMargins = document.documentElement.classList.contains('force-safe-area-margins'); diff --git a/src/core/features/settings/pages/deviceinfo/deviceinfo.ts b/src/core/features/settings/pages/deviceinfo/deviceinfo.ts index cae87a52d..b00cc0dae 100644 --- a/src/core/features/settings/pages/deviceinfo/deviceinfo.ts +++ b/src/core/features/settings/pages/deviceinfo/deviceinfo.ts @@ -16,7 +16,7 @@ import { CoreApp } from '@services/app'; import { Component, OnDestroy } from '@angular/core'; import { CoreConstants } from '@/core/constants'; import { CoreLocalNotifications } from '@services/local-notifications'; -import { Device, Platform, Translate, NgZone } from '@singletons'; +import { Device, Translate, NgZone } from '@singletons'; import { CoreLang } from '@services/lang'; import { CoreFile } from '@services/file'; import { CoreSites } from '@services/sites'; @@ -110,7 +110,7 @@ export class CoreSettingsDeviceInfoPage implements OnDestroy { } if (CorePlatform.isMobile()) { - this.deviceInfo.deviceType = Platform.is('tablet') ? 'tablet' : 'phone'; + this.deviceInfo.deviceType = CorePlatform.is('tablet') ? 'tablet' : 'phone'; if (CoreApp.isAndroid()) { this.deviceInfo.deviceOs = 'android'; this.deviceOsTranslated = 'Android'; diff --git a/src/core/features/sharedfiles/services/sharedfiles-helper.ts b/src/core/features/sharedfiles/services/sharedfiles-helper.ts index 1deb69771..43c01ae83 100644 --- a/src/core/features/sharedfiles/services/sharedfiles-helper.ts +++ b/src/core/features/sharedfiles/services/sharedfiles-helper.ts @@ -23,7 +23,7 @@ import { CoreFile } from '@services/file'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { AlertController, ApplicationInit, makeSingleton, Platform, Translate } from '@singletons'; +import { AlertController, ApplicationInit, makeSingleton, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; import { CoreSharedFilesListModalComponent } from '../components/list-modal/list-modal'; @@ -31,6 +31,7 @@ import { CoreSharedFiles } from './sharedfiles'; import { SHAREDFILES_PAGE_NAME } from '../sharedfiles.module'; import { CoreSharedFilesChooseSitePage } from '../pages/choose-site/choose-site'; import { CoreError } from '@classes/errors/error'; +import { CorePlatform } from '@services/platform'; /** * Helper service to share files with the app. @@ -57,7 +58,7 @@ export class CoreSharedFilesHelperProvider { // Check if there are new files at app start and when the app is resumed. this.searchIOSNewSharedFiles(); - Platform.resume.subscribe(() => { + CorePlatform.resume.subscribe(() => { // Wait a bit to make sure that APP_LAUNCHED_URL is treated before this callback. setTimeout(() => { if (Date.now() - lastCheck < 1000) { diff --git a/src/core/features/usertours/classes/popover-layout.ts b/src/core/features/usertours/classes/popover-layout.ts index e218f2be0..79b4e5edd 100644 --- a/src/core/features/usertours/classes/popover-layout.ts +++ b/src/core/features/usertours/classes/popover-layout.ts @@ -13,7 +13,7 @@ // limitations under the License. import { CoreStyles, renderInlineStyles } from '@/core/utils/style-helpers'; -import { Platform } from '@singletons'; +import { CorePlatform } from '@services/platform'; import { CoreUserToursAlignment, CoreUserToursSide } from '../services/user-tours'; const ARROW_HEIGHT = 22; @@ -54,8 +54,12 @@ export class CoreUserToursPopoverLayout { [CoreUserToursSide.Bottom]: this.calculateWrapperBottomSideStyles, [CoreUserToursSide.Right]: this.calculateWrapperRightSideStyles, [CoreUserToursSide.Left]: this.calculateWrapperLeftSideStyles, - [CoreUserToursSide.Start]: Platform.isRTL ? this.calculateWrapperRightSideStyles : this.calculateWrapperLeftSideStyles, - [CoreUserToursSide.End]: Platform.isRTL ? this.calculateWrapperLeftSideStyles : this.calculateWrapperRightSideStyles, + [CoreUserToursSide.Start]: CorePlatform.isRTL + ? this.calculateWrapperRightSideStyles + : this.calculateWrapperLeftSideStyles, + [CoreUserToursSide.End]: CorePlatform.isRTL + ? this.calculateWrapperLeftSideStyles + : this.calculateWrapperRightSideStyles, }; sideHandlers[this.side].call(this); @@ -69,11 +73,11 @@ export class CoreUserToursPopoverLayout { */ private calculateWrapperHorizontalAlignmentStyles(): void { const horizontalAlignmentHandlers: Record void> ={ - [CoreUserToursAlignment.Start]: Platform.isRTL + [CoreUserToursAlignment.Start]: CorePlatform.isRTL ? this.calculateWrapperRightAlignmentStyles : this.calculateWrapperLeftAlignmentStyles, [CoreUserToursAlignment.Center]: this.calculateWrapperCenterHorizontalAlignmentStyles, - [CoreUserToursAlignment.End]: Platform.isRTL + [CoreUserToursAlignment.End]: CorePlatform.isRTL ? this.calculateWrapperLeftAlignmentStyles : this.calculateWrapperRightAlignmentStyles, }; diff --git a/src/core/initializers/initialize-user-agent.ts b/src/core/initializers/initialize-user-agent.ts index f6e914d90..2b87862be 100644 --- a/src/core/initializers/initialize-user-agent.ts +++ b/src/core/initializers/initialize-user-agent.ts @@ -13,14 +13,14 @@ // limitations under the License. import { CorePlatform } from '@services/platform'; -import { NativeHttp, Platform } from '@singletons'; +import { NativeHttp } from '@singletons'; export default async function(): Promise { if (!CorePlatform.isMobile()) { return; } - await Platform.ready(); + await CorePlatform.ready(); NativeHttp.setHeader('*', 'User-Agent', navigator.userAgent); } diff --git a/src/core/initializers/inject-ios-scripts.ts b/src/core/initializers/inject-ios-scripts.ts index cfd717666..eac4cb3b6 100644 --- a/src/core/initializers/inject-ios-scripts.ts +++ b/src/core/initializers/inject-ios-scripts.ts @@ -13,11 +13,11 @@ // limitations under the License. import { CoreApp } from '@services/app'; +import { CorePlatform } from '@services/platform'; import { CoreIframeUtils } from '@services/utils/iframe'; -import { Platform } from '@singletons'; export default async function(): Promise { - await Platform.ready(); + await CorePlatform.ready(); if (!CoreApp.isIOS() || !('WKUserScript' in window)) { return; diff --git a/src/core/initializers/override-window-open.ts b/src/core/initializers/override-window-open.ts index 2dc7c5ba4..04e4ec995 100644 --- a/src/core/initializers/override-window-open.ts +++ b/src/core/initializers/override-window-open.ts @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Platform } from '@singletons'; +import { CorePlatform } from '@services/platform'; export default async function(): Promise { - await Platform.ready(); + await CorePlatform.ready(); if (!window.cordova?.InAppBrowser) { return; diff --git a/src/core/initializers/wait-for-platform-ready.ts b/src/core/initializers/wait-for-platform-ready.ts index 483289334..7604edb5a 100644 --- a/src/core/initializers/wait-for-platform-ready.ts +++ b/src/core/initializers/wait-for-platform-ready.ts @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Platform } from '@singletons'; +import { CorePlatform } from '@services/platform'; export default async function(): Promise { - await Platform.ready(); + await CorePlatform.ready(); } diff --git a/src/core/services/app.ts b/src/core/services/app.ts index 69222deff..a734676e8 100644 --- a/src/core/services/app.ts +++ b/src/core/services/app.ts @@ -18,7 +18,7 @@ import { CoreDB } from '@services/db'; import { CoreEvents } from '@singletons/events'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; -import { makeSingleton, Keyboard, StatusBar, Platform, Device } from '@singletons'; +import { makeSingleton, Keyboard, StatusBar, Device } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreColors } from '@singletons/colors'; import { DBNAME, SCHEMA_VERSIONS_TABLE_NAME, SCHEMA_VERSIONS_TABLE_SCHEMA, SchemaVersionsDBEntry } from '@services/database/app'; @@ -227,7 +227,7 @@ export class CoreAppProvider { * @return Whether the app is running in an Android mobile or tablet device. */ isAndroid(): boolean { - return CorePlatform.isMobile() && Platform.is('android'); + return CorePlatform.isMobile() && CorePlatform.is('android'); } /** @@ -246,7 +246,7 @@ export class CoreAppProvider { * @return Whether the app is running in an iOS mobile or tablet device. */ isIOS(): boolean { - return CorePlatform.isMobile() && !Platform.is('android'); + return CorePlatform.isMobile() && !CorePlatform.is('android'); } /** @@ -322,7 +322,7 @@ export class CoreAppProvider { * @return Whether the app the current window is wider than a mobile. */ isWide(): boolean { - return Platform.width() > 768; + return CorePlatform.width() > 768; } /** @@ -490,7 +490,7 @@ export class CoreAppProvider { deferred = null; }; - resumeSubscription = Platform.resume.subscribe(stopWaiting); + resumeSubscription = CorePlatform.resume.subscribe(stopWaiting); timeoutId = timeout ? window.setTimeout(stopWaiting, timeout) : null; await deferred; diff --git a/src/core/services/db.ts b/src/core/services/db.ts index 3bbf36f8c..df8ce5bb9 100644 --- a/src/core/services/db.ts +++ b/src/core/services/db.ts @@ -17,8 +17,9 @@ import { Injectable } from '@angular/core'; import { SQLiteDB } from '@classes/sqlitedb'; import { SQLiteDBMock } from '@features/emulator/classes/sqlitedb'; import { CoreBrowser } from '@singletons/browser'; -import { makeSingleton, SQLite, Platform } from '@singletons'; +import { makeSingleton, SQLite } from '@singletons'; import { CoreAppProvider } from './app'; +import { CorePlatform } from '@services/platform'; const tableNameRegex = new RegExp([ '^SELECT.*FROM ([^ ]+)', @@ -208,7 +209,7 @@ export class CoreDbProvider { */ getDB(name: string, forceNew?: boolean): SQLiteDB { if (this.dbInstances[name] === undefined || forceNew) { - if (Platform.is('cordova')) { + if (CorePlatform.is('cordova')) { this.dbInstances[name] = new SQLiteDB(name); } else { this.dbInstances[name] = new SQLiteDBMock(name); @@ -241,7 +242,7 @@ export class CoreDbProvider { location: 'default', }); } - } else if (Platform.is('cordova')) { + } else if (CorePlatform.is('cordova')) { return SQLite.deleteDatabase({ name, location: 'default', diff --git a/src/core/services/file.ts b/src/core/services/file.ts index 5b5eea530..0d8c96388 100644 --- a/src/core/services/file.ts +++ b/src/core/services/file.ts @@ -24,7 +24,7 @@ import { CoreConstants } from '@/core/constants'; import { CoreError } from '@classes/errors/error'; import { CoreLogger } from '@singletons/logger'; -import { makeSingleton, File, Zip, Platform, WebView } from '@singletons'; +import { makeSingleton, File, Zip, WebView } from '@singletons'; import { CoreFileEntry } from '@services/file-helper'; import { CoreText } from '@singletons/text'; import { CorePlatform } from '@services/platform'; @@ -137,7 +137,7 @@ export class CoreFileProvider { return; } - await Platform.ready(); + await CorePlatform.ready(); if (CoreApp.isAndroid()) { this.basePath = File.externalApplicationStorageDirectory || this.basePath; diff --git a/src/core/services/lang.ts b/src/core/services/lang.ts index d76c6153a..67efec309 100644 --- a/src/core/services/lang.ts +++ b/src/core/services/lang.ts @@ -19,10 +19,11 @@ import { LangChangeEvent } from '@ngx-translate/core'; import { CoreAppProvider } from '@services/app'; import { CoreConfig } from '@services/config'; import { CoreSubscriptions } from '@singletons/subscriptions'; -import { makeSingleton, Translate, Platform, Http } from '@singletons'; +import { makeSingleton, Translate, Http } from '@singletons'; import * as moment from 'moment'; import { CoreSite } from '../classes/site'; +import { CorePlatform } from '@services/platform'; /* * Service to handle language features, like changing the current language. @@ -57,7 +58,7 @@ export class CoreLangProvider { * Init language. */ protected async initializeCurrentLanguage(): Promise { - await Platform.ready(); + await CorePlatform.ready(); let language: string; diff --git a/src/core/services/local-notifications.ts b/src/core/services/local-notifications.ts index c7abe1bba..17bb9a503 100644 --- a/src/core/services/local-notifications.ts +++ b/src/core/services/local-notifications.ts @@ -24,7 +24,7 @@ import { SQLiteDB } from '@classes/sqlitedb'; import { CoreQueueRunner } from '@classes/queue-runner'; import { CoreError } from '@classes/errors/error'; import { CoreConstants } from '@/core/constants'; -import { makeSingleton, NgZone, Platform, Translate, LocalNotifications, Push } from '@singletons'; +import { makeSingleton, NgZone, Translate, LocalNotifications, Push } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { APP_SCHEMA, @@ -34,6 +34,7 @@ import { CodeRequestsQueueItem, } from '@services/database/local-notifications'; import { CorePromisedValue } from '@classes/promised-value'; +import { CorePlatform } from '@services/platform'; /** * Service to handle local notifications. @@ -68,7 +69,7 @@ export class CoreLocalNotificationsProvider { * Init some properties. */ async initialize(): Promise { - await Platform.ready(); + await CorePlatform.ready(); if (!this.isAvailable()) { return; diff --git a/src/core/services/platform.ts b/src/core/services/platform.ts index 294a4859a..e53152943 100644 --- a/src/core/services/platform.ts +++ b/src/core/services/platform.ts @@ -13,13 +13,14 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { makeSingleton, Platform } from '@singletons'; +import { Platform } from '@ionic/angular'; +import { makeSingleton } from '@singletons'; /** * Extend Ionic's Platform service. */ @Injectable({ providedIn: 'root' }) -export class CorePlatformService { +export class CorePlatformService extends Platform { /** * Checks if the app is running in a mobile or tablet device (Cordova). @@ -27,7 +28,7 @@ export class CorePlatformService { * @return Whether the app is running in a mobile or tablet device. */ isMobile(): boolean { - return Platform.is('cordova'); + return this.is('cordova'); } } diff --git a/src/core/services/screen.ts b/src/core/services/screen.ts index e733946b6..148eac683 100644 --- a/src/core/services/screen.ts +++ b/src/core/services/screen.ts @@ -16,8 +16,9 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { distinctUntilChanged, map } from 'rxjs/operators'; -import { makeSingleton, Platform } from '@singletons'; +import { makeSingleton } from '@singletons'; import { CoreEvents } from '@singletons/events'; +import { CorePlatform } from '@services/platform'; /** * Screen breakpoints. @@ -120,7 +121,7 @@ export class CoreScreenService { * Watch orientation changes. */ async watchOrientation(): Promise { - await Platform.ready(); + await CorePlatform.ready(); screen.orientation.addEventListener('change', () => { CoreEvents.trigger(CoreEvents.ORIENTATION_CHANGE, { orientation: this.orientation }); diff --git a/src/core/singletons/index.ts b/src/core/singletons/index.ts index 0ef9ac7fc..faa44981f 100644 --- a/src/core/singletons/index.ts +++ b/src/core/singletons/index.ts @@ -26,7 +26,6 @@ import { HttpClient } from '@angular/common/http'; import { DomSanitizer as DomSanitizerService } from '@angular/platform-browser'; import { - Platform as PlatformService, AngularDelegate as AngularDelegateService, AlertController as AlertControllerService, LoadingController as LoadingControllerService, @@ -202,7 +201,6 @@ export const Device = makeSingleton(DeviceService); // Convert some Angular and Ionic injectables to singletons. export const NgZone = makeSingleton(NgZoneService); export const Http = makeSingleton(HttpClient); -export const Platform = makeSingleton(PlatformService); export const ActionSheetController = makeSingleton(ActionSheetControllerService); export const AngularDelegate = makeSingleton(AngularDelegateService); export const AlertController = makeSingleton(AlertControllerService); diff --git a/src/testing/utils.ts b/src/testing/utils.ts index 3a097db93..44624a5f2 100644 --- a/src/testing/utils.ts +++ b/src/testing/utils.ts @@ -19,12 +19,13 @@ import { Observable, Subject } from 'rxjs'; import { sep } from 'path'; import { CORE_SITE_SCHEMAS } from '@services/sites'; -import { CoreSingletonProxy, Platform, Translate } from '@singletons'; +import { CoreSingletonProxy, Translate } from '@singletons'; import { CoreTextUtilsProvider } from '@services/utils/text'; import { TranslatePipeStub } from './stubs/pipes/translate'; import { CoreExternalContentDirectiveStub } from './stubs/directives/core-external-content'; import { CoreNetwork } from '@services/network'; +import { CorePlatform } from '@services/platform'; abstract class WrapperComponent { @@ -37,7 +38,12 @@ type ServiceInjectionToken = AbstractType | Type | string; let testBedInitialized = false; const textUtils = new CoreTextUtilsProvider(); const DEFAULT_SERVICE_SINGLETON_MOCKS: [CoreSingletonProxy, Record][] = [ - [Platform, mock({ is: () => false, ready: () => Promise.resolve(), resume: new Subject() })], + [CorePlatform, mock({ + is: () => false, + isMobile: () => false, + ready: () => Promise.resolve(), + resume: new Subject(), + })], [CoreNetwork, { onChange: () => new Observable() }], ];