MOBILE-4616 chore: Move modals functions to CoreModalsService

main
Pau Ferrer Ocaña 2024-07-16 15:24:04 +02:00
parent ab7b69c262
commit 3f9ea653f9
44 changed files with 232 additions and 160 deletions

View File

@ -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<void> {
await CoreDomUtils.openSideModal({
await CoreModals.openSideModal({
component: AddonCalendarFilterComponent,
componentProps: {
courses: this.manager?.getSource().courses,

View File

@ -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<void> {
await CoreDomUtils.openSideModal({
await CoreModals.openSideModal({
component: AddonCalendarFilterComponent,
componentProps: {
courses: this.courses,

View File

@ -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<CorePasswordModalResponse>({
const response = await CoreModals.promptPassword<CorePasswordModalResponse>({
title: method.name,
validator: validatePassword,
});

View File

@ -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',

View File

@ -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<number>({
const userId = await CoreModals.openSideModal<number>({
component: AddonMessagesConversationInfoComponent,
componentProps: {
conversationId: this.conversationId,

View File

@ -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<AddonModAssignFeedbackCommentsTextData>({
const modalData = await CoreModals.openModal<AddonModAssignFeedbackCommentsTextData>({
component: AddonModAssignEditFeedbackModalComponent,
componentProps: {
assign: this.assign,

View File

@ -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<number>({
const modalData = await CoreModals.openSideModal<number>({
component: AddonModBookTocComponent,
componentProps: {
moduleId: this.cmId,

View File

@ -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<void> {
// Create the toc modal.
const modalData = await CoreDomUtils.openSideModal<AddonModChatUsersModalResult>({
const modalData = await CoreModals.openSideModal<AddonModChatUsersModalResult>({
component: AddonModChatUsersModalComponent,
componentProps: {
sessionId: this.sessionId,

View File

@ -51,6 +51,7 @@ import {
AddonModDataTemplateType,
AddonModDataTemplateMode,
} from '../../constants';
import { CoreModals } from '@services/modals';
const contentToken = '<!-- CORE-DATABASE-CONTENT-GOES-HERE -->';
@ -401,7 +402,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
async showSearch(): Promise<void> {
const { AddonModDataSearchModalComponent } = await import('@addons/mod/data/components/search-modal/search-modal');
const modalData = await CoreDomUtils.openModal<AddonModDataSearchDataParams>({
const modalData = await CoreModals.openModal<AddonModDataSearchDataParams>({
component: AddonModDataSearchModalComponent,
componentProps: {
search: this.search,

View File

@ -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<void> {
// Create the toc modal.
const itemHref = await CoreDomUtils.openSideModal<string>({
const itemHref = await CoreModals.openSideModal<string>({
component: AddonModImscpTocComponent,
componentProps: {
items: this.items,

View File

@ -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<void> {
this.menuShown = true;
await CoreDomUtils.openSideModal({
await CoreModals.openSideModal({
component: AddonModLessonMenuModalPage,
componentProps: {
pageInstance: this,

View File

@ -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',

View File

@ -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<AddonModQuizNavigationModalReturn>({
const modalData = await CoreModals.openSideModal<AddonModQuizNavigationModalReturn>({
component: AddonModQuizNavigationModalComponent,
componentProps: {
navigation: this.navigation,

View File

@ -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<void> {
// Create the navigation modal.
const modalData = await CoreDomUtils.openSideModal<AddonModQuizNavigationModalReturn>({
const modalData = await CoreModals.openSideModal<AddonModQuizNavigationModalReturn>({
component: AddonModQuizNavigationModalComponent,
componentProps: {
navigation: this.navigation,

View File

@ -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(

View File

@ -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<Record<string, string>>({
const modalData = await CoreModals.openModal<Record<string, string>>({
component: AddonModQuizPreflightModalComponent,
componentProps: {
title: options.title,

View File

@ -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<void> {
const modalData = await CoreDomUtils.openSideModal<AddonModScormScoWithData>({
const modalData = await CoreModals.openSideModal<AddonModScormScoWithData>({
component: AddonModScormTocComponent,
componentProps: {
toc: this.toc,

View File

@ -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<void> {
// Create the toc modal.
const { AddonModWikiMapModalComponent } = await import('../map/map');
const modalData = await CoreDomUtils.openSideModal<AddonModWikiMapModalReturn>({
const modalData = await CoreModals.openSideModal<AddonModWikiMapModalReturn>({
component: AddonModWikiMapModalComponent,
componentProps: {
pages: this.subwikiPages,

View File

@ -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<boolean>({
const modalData = await CoreModals.openModal<boolean>({
component: AddonModWorkshopPhaseInfoModalComponent,
componentProps: {
phases: CoreUtils.objectToArray(this.phases),

View File

@ -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<AddonNotesAddModalReturn>({
const modalData = await CoreModals.openModal<AddonNotesAddModalReturn>({
component: AddonNotesAddComponent,
componentProps: {
userId: this.userId,

View File

@ -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<boolean>({
await CoreModals.openModal<boolean>({
component: CoreRefreshButtonModalComponent,
cssClass: 'core-modal-no-background core-modal-fullscreen',
closeOnNavigate: true,

View File

@ -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) {

View File

@ -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,

View File

@ -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,

View File

@ -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<CoreCourseModuleSummaryResult>({
const data = await CoreModals.openSideModal<CoreCourseModuleSummaryResult>({
component: CoreCourseModuleSummaryComponent,
componentProps: {
moduleId: this.module.id,

View File

@ -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<CoreCourseIndexSectionWithModule>({
const data = await CoreModals.openModal<CoreCourseIndexSectionWithModule>({
component: CoreCourseCourseIndexComponent,
initialBreakpoint: 1,
breakpoints: [0, 1],

View File

@ -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<CoreCourseModuleSummaryResult>({
const data = await CoreModals.openSideModal<CoreCourseModuleSummaryResult>({
component: CoreCourseModuleSummaryComponent,
componentProps: {
moduleId: this.module.id,

View File

@ -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<void>({
CoreModals.openSideModal<void>({
component: CoreCourseSummaryPage,
componentProps: {
courseId: course.id,

View File

@ -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<boolean>({
const succeed = await CoreModals.openModal<boolean>({
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<boolean>({
const succeed = await CoreModals.openModal<boolean>({
component: CoreDataPrivacyNewRequestComponent,
componentProps: {
accessInfo: this.accessInfo,

View File

@ -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',
});

View File

@ -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<void>({
CoreModals.openSideModal<void>({
component: CoreMainMenuUserMenuComponent,
});
}

View File

@ -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<boolean>({
const closeAll = await CoreModals.openSideModal<boolean>({
component: CoreLoginSitesModalComponent,
cssClass: 'core-modal-lateral core-modal-lateral-sm',
});

View File

@ -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 },
});

View File

@ -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 },
});

View File

@ -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,

View File

@ -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<void>({
CoreModals.openSideModal<void>({
component: CoreReportBuilderReportSummaryComponent,
componentProps: { reportDetail: this.reportDetail },
});

View File

@ -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<CoreSearchGlobalSearchFilters>({
await CoreModals.openSideModal<CoreSearchGlobalSearchFilters>({
component: CoreSearchGlobalSearchFiltersComponent,
componentProps: {
hideCourses: !!this.courseId,

View File

@ -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<FileEntry>({
const file = await CoreModals.openModal<FileEntry>({
component: CoreSharedFilesListModalComponent,
cssClass: 'core-modal-fullscreen',
componentProps: { mimetypes, pick: true },

View File

@ -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,
},
});
}
}

View File

@ -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<CoreCourseModuleSummaryResult>({
const data = await CoreModals.openSideModal<CoreCourseModuleSummaryResult>({
component: CoreCourseModuleSummaryComponent,
componentProps: {
moduleId: this.module.id,

View File

@ -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<string, HTMLIonModalElement> = {}; // 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<T = unknown>(
options: OpenModalOptions,
): Promise<T | undefined> {
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<T>() : modal.onWillDismiss<T>();
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<T = unknown>(
options: OpenModalOptions,
): Promise<T | undefined> {
options = Object.assign({
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
enterAnimation: CoreModalLateralTransitionEnter,
leaveAnimation: CoreModalLateralTransitionLeave,
}, options);
return this.openModal<T>(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<T extends CorePasswordModalResponse>(passwordParams?: CorePasswordModalParams): Promise<T> {
const { CorePasswordModalComponent } =
await import('@/core/components/password-modal/password-modal.module');
const modalData = await CoreModals.openModal<T>(
{
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.
};

View File

@ -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<string, HTMLIonAlertElement> = {}; // To prevent duplicated alerts.
protected displayedModals: Record<string, HTMLIonModalElement> = {}; // 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<T = unknown>(
options: OpenModalOptions,
): Promise<T | undefined> {
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<T>() : modal.onWillDismiss<T>();
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<T = unknown>(
options: OpenModalOptions,
): Promise<T | undefined> {
options = Object.assign({
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
enterAnimation: CoreModalLateralTransitionEnter,
leaveAnimation: CoreModalLateralTransitionLeave,
}, options);
return this.openModal<T>(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<T extends CorePasswordModalResponse>(passwordParams?: CorePasswordModalParams): Promise<T> {
const { CorePasswordModalComponent } =
await import('@/core/components/password-modal/password-modal.module');
const modalData = await CoreDomUtils.openModal<T>(
{
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<PopoverOptions, 'showBackdrop'> & {
waitForDismissCompleted?: boolean;
};
/**
* Options for the openModal function.
*/
export type OpenModalOptions = ModalOptions & {
waitForDismissCompleted?: boolean;
closeOnNavigate?: boolean; // Default true.
};
/**
* Buttons for prompt alert.
*/

View File

@ -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);
}
}

View File

@ -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<string | undefined> {
const { CoreViewerQRScannerComponent } = await import('@features/viewer/components/qr-scanner/qr-scanner');
return CoreDomUtils.openModal<string>({
return CoreModals.openModal<string>({
component: CoreViewerQRScannerComponent,
cssClass: 'core-modal-fullscreen',
componentProps: {