diff --git a/src/addons/calendar/pages/day/day.ts b/src/addons/calendar/pages/day/day.ts index 1edf50164..88183fd6c 100644 --- a/src/addons/calendar/pages/day/day.ts +++ b/src/addons/calendar/pages/day/day.ts @@ -49,6 +49,7 @@ import { AddonCalendarEventsSource } from '@addons/calendar/classes/events-sourc import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreUrl } from '@singletons/url'; import { CoreTime } from '@singletons/time'; +import { CoreModals } from '@services/modals'; /** * Page that displays the calendar events for a certain day. @@ -375,7 +376,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { * Show the filter menu. */ async openFilter(): Promise { - await CoreDomUtils.openSideModal({ + await CoreModals.openSideModal({ component: AddonCalendarFilterComponent, componentProps: { courses: this.manager?.getSource().courses, diff --git a/src/addons/calendar/pages/index/index.ts b/src/addons/calendar/pages/index/index.ts index 0943286ae..7201116a0 100644 --- a/src/addons/calendar/pages/index/index.ts +++ b/src/addons/calendar/pages/index/index.ts @@ -32,6 +32,7 @@ import { AddonCalendarFilterComponent } from '../../components/filter/filter'; import { CoreNavigator } from '@services/navigator'; import { CoreConstants } from '@/core/constants'; import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager'; +import { CoreModals } from '@services/modals'; /** * Page that displays the calendar events. @@ -330,7 +331,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { * Show the filter menu. */ async openFilter(): Promise { - await CoreDomUtils.openSideModal({ + await CoreModals.openSideModal({ component: AddonCalendarFilterComponent, componentProps: { courses: this.courses, diff --git a/src/addons/enrol/guest/services/enrol-handler.ts b/src/addons/enrol/guest/services/enrol-handler.ts index 00c2a1313..cb5795dfb 100644 --- a/src/addons/enrol/guest/services/enrol-handler.ts +++ b/src/addons/enrol/guest/services/enrol-handler.ts @@ -25,6 +25,7 @@ import { CorePasswordModalResponse } from '@components/password-modal/password-m import { CoreDomUtils } from '@services/utils/dom'; import { CoreWSError } from '@classes/errors/wserror'; import { CoreEnrol, CoreEnrolEnrolmentMethod } from '@features/enrol/services/enrol'; +import { CoreModals } from '@services/modals'; /** * Enrol handler. @@ -118,7 +119,7 @@ export class AddonEnrolGuestHandlerService implements CoreEnrolGuestHandler { }; try { - const response = await CoreDomUtils.promptPassword({ + const response = await CoreModals.promptPassword({ title: method.name, validator: validatePassword, }); diff --git a/src/addons/enrol/self/services/enrol-handler.ts b/src/addons/enrol/self/services/enrol-handler.ts index 5cc0589f0..c2838f53d 100644 --- a/src/addons/enrol/self/services/enrol-handler.ts +++ b/src/addons/enrol/self/services/enrol-handler.ts @@ -20,6 +20,7 @@ import { CorePasswordModalResponse } from '@components/password-modal/password-m import { CoreCoursesProvider } from '@features/courses/services/courses'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreEnrol, CoreEnrolEnrolmentMethod } from '@features/enrol/services/enrol'; +import { CoreModals } from '@services/modals'; /** * Enrol handler. @@ -145,7 +146,7 @@ export class AddonEnrolSelfHandlerService implements CoreEnrolSelfHandler { if (!response.validated) { try { - const response = await CoreDomUtils.promptPassword({ + const response = await CoreModals.promptPassword({ validator: validatePassword, title: method.name, placeholder: 'addon.enrol_self.password', diff --git a/src/addons/messages/pages/discussion/discussion.ts b/src/addons/messages/pages/discussion/discussion.ts index 78df7f2e3..19b55f398 100644 --- a/src/addons/messages/pages/discussion/discussion.ts +++ b/src/addons/messages/pages/discussion/discussion.ts @@ -47,6 +47,7 @@ import { CoreDom } from '@singletons/dom'; import { CoreKeyboard } from '@singletons/keyboard'; import { CoreText } from '@singletons/text'; import { CoreWait } from '@singletons/wait'; +import { CoreModals } from '@services/modals'; /** * Page that displays a message discussion page. @@ -1250,7 +1251,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView await import('@addons/messages/components/conversation-info/conversation-info.module'); // Display the group information. - const userId = await CoreDomUtils.openSideModal({ + const userId = await CoreModals.openSideModal({ component: AddonMessagesConversationInfoComponent, componentProps: { conversationId: this.conversationId, diff --git a/src/addons/mod/assign/classes/base-feedback-plugin-component.ts b/src/addons/mod/assign/classes/base-feedback-plugin-component.ts index 8af588332..31713b758 100644 --- a/src/addons/mod/assign/classes/base-feedback-plugin-component.ts +++ b/src/addons/mod/assign/classes/base-feedback-plugin-component.ts @@ -15,7 +15,7 @@ import { Component, Input } from '@angular/core'; import { CoreCanceledError } from '@classes/errors/cancelederror'; import { CoreError } from '@classes/errors/error'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { AddonModAssignFeedbackCommentsTextData } from '../feedback/comments/services/handler'; import { AddonModAssignAssign, AddonModAssignPlugin, AddonModAssignSubmission } from '../services/assign'; @@ -49,7 +49,7 @@ export class AddonModAssignFeedbackPluginBaseComponent implements IAddonModAssig await import('@addons/mod/assign/components/edit-feedback-modal/edit-feedback-modal'); // Create the navigation modal. - const modalData = await CoreDomUtils.openModal({ + const modalData = await CoreModals.openModal({ component: AddonModAssignEditFeedbackModalComponent, componentProps: { assign: this.assign, diff --git a/src/addons/mod/book/pages/contents/contents.ts b/src/addons/mod/book/pages/contents/contents.ts index 77b1f47ac..6376ddb63 100644 --- a/src/addons/mod/book/pages/contents/contents.ts +++ b/src/addons/mod/book/pages/contents/contents.ts @@ -40,6 +40,7 @@ import { import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreUrl } from '@singletons/url'; import { ADDON_MOD_BOOK_COMPONENT, AddonModBookNavStyle } from '../../constants'; +import { CoreModals } from '@services/modals'; /** * Page that displays a book contents. @@ -250,7 +251,7 @@ export class AddonModBookContentsPage implements OnInit, OnDestroy { // Create the toc modal. const visibleChapter = this.manager?.getSelectedItem(); - const modalData = await CoreDomUtils.openSideModal({ + const modalData = await CoreModals.openSideModal({ component: AddonModBookTocComponent, componentProps: { moduleId: this.cmId, diff --git a/src/addons/mod/chat/pages/chat/chat.ts b/src/addons/mod/chat/pages/chat/chat.ts index f1d770852..aa8de8521 100644 --- a/src/addons/mod/chat/pages/chat/chat.ts +++ b/src/addons/mod/chat/pages/chat/chat.ts @@ -31,6 +31,7 @@ import { CoreTime } from '@singletons/time'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreKeyboard } from '@singletons/keyboard'; import { CoreWait } from '@singletons/wait'; +import { CoreModals } from '@services/modals'; /** * Page that displays a chat session. @@ -187,7 +188,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave { */ async showChatUsers(): Promise { // Create the toc modal. - const modalData = await CoreDomUtils.openSideModal({ + const modalData = await CoreModals.openSideModal({ component: AddonModChatUsersModalComponent, componentProps: { sessionId: this.sessionId, diff --git a/src/addons/mod/data/components/index/index.ts b/src/addons/mod/data/components/index/index.ts index c8c029718..94264157d 100644 --- a/src/addons/mod/data/components/index/index.ts +++ b/src/addons/mod/data/components/index/index.ts @@ -51,6 +51,7 @@ import { AddonModDataTemplateType, AddonModDataTemplateMode, } from '../../constants'; +import { CoreModals } from '@services/modals'; const contentToken = ''; @@ -401,7 +402,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp async showSearch(): Promise { const { AddonModDataSearchModalComponent } = await import('@addons/mod/data/components/search-modal/search-modal'); - const modalData = await CoreDomUtils.openModal({ + const modalData = await CoreModals.openModal({ component: AddonModDataSearchModalComponent, componentProps: { search: this.search, diff --git a/src/addons/mod/imscp/pages/view/view.ts b/src/addons/mod/imscp/pages/view/view.ts index 7a96a3324..60e1cf34c 100644 --- a/src/addons/mod/imscp/pages/view/view.ts +++ b/src/addons/mod/imscp/pages/view/view.ts @@ -28,6 +28,7 @@ import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; import { AddonModImscpTocComponent } from '../../components/toc/toc'; import { AddonModImscp, AddonModImscpImscp, AddonModImscpTocItem } from '../../services/imscp'; +import { CoreModals } from '@services/modals'; /** * Page that displays a IMSCP content. @@ -273,7 +274,7 @@ export class AddonModImscpViewPage implements OnInit { */ async showToc(): Promise { // Create the toc modal. - const itemHref = await CoreDomUtils.openSideModal({ + const itemHref = await CoreModals.openSideModal({ component: AddonModImscpTocComponent, componentProps: { items: this.items, diff --git a/src/addons/mod/lesson/pages/player/player.ts b/src/addons/mod/lesson/pages/player/player.ts index 6c8228e11..85203bfba 100644 --- a/src/addons/mod/lesson/pages/player/player.ts +++ b/src/addons/mod/lesson/pages/player/player.ts @@ -55,6 +55,7 @@ import { AddonModLessonSync } from '../../services/lesson-sync'; import { CoreFormFields, CoreForms } from '@singletons/form'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { ADDON_MOD_LESSON_COMPONENT, AddonModLessonJumpTo } from '../../constants'; +import { CoreModals } from '@services/modals'; /** * Page that allows attempting and reviewing a lesson. @@ -829,7 +830,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { async showMenu(): Promise { this.menuShown = true; - await CoreDomUtils.openSideModal({ + await CoreModals.openSideModal({ component: AddonModLessonMenuModalPage, componentProps: { pageInstance: this, diff --git a/src/addons/mod/lesson/services/handlers/prefetch.ts b/src/addons/mod/lesson/services/handlers/prefetch.ts index 852a07d58..6df58a118 100644 --- a/src/addons/mod/lesson/services/handlers/prefetch.ts +++ b/src/addons/mod/lesson/services/handlers/prefetch.ts @@ -21,7 +21,7 @@ import { CoreFilepool } from '@services/filepool'; import { CoreGroups } from '@services/groups'; import { CoreFileSizeSum, CorePluginFileDelegate } from '@services/plugin-file-delegate'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { CoreUtils } from '@services/utils/utils'; import { CoreWSFile } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; @@ -136,7 +136,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref } // Create and show the modal. - const response = await CoreDomUtils.promptPassword({ + const response = await CoreModals.promptPassword({ title: 'addon.mod_lesson.enterpassword', placeholder: 'core.login.password', submit: 'addon.mod_lesson.continue', diff --git a/src/addons/mod/quiz/pages/player/player.ts b/src/addons/mod/quiz/pages/player/player.ts index c67450887..7a1b56f99 100644 --- a/src/addons/mod/quiz/pages/player/player.ts +++ b/src/addons/mod/quiz/pages/player/player.ts @@ -55,6 +55,7 @@ import { CoreWSError } from '@classes/errors/wserror'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT, AddonModQuizAttemptStates, ADDON_MOD_QUIZ_COMPONENT } from '../../constants'; import { CoreWait } from '@singletons/wait'; +import { CoreModals } from '@services/modals'; /** * Page that allows attempting a quiz. @@ -728,7 +729,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave { } // Create the navigation modal. - const modalData = await CoreDomUtils.openSideModal({ + const modalData = await CoreModals.openSideModal({ component: AddonModQuizNavigationModalComponent, componentProps: { navigation: this.navigation, diff --git a/src/addons/mod/quiz/pages/review/review.ts b/src/addons/mod/quiz/pages/review/review.ts index 524ebed9e..13c95f478 100644 --- a/src/addons/mod/quiz/pages/review/review.ts +++ b/src/addons/mod/quiz/pages/review/review.ts @@ -36,6 +36,7 @@ import { import { AddonModQuizHelper } from '../../services/quiz-helper'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { ADDON_MOD_QUIZ_COMPONENT } from '../../constants'; +import { CoreModals } from '@services/modals'; /** * Page that allows reviewing a quiz attempt. @@ -266,7 +267,7 @@ export class AddonModQuizReviewPage implements OnInit { async openNavigation(): Promise { // Create the navigation modal. - const modalData = await CoreDomUtils.openSideModal({ + const modalData = await CoreModals.openSideModal({ component: AddonModQuizNavigationModalComponent, componentProps: { navigation: this.navigation, diff --git a/src/addons/mod/quiz/services/handlers/prefetch.ts b/src/addons/mod/quiz/services/handlers/prefetch.ts index b6c17276b..9f30d9406 100644 --- a/src/addons/mod/quiz/services/handlers/prefetch.ts +++ b/src/addons/mod/quiz/services/handlers/prefetch.ts @@ -474,7 +474,6 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet * @param accessInfo Quiz access info. * @param attempt Attempt. * @param modOptions Other options. - * @param siteId Site ID. * @returns Promise resolved when done. */ protected async prefetchAttemptReview( diff --git a/src/addons/mod/quiz/services/quiz-helper.ts b/src/addons/mod/quiz/services/quiz-helper.ts index 2bc6d85ea..24f2e6337 100644 --- a/src/addons/mod/quiz/services/quiz-helper.ts +++ b/src/addons/mod/quiz/services/quiz-helper.ts @@ -40,6 +40,7 @@ import { import { QuestionDisplayOptionsMarks } from '@features/question/constants'; import { CoreGroups } from '@services/groups'; import { CoreTimeUtils } from '@services/utils/time'; +import { CoreModals } from '@services/modals'; /** * Helper service that provides some features for quiz. @@ -272,7 +273,7 @@ export class AddonModQuizHelperProvider { await import('@addons/mod/quiz/components/preflight-modal/preflight-modal'); // Create and show the modal. - const modalData = await CoreDomUtils.openModal>({ + const modalData = await CoreModals.openModal>({ component: AddonModQuizPreflightModalComponent, componentProps: { title: options.title, diff --git a/src/addons/mod/scorm/pages/player/player.ts b/src/addons/mod/scorm/pages/player/player.ts index c9d4f6aa5..f93df0c48 100644 --- a/src/addons/mod/scorm/pages/player/player.ts +++ b/src/addons/mod/scorm/pages/player/player.ts @@ -44,6 +44,7 @@ import { ADDON_MOD_SCORM_UPDATE_TOC_EVENT, } from '../../constants'; import { CoreWait } from '@singletons/wait'; +import { CoreModals } from '@services/modals'; /** * Page that allows playing a SCORM. @@ -513,7 +514,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { * Show the TOC. */ async openToc(): Promise { - const modalData = await CoreDomUtils.openSideModal({ + const modalData = await CoreModals.openSideModal({ component: AddonModScormTocComponent, componentProps: { toc: this.toc, diff --git a/src/addons/mod/wiki/components/index/index.ts b/src/addons/mod/wiki/components/index/index.ts index c9940f548..590245828 100644 --- a/src/addons/mod/wiki/components/index/index.ts +++ b/src/addons/mod/wiki/components/index/index.ts @@ -58,6 +58,7 @@ import { ADDON_MOD_WIKI_PAGE_CREATED_EVENT, ADDON_MOD_WIKI_PAGE_NAME, } from '../../constants'; +import { CoreModals } from '@services/modals'; /** * Component that displays a wiki entry page. @@ -665,7 +666,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp async openMap(): Promise { // Create the toc modal. const { AddonModWikiMapModalComponent } = await import('../map/map'); - const modalData = await CoreDomUtils.openSideModal({ + const modalData = await CoreModals.openSideModal({ component: AddonModWikiMapModalComponent, componentProps: { pages: this.subwikiPages, diff --git a/src/addons/mod/workshop/components/index/index.ts b/src/addons/mod/workshop/components/index/index.ts index 628d70853..ee4337778 100644 --- a/src/addons/mod/workshop/components/index/index.ts +++ b/src/addons/mod/workshop/components/index/index.ts @@ -21,7 +21,7 @@ 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 { CoreModals } from '@services/modals'; import { CoreUtils } from '@services/utils/utils'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { Subscription } from 'rxjs'; @@ -400,7 +400,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity const { AddonModWorkshopPhaseInfoModalComponent } = await import('@addons/mod/workshop/components/phase-modal/phase-modal'); - const modalData = await CoreDomUtils.openModal({ + const modalData = await CoreModals.openModal({ component: AddonModWorkshopPhaseInfoModalComponent, componentProps: { phases: CoreUtils.objectToArray(this.phases), diff --git a/src/addons/notes/pages/list/list.ts b/src/addons/notes/pages/list/list.ts index 840ef91dd..d4cc56a65 100644 --- a/src/addons/notes/pages/list/list.ts +++ b/src/addons/notes/pages/list/list.ts @@ -32,6 +32,7 @@ import { Translate } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreTime } from '@singletons/time'; import { CoreToasts, ToastDuration } from '@services/toasts'; +import { CoreModals } from '@services/modals'; /** * Page that displays a list of notes. @@ -197,7 +198,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy { const { AddonNotesAddComponent } = await import('@addons/notes/components/add/add-modal'); - const modalData = await CoreDomUtils.openModal({ + const modalData = await CoreModals.openModal({ component: AddonNotesAddComponent, componentProps: { userId: this.userId, diff --git a/src/core/classes/page-loads-manager.ts b/src/core/classes/page-loads-manager.ts index a67816df0..174f6a66d 100644 --- a/src/core/classes/page-loads-manager.ts +++ b/src/core/classes/page-loads-manager.ts @@ -13,7 +13,7 @@ // limitations under the License. import { CoreNavigator } from '@services/navigator'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { Subject } from 'rxjs'; import { AsyncDirective } from './async-directive'; import { PageLoadWatcher } from './page-load-watcher'; @@ -131,7 +131,7 @@ export class PageLoadsManager { const { CoreRefreshButtonModalComponent } = await import('@components/refresh-button-modal/refresh-button-modal'); - await CoreDomUtils.openModal({ + await CoreModals.openModal({ component: CoreRefreshButtonModalComponent, cssClass: 'core-modal-no-background core-modal-fullscreen', closeOnNavigate: true, diff --git a/src/core/components/combobox/combobox.ts b/src/core/components/combobox/combobox.ts index ddf7e75e8..e85060584 100644 --- a/src/core/components/combobox/combobox.ts +++ b/src/core/components/combobox/combobox.ts @@ -15,7 +15,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Translate } from '@singletons'; import { ModalOptions } from '@ionic/core'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; /** @@ -123,7 +123,7 @@ export class CoreComboboxComponent implements ControlValueAccessor { this.modalOptions.id = this.listboxId; } - const data = await CoreDomUtils.openModal(this.modalOptions); + const data = await CoreModals.openModal(this.modalOptions); this.expanded = false; if (data) { diff --git a/src/core/features/block/components/side-blocks-button/side-blocks-button.ts b/src/core/features/block/components/side-blocks-button/side-blocks-button.ts index 69ae1e0ac..77ca2aacb 100644 --- a/src/core/features/block/components/side-blocks-button/side-blocks-button.ts +++ b/src/core/features/block/components/side-blocks-button/side-blocks-button.ts @@ -16,7 +16,7 @@ import { Component, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; import { CoreCancellablePromise } from '@classes/cancellable-promise'; import { CoreUserTourDirectiveOptions } from '@directives/user-tour'; import { CoreUserToursAlignment, CoreUserToursSide } from '@features/usertours/services/user-tours'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { CoreDom } from '@singletons/dom'; import { CoreBlockSideBlocksTourComponent } from '../side-blocks-tour/side-blocks-tour'; import { CoreBlockSideBlocksComponent } from '../side-blocks/side-blocks'; @@ -68,7 +68,7 @@ export class CoreBlockSideBlocksButtonComponent implements OnInit, OnDestroy { * Open side blocks. */ openBlocks(): void { - CoreDomUtils.openSideModal({ + CoreModals.openSideModal({ component: CoreBlockSideBlocksComponent, componentProps: { contextLevel: this.contextLevel, diff --git a/src/core/features/contentlinks/services/contentlinks-helper.ts b/src/core/features/contentlinks/services/contentlinks-helper.ts index b7ba93788..4f63b6770 100644 --- a/src/core/features/contentlinks/services/contentlinks-helper.ts +++ b/src/core/features/contentlinks/services/contentlinks-helper.ts @@ -20,6 +20,7 @@ import { CoreSite } from '@classes/sites/site'; import { makeSingleton, Translate } from '@singletons'; import { CoreNavigator } from '@services/navigator'; import { CoreCustomURLSchemes } from '@services/urlschemes'; +import { CoreModals } from '@services/modals'; /** * Service that provides some features regarding content links. @@ -98,7 +99,7 @@ export class CoreContentLinksHelperProvider { const { CoreContentLinksChooseSiteModalComponent } = await import('@features/contentlinks/components/choose-site-modal/choose-site-modal'); - await CoreDomUtils.openModal({ + await CoreModals.openModal({ component: CoreContentLinksChooseSiteModalComponent, componentProps: { url: url, diff --git a/src/core/features/course/classes/main-resource-component.ts b/src/core/features/course/classes/main-resource-component.ts index d5c4f064c..a2e8c5d95 100644 --- a/src/core/features/course/classes/main-resource-component.ts +++ b/src/core/features/course/classes/main-resource-component.ts @@ -34,6 +34,7 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreUrl } from '@singletons/url'; import { CoreTime } from '@singletons/time'; import { CoreText } from '@singletons/text'; +import { CoreModals } from '@services/modals'; /** * Result of a resource download. @@ -424,7 +425,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, return; } - const data = await CoreDomUtils.openSideModal({ + const data = await CoreModals.openSideModal({ component: CoreCourseModuleSummaryComponent, componentProps: { moduleId: this.module.id, diff --git a/src/core/features/course/components/course-format/course-format.ts b/src/core/features/course/components/course-format/course-format.ts index 63ddb340f..e836d75d7 100644 --- a/src/core/features/course/components/course-format/course-format.ts +++ b/src/core/features/course/components/course-format/course-format.ts @@ -53,6 +53,7 @@ import { CoreUserTourDirectiveOptions } from '@directives/user-tour'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreBlockSideBlocksComponent } from '@features/block/components/side-blocks/side-blocks'; import { ContextLevel } from '@/core/constants'; +import { CoreModals } from '@services/modals'; /** * Component to display course contents using a certain format. If the format isn't found, use default one. @@ -316,7 +317,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.sectionChanged(section); } } else if (this.initialBlockInstanceId && this.displayBlocks && this.hasBlocks) { - CoreDomUtils.openSideModal({ + CoreModals.openSideModal({ component: CoreBlockSideBlocksComponent, componentProps: { contextLevel: ContextLevel.COURSE, @@ -431,7 +432,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { const { CoreCourseCourseIndexComponent } = await import('@features/course/components/course-index/course-index'); - const data = await CoreDomUtils.openModal({ + const data = await CoreModals.openModal({ component: CoreCourseCourseIndexComponent, initialBreakpoint: 1, breakpoints: [0, 1], diff --git a/src/core/features/course/pages/module-preview/module-preview.ts b/src/core/features/course/pages/module-preview/module-preview.ts index bbaf90c66..86219e53e 100644 --- a/src/core/features/course/pages/module-preview/module-preview.ts +++ b/src/core/features/course/pages/module-preview/module-preview.ts @@ -20,6 +20,7 @@ import { import { CoreCourse } from '@features/course/services/course'; import { CoreCourseHelper, CoreCourseModuleData, CoreCourseSection } from '@features/course/services/course-helper'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; +import { CoreModals } from '@services/modals'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -106,7 +107,7 @@ export class CoreCourseModulePreviewPage implements OnInit { return; } - const data = await CoreDomUtils.openSideModal({ + const data = await CoreModals.openSideModal({ component: CoreCourseModuleSummaryComponent, componentProps: { moduleId: this.module.id, diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index b3e31546f..f0671b3f4 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -75,6 +75,7 @@ import { CoreLocalNotifications } from '@services/local-notifications'; import { CoreEnrol } from '@features/enrol/services/enrol'; import { CoreEnrolAction, CoreEnrolDelegate } from '@features/enrol/services/enrol-delegate'; import { LazyRoutesModule } from '@/app/app-routing.module'; +import { CoreModals } from '@services/modals'; /** * Prefetch info of a module. @@ -2009,7 +2010,7 @@ export class CoreCourseHelperProvider { * @param course Course selected */ openCourseSummary(course: CoreCourseWithImageAndColor & CoreCourseAnyCourseData): void { - CoreDomUtils.openSideModal({ + CoreModals.openSideModal({ component: CoreCourseSummaryPage, componentProps: { courseId: course.id, diff --git a/src/core/features/dataprivacy/pages/main/main.ts b/src/core/features/dataprivacy/pages/main/main.ts index 6ac26a9cc..36fd84bd3 100644 --- a/src/core/features/dataprivacy/pages/main/main.ts +++ b/src/core/features/dataprivacy/pages/main/main.ts @@ -19,6 +19,7 @@ import { CoreDataPrivacyGetAccessInformationWSResponse, CoreDataPrivacyRequest, } from '@features/dataprivacy/services/dataprivacy'; +import { CoreModals } from '@services/modals'; import { CoreNavigator } from '@services/navigator'; import { CoreScreen } from '@services/screen'; import { CoreDomUtils } from '@services/utils/dom'; @@ -117,7 +118,7 @@ export class CoreDataPrivacyMainPage implements OnInit { await import('@features/dataprivacy/components/contactdpo/contactdpo'); // Create and show the modal. - const succeed = await CoreDomUtils.openModal({ + const succeed = await CoreModals.openModal({ component: CoreDataPrivacyContactDPOComponent, }); @@ -139,7 +140,7 @@ export class CoreDataPrivacyMainPage implements OnInit { await import('@features/dataprivacy/components/newrequest/newrequest'); // Create and show the modal. - const succeed = await CoreDomUtils.openModal({ + const succeed = await CoreModals.openModal({ component: CoreDataPrivacyNewRequestComponent, componentProps: { accessInfo: this.accessInfo, diff --git a/src/core/features/login/pages/site/site.ts b/src/core/features/login/pages/site/site.ts index b127025c0..49202fd68 100644 --- a/src/core/features/login/pages/site/site.ts +++ b/src/core/features/login/pages/site/site.ts @@ -46,6 +46,7 @@ import { CoreSitesFactory } from '@services/sites-factory'; import { ONBOARDING_DONE } from '@features/login/constants'; import { CoreUnauthenticatedSite } from '@classes/sites/unauthenticated-site'; import { CoreKeyboard } from '@singletons/keyboard'; +import { CoreModals } from '@services/modals'; /** * Site (url) chooser when adding a new site. @@ -260,7 +261,7 @@ export class CoreLoginSitePage implements OnInit { const { CoreLoginSiteHelpComponent } = await import('@features/login/components/site-help/site-help'); - await CoreDomUtils.openModal({ + await CoreModals.openModal({ component: CoreLoginSiteHelpComponent, cssClass: 'core-modal-fullscreen', }); @@ -273,7 +274,7 @@ export class CoreLoginSitePage implements OnInit { const { CoreLoginSiteOnboardingComponent } = await import('@features/login/components/site-onboarding/site-onboarding'); - await CoreDomUtils.openModal({ + await CoreModals.openModal({ component: CoreLoginSiteOnboardingComponent, cssClass: 'core-modal-fullscreen', }); diff --git a/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts index e747efdeb..b520be854 100644 --- a/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts +++ b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts @@ -19,7 +19,7 @@ import { CoreUserToursAlignment, CoreUserToursSide } from '@features/usertours/s import { IonRouterOutlet } from '@ionic/angular'; import { CoreScreen } from '@services/screen'; import { CoreSites } from '@services/sites'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { CoreMainMenuUserMenuTourComponent } from '../user-menu-tour/user-menu-tour'; import { CoreMainMenuUserMenuComponent } from '../user-menu/user-menu'; import { CoreMainMenuPage } from '@features/mainmenu/pages/menu/menu'; @@ -66,7 +66,7 @@ export class CoreMainMenuUserButtonComponent implements OnInit { event.preventDefault(); event.stopPropagation(); - CoreDomUtils.openSideModal({ + CoreModals.openSideModal({ component: CoreMainMenuUserMenuComponent, }); } diff --git a/src/core/features/mainmenu/components/user-menu/user-menu.ts b/src/core/features/mainmenu/components/user-menu/user-menu.ts index af928f3c7..1387bea70 100644 --- a/src/core/features/mainmenu/components/user-menu/user-menu.ts +++ b/src/core/features/mainmenu/components/user-menu/user-menu.ts @@ -28,6 +28,7 @@ import { CoreUserProfileHandlerType, CoreUserDelegateContext, } from '@features/user/services/user-delegate'; +import { CoreModals } from '@services/modals'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -248,7 +249,7 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy { event.preventDefault(); event.stopPropagation(); - const closeAll = await CoreDomUtils.openSideModal({ + const closeAll = await CoreModals.openSideModal({ component: CoreLoginSitesModalComponent, cssClass: 'core-modal-lateral core-modal-lateral-sm', }); diff --git a/src/core/features/policy/pages/acceptances/acceptances.ts b/src/core/features/policy/pages/acceptances/acceptances.ts index 3344c6957..9f4513565 100644 --- a/src/core/features/policy/pages/acceptances/acceptances.ts +++ b/src/core/features/policy/pages/acceptances/acceptances.ts @@ -26,6 +26,7 @@ import { Subscription } from 'rxjs'; import { CORE_DATAPRIVACY_FEATURE_NAME, CORE_DATAPRIVACY_PAGE_NAME } from '@features/dataprivacy/constants'; import { CoreNavigator } from '@services/navigator'; import { CoreDataPrivacy } from '@features/dataprivacy/services/dataprivacy'; +import { CoreModals } from '@services/modals'; /** * Page to view user acceptances. @@ -194,7 +195,7 @@ export class CorePolicyAcceptancesPage implements OnInit, OnDestroy { const { CorePolicyViewPolicyModalComponent } = await import('@features/policy/components/policy-modal/policy-modal'); - CoreDomUtils.openModal({ + CoreModals.openModal({ component: CorePolicyViewPolicyModalComponent, componentProps: { policy }, }); diff --git a/src/core/features/policy/pages/site-policy/site-policy.ts b/src/core/features/policy/pages/site-policy/site-policy.ts index 46e65efb1..e59851459 100644 --- a/src/core/features/policy/pages/site-policy/site-policy.ts +++ b/src/core/features/policy/pages/site-policy/site-policy.ts @@ -31,6 +31,7 @@ import { CoreScreen } from '@services/screen'; import { Subscription } from 'rxjs'; import { CoreDom } from '@singletons/dom'; import { CoreWait } from '@singletons/wait'; +import { CoreModals } from '@services/modals'; /** * Page to accept a site policy. @@ -468,7 +469,7 @@ export class CorePolicySitePolicyPage implements OnInit, OnDestroy { const { CorePolicyViewPolicyModalComponent } = await import('@features/policy/components/policy-modal/policy-modal'); - CoreDomUtils.openModal({ + CoreModals.openModal({ component: CorePolicyViewPolicyModalComponent, componentProps: { policy }, }); diff --git a/src/core/features/rating/components/aggregate/aggregate.ts b/src/core/features/rating/components/aggregate/aggregate.ts index 8f81aac08..7837e6343 100644 --- a/src/core/features/rating/components/aggregate/aggregate.ts +++ b/src/core/features/rating/components/aggregate/aggregate.ts @@ -20,8 +20,8 @@ import { CoreRatingInfoItem, CoreRatingProvider, } from '@features/rating/services/rating'; +import { CoreModals } from '@services/modals'; import { CoreSites } from '@services/sites'; -import { CoreDomUtils } from '@services/utils/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; /** @@ -120,7 +120,7 @@ export class CoreRatingAggregateComponent implements OnChanges, OnDestroy { const { CoreRatingRatingsComponent } = await import('@features/rating/components/ratings/ratings'); - await CoreDomUtils.openModal({ + await CoreModals.openModal({ component: CoreRatingRatingsComponent, componentProps: { contextLevel: this.contextLevel, diff --git a/src/core/features/reportbuilder/pages/report/report.ts b/src/core/features/reportbuilder/pages/report/report.ts index 958509675..c44252df5 100644 --- a/src/core/features/reportbuilder/pages/report/report.ts +++ b/src/core/features/reportbuilder/pages/report/report.ts @@ -15,8 +15,8 @@ import { Component, OnInit } from '@angular/core'; import { CoreReportBuilderReportSummaryComponent } from '@features/reportbuilder/components/report-summary/report-summary'; import { CoreReportBuilderReportDetail } from '@features/reportbuilder/services/reportbuilder'; +import { CoreModals } from '@services/modals'; import { CoreNavigator } from '@services/navigator'; -import { CoreDomUtils } from '@services/utils/dom'; @Component({ selector: 'core-report-builder-report', @@ -43,7 +43,7 @@ export class CoreReportBuilderReportPage implements OnInit { } openInfo(): void { - CoreDomUtils.openSideModal({ + CoreModals.openSideModal({ component: CoreReportBuilderReportSummaryComponent, componentProps: { reportDetail: this.reportDetail }, }); diff --git a/src/core/features/search/pages/global-search/global-search.ts b/src/core/features/search/pages/global-search/global-search.ts index c67d2abfc..059899d8c 100644 --- a/src/core/features/search/pages/global-search/global-search.ts +++ b/src/core/features/search/pages/global-search/global-search.ts @@ -29,6 +29,7 @@ import { } from '@features/search/services/global-search'; import { CoreNavigator } from '@services/navigator'; import { CoreSearchBoxComponent } from '@features/search/components/search-box/search-box'; +import { CoreModals } from '@services/modals'; @Component({ selector: 'page-core-search-global-search', @@ -139,7 +140,7 @@ export class CoreSearchGlobalSearchPage implements OnInit, OnDestroy, AfterViewI const { CoreSearchGlobalSearchFiltersComponent } = await import('@features/search/components/global-search-filters/global-search-filters.module'); - await CoreDomUtils.openSideModal({ + await CoreModals.openSideModal({ component: CoreSearchGlobalSearchFiltersComponent, componentProps: { hideCourses: !!this.courseId, diff --git a/src/core/features/sharedfiles/services/sharedfiles-helper.ts b/src/core/features/sharedfiles/services/sharedfiles-helper.ts index ba178ba95..0c8613bcb 100644 --- a/src/core/features/sharedfiles/services/sharedfiles-helper.ts +++ b/src/core/features/sharedfiles/services/sharedfiles-helper.ts @@ -30,6 +30,7 @@ import { SHAREDFILES_PAGE_NAME } from '../constants'; import { CoreSharedFilesChooseSitePage } from '../pages/choose-site/choose-site'; import { CoreError } from '@classes/errors/error'; import { CorePlatform } from '@services/platform'; +import { CoreModals } from '@services/modals'; /** * Helper service to share files with the app. @@ -152,7 +153,7 @@ export class CoreSharedFilesHelperProvider { const { CoreSharedFilesListModalComponent } = await import('@features/sharedfiles/components/list-modal/list-modal'); - const file = await CoreDomUtils.openModal({ + const file = await CoreModals.openModal({ component: CoreSharedFilesListModalComponent, cssClass: 'core-modal-fullscreen', componentProps: { mimetypes, pick: true }, diff --git a/src/core/features/sitehome/pages/index/index.ts b/src/core/features/sitehome/pages/index/index.ts index 508e2fcc1..30ff59412 100644 --- a/src/core/features/sitehome/pages/index/index.ts +++ b/src/core/features/sitehome/pages/index/index.ts @@ -32,6 +32,7 @@ import { CoreTime } from '@singletons/time'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreBlockSideBlocksComponent } from '@features/block/components/side-blocks/side-blocks'; import { ContextLevel } from '@/core/constants'; +import { CoreModals } from '@services/modals'; /** * Page that displays site home index. @@ -229,17 +230,18 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy { */ private openFocusedInstance() { const blockInstanceId = CoreNavigator.getRouteNumberParam('blockInstanceId'); - - if (blockInstanceId) { - CoreDomUtils.openSideModal({ - component: CoreBlockSideBlocksComponent, - componentProps: { - contextLevel: ContextLevel.COURSE, - instanceId: this.siteHomeId, - initialBlockInstanceId: blockInstanceId, - }, - }); + if (!blockInstanceId) { + return; } + + CoreModals.openSideModal({ + component: CoreBlockSideBlocksComponent, + componentProps: { + contextLevel: ContextLevel.COURSE, + instanceId: this.siteHomeId, + initialBlockInstanceId: blockInstanceId, + }, + }); } } diff --git a/src/core/features/siteplugins/components/module-index/module-index.ts b/src/core/features/siteplugins/components/module-index/module-index.ts index f7e5a0180..970092bb7 100644 --- a/src/core/features/siteplugins/components/module-index/module-index.ts +++ b/src/core/features/siteplugins/components/module-index/module-index.ts @@ -30,7 +30,7 @@ import { CoreSitePluginsContent, CoreSitePluginsCourseModuleHandlerData, } from '@features/siteplugins/services/siteplugins'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { CoreUtils } from '@services/utils/utils'; import { CoreSitePluginsPluginContentComponent, CoreSitePluginsPluginContentLoadedData } from '../plugin-content/plugin-content'; @@ -157,7 +157,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C return; } - const data = await CoreDomUtils.openSideModal({ + const data = await CoreModals.openSideModal({ component: CoreCourseModuleSummaryComponent, componentProps: { moduleId: this.module.id, diff --git a/src/core/services/modals.ts b/src/core/services/modals.ts index 78a1f2bf6..13df097d7 100644 --- a/src/core/services/modals.ts +++ b/src/core/services/modals.ts @@ -14,10 +14,19 @@ import { Constructor } from '@/core/utils/types'; import { Injectable } from '@angular/core'; +import { NavigationStart } from '@angular/router'; import { CoreModalComponent } from '@classes/modal-component'; +import { CoreModalLateralTransitionEnter, CoreModalLateralTransitionLeave } from '@classes/modal-lateral-transition'; import { CoreSheetModalComponent } from '@components/sheet-modal/sheet-modal'; -import { AngularFrameworkDelegate, makeSingleton } from '@singletons'; +import { AngularFrameworkDelegate, makeSingleton, ModalController, Router } from '@singletons'; import { CoreDirectivesRegistry } from '@singletons/directives-registry'; +import { Subscription, filter } from 'rxjs'; +import { Md5 } from 'ts-md5'; +import { fixOverlayAriaHidden } from '../utils/fix-aria-hidden'; +import { ModalOptions } from '@ionic/angular'; +import { CoreCanceledError } from '@classes/errors/cancelederror'; +import { CoreWSError } from '@classes/errors/wserror'; +import { CorePasswordModalResponse, CorePasswordModalParams } from '@components/password-modal/password-modal'; /** * Handles application modals. @@ -25,6 +34,8 @@ import { CoreDirectivesRegistry } from '@singletons/directives-registry'; @Injectable({ providedIn: 'root' }) export class CoreModalsService { + protected displayedModals: Record = {}; // To prevent duplicated modals. + /** * Get index of the overlay on top of the stack. * @@ -84,6 +95,118 @@ export class CoreModalsService { return modal.result; } -} + /** + * Opens a Modal. + * + * @param options Modal Options. + * @returns The modal data when the modal closes. + */ + async openModal( + options: OpenModalOptions, + ): Promise { + const { waitForDismissCompleted, closeOnNavigate, ...modalOptions } = options; + const listenCloseEvents = closeOnNavigate ?? true; // Default to true. + // TODO: Improve this if we need two modals with same component open at the same time. + const modalId = Md5.hashAsciiStr(options.component?.toString() || ''); + const alreadyDisplayed = !!this.displayedModals[modalId]; + + const modal = alreadyDisplayed + ? this.displayedModals[modalId] + : await ModalController.create(modalOptions); + + let navSubscription: Subscription | undefined; + + // Get the promise before presenting to get result if modal is suddenly hidden. + const resultPromise = waitForDismissCompleted ? modal.onDidDismiss() : modal.onWillDismiss(); + + if (!this.displayedModals[modalId]) { + // Store the modal and remove it when dismissed. + this.displayedModals[modalId] = modal; + + if (listenCloseEvents) { + // Listen navigation events to close modals. + navSubscription = Router.events + .pipe(filter(event => event instanceof NavigationStart)) + .subscribe(async () => { + modal.dismiss(); + }); + } + + await modal.present(); + } + + if (!alreadyDisplayed) { + fixOverlayAriaHidden(modal); + } + + const result = await resultPromise; + + navSubscription?.unsubscribe(); + delete this.displayedModals[modalId]; + + if (result?.data) { + return result?.data; + } + } + + /** + * Opens a side Modal. + * + * @param options Modal Options. + * @returns The modal data when the modal closes. + */ + async openSideModal( + options: OpenModalOptions, + ): Promise { + + options = Object.assign({ + cssClass: 'core-modal-lateral', + showBackdrop: true, + backdropDismiss: true, + enterAnimation: CoreModalLateralTransitionEnter, + leaveAnimation: CoreModalLateralTransitionLeave, + }, options); + + return this.openModal(options); + } + + /** + * Prompts password to the user and returns the entered text. + * + * @param passwordParams Params to show the modal. + * @returns Entered password, error and validation. + */ + async promptPassword(passwordParams?: CorePasswordModalParams): Promise { + const { CorePasswordModalComponent } = + await import('@/core/components/password-modal/password-modal.module'); + + const modalData = await CoreModals.openModal( + { + cssClass: 'core-password-modal', + showBackdrop: true, + backdropDismiss: true, + component: CorePasswordModalComponent, + componentProps: passwordParams, + }, + ); + + if (modalData === undefined) { + throw new CoreCanceledError(); + } else if (modalData instanceof CoreWSError) { + throw modalData; + } + + return modalData; + } + +} export const CoreModals = makeSingleton(CoreModalsService); + +/** + * Options for the openModal function. + */ +export type OpenModalOptions = ModalOptions & { + waitForDismissCompleted?: boolean; + closeOnNavigate?: boolean; // Default true. +}; diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index 68ff56d09..e5503e6ab 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -14,7 +14,7 @@ import { Injectable, SimpleChange, KeyValueChanges } from '@angular/core'; import { IonContent } from '@ionic/angular'; -import { ModalOptions, PopoverOptions, AlertOptions, AlertButton, TextFieldTypes } from '@ionic/core'; +import { PopoverOptions, AlertOptions, AlertButton, TextFieldTypes } from '@ionic/core'; import { Md5 } from 'ts-md5'; import { CoreConfig } from '@services/config'; @@ -33,18 +33,12 @@ import { Translate, AlertController, PopoverController, - ModalController, - Router, } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreFileSizeSum } from '@services/plugin-file-delegate'; import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreBSTooltipComponent } from '@components/bs-tooltip/bs-tooltip'; -import { CoreModalLateralTransitionEnter, CoreModalLateralTransitionLeave } from '@classes/modal-lateral-transition'; import { CoreSites } from '@services/sites'; -import { NavigationStart } from '@angular/router'; -import { filter } from 'rxjs/operators'; -import { Subscription } from 'rxjs'; import { CoreNetwork } from '@services/network'; import { CoreSiteError } from '@classes/errors/siteerror'; import { CoreUserSupport } from '@features/user/services/support'; @@ -53,12 +47,12 @@ import { CorePlatform } from '@services/platform'; import { CoreCancellablePromise } from '@classes/cancellable-promise'; import { CoreLang } from '@services/lang'; import { CorePasswordModalParams, CorePasswordModalResponse } from '@components/password-modal/password-modal'; -import { CoreWSError } from '@classes/errors/wserror'; import { CoreErrorLogs } from '@singletons/error-logs'; import { CoreKeyboard } from '@singletons/keyboard'; import { CoreWait } from '@singletons/wait'; import { CoreToasts, ToastDuration, ShowToastOptions } from '../toasts'; import { fixOverlayAriaHidden } from '@/core/utils/fix-aria-hidden'; +import { CoreModals, OpenModalOptions } from '@services/modals'; /* * "Utils" service with helper functions for UI, DOM elements and HTML code. @@ -77,7 +71,6 @@ export class CoreDomUtilsProvider { protected matchesFunctionName?: string; // Name of the "matches" function to use when simulating a closest call. protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous. protected displayedAlerts: Record = {}; // To prevent duplicated alerts. - protected displayedModals: Record = {}; // To prevent duplicated modals. protected activeLoadingModals: CoreIonLoadingElement[] = []; protected logger: CoreLogger; @@ -1465,54 +1458,13 @@ export class CoreDomUtilsProvider { * * @param options Modal Options. * @returns The modal data when the modal closes. + * + * @deprecated since 4.5. Use CoreModals.openModal instead. */ async openModal( options: OpenModalOptions, ): Promise { - const { waitForDismissCompleted, closeOnNavigate, ...modalOptions } = options; - const listenCloseEvents = closeOnNavigate ?? true; // Default to true. - - // TODO: Improve this if we need two modals with same component open at the same time. - const modalId = Md5.hashAsciiStr(options.component?.toString() || ''); - const alreadyDisplayed = !!this.displayedModals[modalId]; - - const modal = alreadyDisplayed - ? this.displayedModals[modalId] - : await ModalController.create(modalOptions); - - let navSubscription: Subscription | undefined; - - // Get the promise before presenting to get result if modal is suddenly hidden. - const resultPromise = waitForDismissCompleted ? modal.onDidDismiss() : modal.onWillDismiss(); - - if (!this.displayedModals[modalId]) { - // Store the modal and remove it when dismissed. - this.displayedModals[modalId] = modal; - - if (listenCloseEvents) { - // Listen navigation events to close modals. - navSubscription = Router.events - .pipe(filter(event => event instanceof NavigationStart)) - .subscribe(async () => { - modal.dismiss(); - }); - } - - await modal.present(); - } - - if (!alreadyDisplayed) { - fixOverlayAriaHidden(modal); - } - - const result = await resultPromise; - - navSubscription?.unsubscribe(); - delete this.displayedModals[modalId]; - - if (result?.data) { - return result?.data; - } + return CoreModals.openModal(options); } /** @@ -1520,20 +1472,13 @@ export class CoreDomUtilsProvider { * * @param options Modal Options. * @returns The modal data when the modal closes. + * + * @deprecated since 4.5. Use CoreModals.openSideModal instead. */ async openSideModal( options: OpenModalOptions, ): Promise { - - options = Object.assign({ - cssClass: 'core-modal-lateral', - showBackdrop: true, - backdropDismiss: true, - enterAnimation: CoreModalLateralTransitionEnter, - leaveAnimation: CoreModalLateralTransitionLeave, - }, options); - - return this.openModal(options); + return CoreModals.openSideModal(options); } /** @@ -1574,28 +1519,11 @@ export class CoreDomUtilsProvider { * * @param passwordParams Params to show the modal. * @returns Entered password, error and validation. + * + * @deprecated since 4.5. Use CoreModals.promptPassword instead. */ async promptPassword(passwordParams?: CorePasswordModalParams): Promise { - const { CorePasswordModalComponent } = - await import('@/core/components/password-modal/password-modal.module'); - - const modalData = await CoreDomUtils.openModal( - { - cssClass: 'core-password-modal', - showBackdrop: true, - backdropDismiss: true, - component: CorePasswordModalComponent, - componentProps: passwordParams, - }, - ); - - if (modalData === undefined) { - throw new CoreCanceledError(); - } else if (modalData instanceof CoreWSError) { - throw modalData; - } - - return modalData; + return CoreModals.promptPassword(passwordParams); } /** @@ -1617,7 +1545,7 @@ export class CoreDomUtilsProvider { } const { CoreViewerImageComponent } = await import('@features/viewer/components/image/image'); - await CoreDomUtils.openModal({ + await CoreModals.openModal({ component: CoreViewerImageComponent, componentProps: { title, @@ -1765,14 +1693,6 @@ export type OpenPopoverOptions = Omit & { waitForDismissCompleted?: boolean; }; -/** - * Options for the openModal function. - */ -export type OpenModalOptions = ModalOptions & { - waitForDismissCompleted?: boolean; - closeOnNavigate?: boolean; // Default true. -}; - /** * Buttons for prompt alert. */ diff --git a/src/core/services/utils/text.ts b/src/core/services/utils/text.ts index 2bfb864ed..5215f87d0 100644 --- a/src/core/services/utils/text.ts +++ b/src/core/services/utils/text.ts @@ -21,7 +21,7 @@ import { DomSanitizer, makeSingleton, Translate } from '@singletons'; import { CoreWSFile } from '@services/ws'; import { Locutus } from '@singletons/locutus'; import { CoreFileHelper } from '@services/file-helper'; -import { CoreDomUtils } from './dom'; +import { CoreModals } from '@services/modals'; import { CoreUrl } from '@singletons/url'; import { AlertButton } from '@ionic/angular'; import { CorePath } from '@singletons/path'; @@ -1050,7 +1050,7 @@ export class CoreTextUtilsProvider { ...options, }; - await CoreDomUtils.openModal(modalOptions); + await CoreModals.openModal(modalOptions); } } diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index cdced27db..0c1724eaf 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -20,7 +20,7 @@ import { CoreEvents } from '@singletons/events'; import { CoreFile } from '@services/file'; import { CoreLang } from '@services/lang'; import { CoreWS } from '@services/ws'; -import { CoreDomUtils } from '@services/utils/dom'; +import { CoreModals } from '@services/modals'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTextUtils } from '@services/utils/text'; import { makeSingleton, InAppBrowser, FileOpener, WebIntent, Translate, NgZone } from '@singletons'; @@ -1657,7 +1657,7 @@ export class CoreUtilsProvider { async scanQR(title?: string): Promise { const { CoreViewerQRScannerComponent } = await import('@features/viewer/components/qr-scanner/qr-scanner'); - return CoreDomUtils.openModal({ + return CoreModals.openModal({ component: CoreViewerQRScannerComponent, cssClass: 'core-modal-fullscreen', componentProps: {