MOBILE-3745 core: Use new openModal function

main
Pau Ferrer Ocaña 2021-05-04 15:26:06 +02:00
parent fa22325fb4
commit 7af5c510bf
36 changed files with 211 additions and 276 deletions

View File

@ -39,7 +39,7 @@ import { Md5 } from 'ts-md5/dist/md5';
import moment from 'moment';
import { CoreAnimations } from '@components/animations';
import { CoreError } from '@classes/errors/error';
import { ModalController, Translate } from '@singletons';
import { Translate } from '@singletons';
import { CoreNavigator } from '@services/navigator';
import { CoreIonLoadingElement } from '@classes/ion-loading';
import { ActivatedRoute } from '@angular/router';
@ -1302,18 +1302,14 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
async viewInfo(): Promise<void> {
if (this.isGroup) {
// Display the group information.
const modal = await ModalController.create({
const userId = await CoreDomUtils.openModal<number>({
component: AddonMessagesConversationInfoComponent,
componentProps: {
conversationId: this.conversationId,
},
});
await modal.present();
const result = await modal.onDidDismiss();
if (typeof result.data != 'undefined') {
if (typeof userId != 'undefined') {
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/**/discussion');
// Open user conversation.
@ -1321,12 +1317,12 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
// Notify the left pane to load it, this way the right conversation will be highlighted.
CoreEvents.trigger(
AddonMessagesProvider.OPEN_CONVERSATION_EVENT,
{ userId: result.data },
{ userId },
this.siteId,
);
} else {
// Open the discussion in a new view.
CoreNavigator.navigateToSitePath('/messages/discussion', { params: { userId: result.data.userId } });
CoreNavigator.navigateToSitePath('/messages/discussion', { params: { userId } });
}
}
} else {

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 { ModalController } from '@singletons';
import { CoreDomUtils } from '@services/utils/dom';
import { AddonModAssignEditFeedbackModalComponent } from '../components/edit-feedback-modal/edit-feedback-modal';
import { AddonModAssignFeedbackCommentsTextData } from '../feedback/comments/services/handler';
import { AddonModAssignAssign, AddonModAssignPlugin, AddonModAssignSubmission } from '../services/assign';
@ -47,7 +47,7 @@ export class AddonModAssignFeedbackPluginBaseComponent {
}
// Create the navigation modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<AddonModAssignFeedbackCommentsTextData>({
component: AddonModAssignEditFeedbackModalComponent,
componentProps: {
assign: this.assign,
@ -57,15 +57,11 @@ export class AddonModAssignFeedbackPluginBaseComponent {
},
});
await modal.present();
const result = await modal.onDidDismiss();
if (typeof result.data == 'undefined') {
if (typeof modalData == 'undefined') {
throw new CoreCanceledError(); // User cancelled.
} else {
return result.data;
}
return modalData;
}
/**

View File

@ -28,7 +28,7 @@ import {
import { CoreTag, CoreTagItem } from '@features/tag/services/tag';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { ModalController, Translate } from '@singletons';
import { Translate } from '@singletons';
import { CoreUtils } from '@services/utils/utils';
import { CoreCourse } from '@features/course/services/course';
import { AddonModBookTocComponent } from '../toc/toc';
@ -84,7 +84,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
*/
async showToc(): Promise<void> {
// Create the toc modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<number>({
component: AddonModBookTocComponent,
componentProps: {
moduleId: this.module.id,
@ -93,19 +93,10 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
courseId: this.courseId,
book: this.book,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
await modal.present();
const result = await modal.onDidDismiss();
if (result.data) {
this.changeChapter(result.data);
if (modalData) {
this.changeChapter(modalData);
}
}

View File

@ -21,7 +21,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { ModalController, Network, NgZone } from '@singletons';
import { Network, NgZone } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { Subscription } from 'rxjs';
import { AddonModChatUsersModalComponent, AddonModChatUsersModalResult } from '../../components/users-modal/users-modal';
@ -178,32 +178,23 @@ export class AddonModChatChatPage implements OnInit, OnDestroy {
*/
async showChatUsers(): Promise<void> {
// Create the toc modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<AddonModChatUsersModalResult>({
component: AddonModChatUsersModalComponent,
componentProps: {
sessionId: this.sessionId,
cmId: this.cmId,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
await modal.present();
const result = await modal.onDidDismiss<AddonModChatUsersModalResult>();
if (result.data) {
if (result.data.talkTo) {
this.newMessage = `To ${result.data.talkTo}: ` + (this.sendMessageForm?.message || '');
if (modalData) {
if (modalData.talkTo) {
this.newMessage = `To ${modalData.talkTo}: ` + (this.sendMessageForm?.message || '');
}
if (result.data.beepTo) {
this.sendMessage('', result.data.beepTo);
if (modalData.beepTo) {
this.sendMessage('', modalData.beepTo);
}
this.users = result.data.users;
this.users = modalData.users;
}
}

View File

@ -29,7 +29,6 @@ import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { ModalController } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import {
AddonModDataProvider,
@ -376,7 +375,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
* Display the chat users modal.
*/
async showSearch(): Promise<void> {
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<AddonModDataSearchDataParams>({
component: AddonModDataSearchComponent,
componentProps: {
search: this.search,
@ -385,12 +384,9 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
},
});
await modal.present();
const result = await modal.onDidDismiss();
// Add data to search object.
if (result.data) {
this.search = result.data;
if (modalData) {
this.search = modalData;
this.searchEntries(0);
}
}

View File

@ -40,7 +40,7 @@ import {
AddonModForumUpdateDiscussionPostWSOptionsObject,
} from '../../services/forum';
import { CoreTag } from '@features/tag/services/tag';
import { ModalController, PopoverController, Translate } from '@singletons';
import { PopoverController, Translate } from '@singletons';
import { CoreFileUploader } from '@features/fileuploader/services/fileuploader';
import { IonContent } from '@ionic/angular';
import { AddonModForumSync } from '../../services/forum-sync';
@ -254,7 +254,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
* Shows a form modal to edit an online post.
*/
async editPost(): Promise<void> {
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<AddonModForumReply>({
component: AddonModForumEditPostComponent,
componentProps: {
post: this.post,
@ -265,18 +265,13 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
backdropDismiss: false,
});
await modal.present();
const result = await modal.onDidDismiss<AddonModForumReply>();
const data = result.data;
if (!data) {
if (!modalData) {
return;
}
// Add some HTML to the message if needed.
const message = CoreTextUtils.formatHtmlLines(data.message!);
const files = data.files;
const message = CoreTextUtils.formatHtmlLines(modalData.message!);
const files = modalData.files;
const options: AddonModForumUpdateDiscussionPostWSOptionsObject = {};
const sendingModal = await CoreDomUtils.showModalLoading('core.sending', true);
@ -295,16 +290,16 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
}
// Try to send it to server.
const sent = await AddonModForum.updatePost(this.post.id, data.subject!, message, options);
const sent = await AddonModForum.updatePost(this.post.id, modalData.subject!, message, options);
if (sent && this.forum.id) {
// Data sent to server, delete stored files (if any).
AddonModForumHelper.deleteReplyStoredFiles(this.forum.id, this.post.id);
this.onPostChange.emit();
this.post.subject = data.subject!;
this.post.subject = modalData.subject!;
this.post.message = message;
this.post.attachments = data.files;
this.post.attachments = modalData.files;
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_forum.couldnotupdate', true);

View File

@ -21,7 +21,6 @@ import {
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { CoreDomUtils } from '@services/utils/dom';
import { ModalController } from '@singletons';
import { AddonModImscpProvider, AddonModImscp, AddonModImscpTocItem } from '../../services/imscp';
import { AddonModImscpTocComponent } from '../toc/toc';
@ -150,25 +149,16 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
*/
async showToc(): Promise<void> {
// Create the toc modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<string>({
component: AddonModImscpTocComponent,
componentProps: {
items: this.items,
selected: this.currentItem,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
await modal.present();
const result = await modal.onDidDismiss();
if (result.data) {
this.loadItem(result.data);
if (modalData) {
this.loadItem(modalData);
}
}

View File

@ -762,22 +762,13 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
async showMenu(): Promise<void> {
this.menuShown = true;
const menuModal = await ModalController.create({
await CoreDomUtils.openSideModal({
component: AddonModLessonMenuModalPage,
componentProps: {
pageInstance: this,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// leaveAnimation: 'core-modal-lateral-transition',
});
await menuModal.present();
await menuModal.onWillDismiss();
this.menuShown = false;
}

View File

@ -22,9 +22,10 @@ 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 { CoreUtils } from '@services/utils/utils';
import { CoreWSFile } from '@services/ws';
import { makeSingleton, ModalController, Translate } from '@singletons';
import { makeSingleton, Translate } from '@singletons';
import { AddonModLessonPasswordModalComponent } from '../../components/password-modal/password-modal';
import {
AddonModLesson,
@ -54,19 +55,15 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
*/
protected async askUserPassword(): Promise<string> {
// Create and show the modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<string>({
component: AddonModLessonPasswordModalComponent,
});
await modal.present();
const result = await modal.onWillDismiss();
if (typeof result.data != 'string') {
if (typeof modalData != 'string') {
throw new CoreCanceledError();
}
return result.data;
return modalData;
}
/**

View File

@ -50,7 +50,7 @@ export class AddonModQuizNavigationModalComponent {
* @param slot Slot of the question to scroll to.
*/
loadPage(page: number, slot?: number): void {
ModalController.dismiss({
ModalController.dismiss(<AddonModQuizNavigationModalReturn>{
action: AddonModQuizNavigationModalComponent.CHANGE_PAGE,
page,
slot,
@ -61,7 +61,7 @@ export class AddonModQuizNavigationModalComponent {
* Switch mode in review.
*/
switchMode(): void {
ModalController.dismiss({
ModalController.dismiss(<AddonModQuizNavigationModalReturn>{
action: AddonModQuizNavigationModalComponent.SWITCH_MODE,
});
}
@ -74,3 +74,9 @@ export class AddonModQuizNavigationModalComponent {
export type AddonModQuizNavigationQuestion = CoreQuestionQuestionParsed & {
stateClass?: string;
};
export type AddonModQuizNavigationModalReturn = {
action: number;
page?: number;
slot?: number;
};

View File

@ -31,6 +31,7 @@ import { CoreEvents } from '@singletons/events';
import { AddonModQuizAutoSave } from '../../classes/auto-save';
import {
AddonModQuizNavigationModalComponent,
AddonModQuizNavigationModalReturn,
AddonModQuizNavigationQuestion,
} from '../../components/navigation-modal/navigation-modal';
import {
@ -581,7 +582,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
}
// Create the navigation modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<AddonModQuizNavigationModalReturn>({
component: AddonModQuizNavigationModalComponent,
componentProps: {
navigation: this.navigation,
@ -589,19 +590,10 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
currentPage: this.attempt?.currentpage,
isReview: false,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
await modal.present();
const result = await modal.onWillDismiss();
if (result.data && result.data.action == AddonModQuizNavigationModalComponent.CHANGE_PAGE) {
this.changePage(result.data.page, true, result.data.slot);
if (modalData && modalData.action == AddonModQuizNavigationModalComponent.CHANGE_PAGE) {
this.changePage(modalData.page!, true, modalData.slot);
}
}

View File

@ -21,9 +21,10 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { ModalController, Translate } from '@singletons';
import { Translate } from '@singletons';
import {
AddonModQuizNavigationModalComponent,
AddonModQuizNavigationModalReturn,
AddonModQuizNavigationQuestion,
} from '../../components/navigation-modal/navigation-modal';
import {
@ -325,7 +326,7 @@ export class AddonModQuizReviewPage implements OnInit {
async openNavigation(): Promise<void> {
// Create the navigation modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<AddonModQuizNavigationModalReturn>({
component: AddonModQuizNavigationModalComponent,
componentProps: {
navigation: this.navigation,
@ -335,24 +336,15 @@ export class AddonModQuizReviewPage implements OnInit {
numPages: this.numPages,
showAll: this.showAll,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
await modal.present();
const result = await modal.onWillDismiss();
if (!result.data) {
if (!modalData) {
return;
}
if (result.data.action == AddonModQuizNavigationModalComponent.CHANGE_PAGE) {
this.changePage(result.data.page, true, result.data.slot);
} else if (result.data.action == AddonModQuizNavigationModalComponent.SWITCH_MODE) {
if (modalData.action == AddonModQuizNavigationModalComponent.CHANGE_PAGE) {
this.changePage(modalData.page!, true, modalData.slot);
} else if (modalData.action == AddonModQuizNavigationModalComponent.SWITCH_MODE) {
this.switchMode();
}
}

View File

@ -21,7 +21,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, ModalController, Translate } from '@singletons';
import { makeSingleton, Translate } from '@singletons';
import { AddonModQuizPreflightModalComponent } from '../components/preflight-modal/preflight-modal';
import { AddonModQuizAccessRuleDelegate } from './access-rules-delegate';
import { AddonModQuizModuleHandlerService } from './handlers/module';
@ -160,7 +160,7 @@ export class AddonModQuizHelperProvider {
}
// Create and show the modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<Record<string, string>>({
component: AddonModQuizPreflightModalComponent,
componentProps: {
title: title,
@ -172,15 +172,11 @@ export class AddonModQuizHelperProvider {
},
});
await modal.present();
const result = await modal.onWillDismiss();
if (!result.data) {
if (!modalData) {
throw new CoreCanceledError();
}
return <Record<string, string>> result.data;
return modalData;
}
/**

View File

@ -20,7 +20,6 @@ import { CoreSync } from '@services/sync';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { ModalController } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { AddonModScormDataModel12 } from '../../classes/data-model-12';
import { AddonModScormTocComponent } from '../../components/toc/toc';
@ -486,7 +485,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
* Show the TOC.
*/
async openToc(): Promise<void> {
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<AddonModScormScoWithData>({
component: AddonModScormTocComponent,
componentProps: {
toc: this.toc,
@ -497,19 +496,10 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
accessInfo: this.accessInfo,
mode: this.mode,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// leaveAnimation: 'core-modal-lateral-transition'
});
await modal.present();
const result = await modal.onDidDismiss();
if (result.data) {
this.loadSco(result.data);
if (modalData) {
this.loadSco(modalData);
}
}

View File

@ -27,7 +27,7 @@ import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { ModalController, PopoverController, Translate } from '@singletons';
import { PopoverController, Translate } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { Md5 } from 'ts-md5';
import { AddonModWikiPageDBRecord } from '../../services/database/wiki';
@ -51,7 +51,7 @@ import {
AddonModWikiSyncWikiResult,
AddonModWikiSyncWikiSubwiki,
} from '../../services/wiki-sync';
import { AddonModWikiMapModalComponent } from '../map/map';
import { AddonModWikiMapModalComponent, AddonModWikiMapModalReturn } from '../map/map';
import { AddonModWikiSubwikiPickerComponent } from '../subwiki-picker/subwiki-picker';
/**
@ -576,7 +576,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
*/
async openMap(): Promise<void> {
// Create the toc modal.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openSideModal<AddonModWikiMapModalReturn>({
component: AddonModWikiMapModalComponent,
componentProps: {
pages: this.subwikiPages,
@ -585,23 +585,14 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
courseId: this.courseId,
selectedTitle: this.currentPageObj && this.currentPageObj.title,
},
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
await modal.present();
const result = await modal.onDidDismiss();
if (result.data) {
if (result.data.type == 'home') {
if (modalData) {
if (modalData.home) {
// Go back to the initial page of the wiki.
CoreNavigator.navigateToSitePath(result.data.goto);
} else {
this.goToPage(result.data.goto);
CoreNavigator.navigateToSitePath(modalData.home);
} else if (modalData.page) {
this.goToPage(modalData.page);
}
}

View File

@ -47,14 +47,14 @@ export class AddonModWikiMapModalComponent implements OnInit {
* @param page Clicked page.
*/
goToPage(page: AddonModWikiSubwikiPage | AddonModWikiPageDBRecord): void {
ModalController.dismiss({ type: 'page', goto: page });
ModalController.dismiss(<AddonModWikiMapModalReturn>{ page });
}
/**
* Go back to the initial page of the wiki.
*/
goToWikiHome(): void {
ModalController.dismiss({ type: 'home', goto: this.homeView });
ModalController.dismiss(<AddonModWikiMapModalReturn>{ home: this.homeView });
}
/**
@ -103,3 +103,8 @@ type AddonModWikiPagesMapLetter = {
label: string;
pages: (AddonModWikiSubwikiPage | AddonModWikiPageDBRecord)[];
};
export type AddonModWikiMapModalReturn = {
page?: AddonModWikiSubwikiPage | AddonModWikiPageDBRecord;
home?: string;
};

View File

@ -20,8 +20,9 @@ import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreGroupInfo, CoreGroups } from '@services/groups';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { ModalController, Platform } from '@singletons';
import { Platform } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { Subscription } from 'rxjs';
import { AddonModWorkshopModuleHandlerService } from '../../services/handlers/module';
@ -387,7 +388,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
*/
async viewPhaseInfo(): Promise<void> {
if (this.phases) {
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<boolean>({
component: AddonModWorkshopPhaseInfoComponent,
componentProps: {
phases: CoreUtils.objectToArray(this.phases),
@ -396,10 +397,8 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
showSubmit: this.showSubmit,
},
});
await modal.present();
const result = await modal.onDidDismiss();
if (result.data === true) {
if (modalData === true) {
this.gotoSubmit();
}
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { AddonNotes } from '@addons/notes/services/notes';
import { AddonNotes, AddonNotesPublishState } from '@addons/notes/services/notes';
import { Component, ViewChild, ElementRef, Input } from '@angular/core';
import { CoreApp } from '@services/app';
import { CoreSites } from '@services/sites';
@ -32,7 +32,7 @@ export class AddonNotesAddComponent {
@Input() protected courseId!: number;
@Input() protected userId?: number;
@Input() type = 'personal';
@Input() type: AddonNotesPublishState = 'personal';
text = '';
processing = false;
@ -56,7 +56,7 @@ export class AddonNotesAddComponent {
CoreForms.triggerFormSubmittedEvent(this.formElement, sent, CoreSites.getCurrentSiteId());
ModalController.dismiss({ type: this.type, sent: true }).finally(() => {
ModalController.dismiss(<AddonNotesAddModalReturn>{ type: this.type, sent: true }).finally(() => {
CoreDomUtils.showToast(sent ? 'addon.notes.eventnotecreated' : 'core.datastoredoffline', true, 3000);
});
} catch (error){
@ -73,7 +73,12 @@ export class AddonNotesAddComponent {
closeModal(): void {
CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
ModalController.dismiss({ type: this.type });
ModalController.dismiss(<AddonNotesAddModalReturn>{ type: this.type });
}
}
export type AddonNotesAddModalReturn = {
type: AddonNotesPublishState;
sent?: boolean;
};

View File

@ -13,8 +13,8 @@
// limitations under the License.
import { CoreConstants } from '@/core/constants';
import { AddonNotesAddComponent } from '@addons/notes/components/add/add-modal';
import { AddonNotes, AddonNotesNoteFormatted } from '@addons/notes/services/notes';
import { AddonNotesAddComponent, AddonNotesAddModalReturn } from '@addons/notes/components/add/add-modal';
import { AddonNotes, AddonNotesNoteFormatted, AddonNotesPublishState } from '@addons/notes/services/notes';
import { AddonNotesOffline } from '@addons/notes/services/notes-offline';
import { AddonNotesSync, AddonNotesSyncProvider } from '@addons/notes/services/notes-sync';
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
@ -26,7 +26,6 @@ import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { ModalController } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
/**
@ -43,7 +42,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
courseId: number;
userId?: number;
type = 'course';
type: AddonNotesPublishState = 'course';
refreshIcon = CoreConstants.ICON_LOADING;
syncIcon = CoreConstants.ICON_LOADING;
notes: AddonNotesNoteFormatted[] = [];
@ -160,7 +159,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
*
* @param type New type.
*/
async typeChanged(type: string): Promise<void> {
async typeChanged(type: AddonNotesPublishState): Promise<void> {
this.type = type;
this.notesLoaded = false;
this.refreshIcon = CoreConstants.ICON_LOADING;
@ -179,7 +178,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
e.preventDefault();
e.stopPropagation();
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<AddonNotesAddModalReturn>({
component: AddonNotesAddComponent,
componentProps: {
userId: this.userId,
@ -188,21 +187,17 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
},
});
await modal.present();
if (typeof modalData != 'undefined') {
const result = await modal.onDidDismiss();
if (typeof result.data != 'undefined') {
if (result.data.sent && result.data.type) {
if (result.data.type != this.type) {
this.type = result.data.type;
if (modalData.sent && modalData.type) {
if (modalData.type != this.type) {
this.type = modalData.type;
this.notesLoaded = false;
}
this.refreshNotes(false);
} else if (result.data.type && result.data.type != this.type) {
this.typeChanged(result.data.type);
} else if (modalData.type && modalData.type != this.type) {
this.typeChanged(modalData.type);
}
}
}

View File

@ -13,6 +13,7 @@
// limitations under the License.
import { CoreSiteSchema } from '@services/sites';
import { AddonNotesPublishState } from '../notes';
/**
* Database variables for AddonNotesOfflineProvider.
@ -83,7 +84,7 @@ export type AddonNotesDBRecord = {
content: string; // Primary key.
created: number; // Primary key.
courseid: number;
publishstate: string;
publishstate: AddonNotesPublishState;
format: number;
lastmodified: number;
};

View File

@ -17,6 +17,7 @@ import { CoreSites } from '@services/sites';
import { CoreTimeUtils } from '@services/utils/time';
import { makeSingleton } from '@singletons';
import { AddonNotesDBRecord, AddonNotesDeletedDBRecord, NOTES_DELETED_TABLE, NOTES_TABLE } from './database/notes';
import { AddonNotesPublishState } from './notes';
/**
* Service to handle offline notes.
@ -150,7 +151,7 @@ export class AddonNotesOfflineProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with notes.
*/
async getNotesWithPublishState(state: string, siteId?: string): Promise<AddonNotesDBRecord[]> {
async getNotesWithPublishState(state: AddonNotesPublishState, siteId?: string): Promise<AddonNotesDBRecord[]> {
const site = await CoreSites.getSite(siteId);
return await site.getDb().getRecords(NOTES_TABLE, { publishstate: state });
@ -189,7 +190,7 @@ export class AddonNotesOfflineProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with boolean: true if has offline notes, false otherwise.
*/
async hasNotesWithPublishState(state: string, siteId?: string): Promise<boolean> {
async hasNotesWithPublishState(state: AddonNotesPublishState, siteId?: string): Promise<boolean> {
const notes = await this.getNotesWithPublishState(state, siteId);
return !!notes.length;
@ -205,7 +206,13 @@ export class AddonNotesOfflineProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved if stored, rejected if failure.
*/
async saveNote(userId: number, courseId: number, state: string, content: string, siteId?: string): Promise<void> {
async saveNote(
userId: number,
courseId: number,
state: AddonNotesPublishState,
content: string,
siteId?: string,
): Promise<void> {
const site = await CoreSites.getSite(siteId);
const now = CoreTimeUtils.timestamp();

View File

@ -42,7 +42,13 @@ export class AddonNotesProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with boolean: true if note was sent to server, false if stored in device.
*/
async addNote(userId: number, courseId: number, publishState: string, noteText: string, siteId?: string): Promise<boolean> {
async addNote(
userId: number,
courseId: number,
publishState: AddonNotesPublishState,
noteText: string,
siteId?: string,
): Promise<boolean> {
siteId = siteId || CoreSites.getCurrentSiteId();
// Convenience function to store a note to be synchronized later.
@ -82,7 +88,13 @@ export class AddonNotesProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when added, rejected otherwise.
*/
async addNoteOnline(userId: number, courseId: number, publishState: string, noteText: string, siteId?: string): Promise<void> {
async addNoteOnline(
userId: number,
courseId: number,
publishState: AddonNotesPublishState,
noteText: string,
siteId?: string,
): Promise<void> {
const notes: AddonNotesCreateNoteData[] = [
{
courseid: courseId,
@ -438,7 +450,7 @@ export type AddonNotesNote = {
created: number; // Time created (timestamp).
lastmodified: number; // Time of last modification (timestamp).
usermodified: number; // User id of the creator of this note.
publishstate: string; // State of the note (i.e. draft, public, site).
publishstate: AddonNotesPublishState; // State of the note (i.e. draft, public, site).
offline?: boolean;
};
@ -474,7 +486,7 @@ export type AddonNotesNoteFormatted = AddonNotesNote & {
export type AddonNotesCreateNoteData = {
userid: number; // Id of the user the note is about.
publishstate: string; // 'personal', 'course' or 'site'.
publishstate: AddonNotesPublishState; // 'personal', 'course' or 'site'.
courseid: number; // Course id of the note (in Moodle a note can only be created into a course,
// even for site and personal notes).
text: string; // The text of the message - text or HTML.
@ -504,3 +516,5 @@ export type AddonNotesCreateNotesWSResponse = {
type AddonNotesDeleteNotesWSParams = {
notes: number[]; // Array of Note Ids to be deleted.
};
export type AddonNotesPublishState = 'personal' | 'site' | 'course';

View File

@ -42,7 +42,7 @@ export class CoreRecaptchaModalComponent implements OnDestroy {
* Close modal.
*/
closeModal(): void {
ModalController.dismiss({
ModalController.dismiss(<CoreRecaptchaModalReturn>{
expired: this.expired,
value: this.value,
});
@ -119,3 +119,8 @@ export class CoreRecaptchaModalComponent implements OnDestroy {
}
}
export type CoreRecaptchaModalReturn = {
expired: boolean;
value: string;
};

View File

@ -16,9 +16,9 @@ import { Component, Input, OnInit } from '@angular/core';
import { CoreLang } from '@services/lang';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { ModalController } from '@singletons';
import { CoreRecaptchaModalComponent } from './recaptcha-modal';
import { CoreRecaptchaModalComponent, CoreRecaptchaModalReturn } from './recaptcha-modal';
/**
* Component that allows answering a recaptcha.
@ -66,7 +66,7 @@ export class CoreRecaptchaComponent implements OnInit {
// Modal to answer the recaptcha.
// This is because the size of the recaptcha is dynamic, so it could cause problems if it was displayed inline.
const modal = await ModalController.create({
const modalData = await CoreDomUtils.openModal<CoreRecaptchaModalReturn>({
component: CoreRecaptchaModalComponent,
cssClass: 'core-modal-fullscreen',
componentProps: {
@ -74,12 +74,10 @@ export class CoreRecaptchaComponent implements OnInit {
},
});
await modal.present();
const result = await modal.onWillDismiss();
this.expired = result.data.expired;
this.model![this.modelValueName] = result.data.value;
if (modalData) {
this.expired = modalData.expired;
this.model![this.modelValueName] = modalData.value;
}
}
}

View File

@ -69,7 +69,7 @@ export class CoreCommentsAddComponent {
CoreSites.getCurrentSiteId(),
);
ModalController.dismiss({ comment: commentsResponse }).finally(() => {
ModalController.dismiss(commentsResponse).finally(() => {
CoreDomUtils.showToast(
commentsResponse ? 'core.comments.eventcommentcreated' : 'core.datastoredoffline',
true,

View File

@ -30,7 +30,7 @@ import {
import { IonContent, IonRefresher } from '@ionic/angular';
import { ContextLevel, CoreConstants } from '@/core/constants';
import { CoreNavigator } from '@services/navigator';
import { ModalController, Translate } from '@singletons';
import { Translate } from '@singletons';
import { CoreUtils } from '@services/utils/utils';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
@ -279,19 +279,15 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
content: this.offlineComment ? this.offlineComment!.content : '',
};
const modal = await ModalController.create({
const comment = await CoreDomUtils.openModal<CoreCommentsDataWithUser>({
component: CoreCommentsAddComponent,
componentProps: params,
});
await modal.present();
const result = await modal.onDidDismiss();
if (result?.data?.comment) {
if (comment) {
this.invalidateComments();
const addedComments = await this.loadCommentProfile(result.data.comment);
const addedComments = await this.loadCommentProfile(comment);
// Add the comment to the top.
this.comments = [addedComments].concat(this.comments);
this.canDeleteComments = this.addDeleteCommentsAvailable;
@ -305,7 +301,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
countChange: 1,
}, CoreSites.getCurrentSiteId());
} else if (result?.data?.comment === false) {
} else if (comment === false) {
// Comments added in offline mode.
return this.loadOfflineData();
}

View File

@ -17,7 +17,7 @@ import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate';
import { CoreSite } from '@classes/site';
import { makeSingleton, ModalController, Translate } from '@singletons';
import { makeSingleton, Translate } from '@singletons';
import { CoreNavigator } from '@services/navigator';
import { Params } from '@angular/router';
import { CoreContentLinksChooseSiteModalComponent } from '../components/choose-site-modal/choose-site-modal';
@ -112,15 +112,13 @@ export class CoreContentLinksHelperProvider {
* @todo set correct root.
*/
async goToChooseSite(url: string): Promise<void> {
const modal = await ModalController.create({
await CoreDomUtils.openModal({
component: CoreContentLinksChooseSiteModalComponent,
componentProps: {
url: url,
},
cssClass: 'core-modal-fullscreen',
});
await modal.present();
}
/**

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Component, OnDestroy, NgZone, OnInit } from '@angular/core';
import { ModalController, IonRefresher } from '@ionic/angular';
import { IonRefresher } from '@ionic/angular';
import { CoreApp } from '@services/app';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
@ -76,7 +76,6 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
protected courseStatusObserver?: CoreEventObserver;
constructor(
protected modalCtrl: ModalController,
protected zone: NgZone,
) {
this.isMobile = CoreApp.isMobile();
@ -347,19 +346,16 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
if (error && error.errorcode === CoreCoursesProvider.ENROL_INVALID_KEY) {
// Initialize the self enrol modal.
const selfEnrolModal = await this.modalCtrl.create(
// Invalid password, show the modal to enter the password.
const modalData = await CoreDomUtils.openModal<string>(
{
component: CoreCoursesSelfEnrolPasswordComponent,
componentProps: { password },
},
);
// Invalid password, show the modal to enter the password.
await selfEnrolModal.present();
const data = await selfEnrolModal.onDidDismiss<string>();
if (typeof data?.data != 'undefined') {
this.selfEnrolInCourse(data.data, instanceId);
if (typeof modalData != 'undefined') {
this.selfEnrolInCourse(modalData, instanceId);
return;
}

View File

@ -13,8 +13,9 @@
// limitations under the License.
import { Component, ViewChild, ElementRef } from '@angular/core';
import { ModalController, NavParams } from '@ionic/angular';
import { NavParams } from '@ionic/angular';
import { CoreSites } from '@services/sites';
import { ModalController } from '@singletons';
import { CoreForms } from '@singletons/form';
/**
@ -30,7 +31,6 @@ export class CoreCoursesSelfEnrolPasswordComponent {
password = '';
constructor(
protected modalCtrl: ModalController,
navParams: NavParams,
) {
this.password = navParams.get('password') || '';
@ -42,7 +42,7 @@ export class CoreCoursesSelfEnrolPasswordComponent {
close(): void {
CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
this.modalCtrl.dismiss();
ModalController.dismiss();
}
/**
@ -57,7 +57,7 @@ export class CoreCoursesSelfEnrolPasswordComponent {
CoreForms.triggerFormSubmittedEvent(this.formElement, false, CoreSites.getCurrentSiteId());
this.modalCtrl.dismiss(this.password);
ModalController.dismiss(this.password);
}
}

View File

@ -24,7 +24,7 @@ import { CoreLoginHelper, CoreLoginHelperProvider } from '@features/login/servic
import { CoreSite } from '@classes/site';
import { CoreError } from '@classes/errors/error';
import { CoreConstants } from '@/core/constants';
import { Translate, ModalController } from '@singletons';
import { Translate } from '@singletons';
import { CoreUrl } from '@singletons/url';
import { CoreUrlUtils } from '@services/utils/url';
import { CoreLoginSiteHelpComponent } from '@features/login/components/site-help/site-help';
@ -215,24 +215,20 @@ export class CoreLoginSitePage implements OnInit {
* Show a help modal.
*/
async showHelp(): Promise<void> {
const modal = await ModalController.create({
await CoreDomUtils.openModal({
component: CoreLoginSiteHelpComponent,
cssClass: 'core-modal-fullscreen',
});
await modal.present();
}
/**
* Show an onboarding modal.
*/
async showOnboarding(): Promise<void> {
const modal = await ModalController.create({
await CoreDomUtils.openModal({
component: CoreLoginSiteOnboardingComponent,
cssClass: 'core-modal-fullscreen',
});
await modal.present();
}
/**

View File

@ -21,7 +21,7 @@ import {
CoreRatingProvider,
} from '@features/rating/services/rating';
import { CoreSites } from '@services/sites';
import { ModalController } from '@singletons';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreRatingRatingsComponent } from '../ratings/ratings';
@ -117,7 +117,7 @@ export class CoreRatingAggregateComponent implements OnChanges, OnDestroy {
return;
}
const modal = await ModalController.create({
await CoreDomUtils.openModal({
component: CoreRatingRatingsComponent,
componentProps: {
contextLevel: this.contextLevel,
@ -129,8 +129,6 @@ export class CoreRatingAggregateComponent implements OnChanges, OnDestroy {
courseId: this.courseId,
},
});
await modal.present();
}
/**

View File

@ -23,7 +23,7 @@ import { CoreFile } from '@services/file';
import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { AlertController, ApplicationInit, makeSingleton, ModalController, Platform, Translate } from '@singletons';
import { AlertController, ApplicationInit, makeSingleton, Platform, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { CoreLogger } from '@singletons/logger';
import { CoreSharedFilesListModalComponent } from '../components/list-modal/list-modal';
@ -150,17 +150,12 @@ export class CoreSharedFilesHelperProvider {
* @return Promise resolved when a file is picked, rejected if file picker is closed without selecting a file.
*/
async pickSharedFile(mimetypes?: string[]): Promise<CoreFileUploaderHandlerResult> {
const modal = await ModalController.create({
const file = await CoreDomUtils.openModal<FileEntry>({
component: CoreSharedFilesListModalComponent,
cssClass: 'core-modal-fullscreen',
componentProps: { mimetypes, pick: true },
});
await modal.present();
const result = await modal.onDidDismiss();
const file: FileEntry | undefined = result.data;
if (!file) {
// User cancelled.
throw new CoreCanceledError();

View File

@ -1684,23 +1684,43 @@ export class CoreDomUtilsProvider {
/**
* Opens a Modal.
*
* @param opts Modal Options.
* @param modalOptions Modal Options.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async openModal<T = any>(
opts: ModalOptions,
async openModal<T = unknown>(
modalOptions: ModalOptions,
): Promise<T | undefined> {
const modal = await ModalController.create(opts);
const modal = await ModalController.create(modalOptions);
await modal.present();
// If onDidDismiss is nedded we can add a new param to the function to wait one function or the other.
const result = await modal.onWillDismiss<T>();
if (result?.data) {
return result?.data;
}
}
/**
* Opens a side Modal.
*
* @param modalOptions Modal Options.
*/
async openSideModal<T = unknown>(
modalOptions: ModalOptions,
): Promise<T | undefined> {
modalOptions = Object.assign(modalOptions, {
cssClass: 'core-modal-lateral',
showBackdrop: true,
backdropDismiss: true,
// @todo enterAnimation: 'core-modal-lateral-transition',
// @todo leaveAnimation: 'core-modal-lateral-transition',
});
return await this.openModal<T>(modalOptions);
}
/**
* View an image in a modal.
*
@ -1721,7 +1741,7 @@ export class CoreDomUtilsProvider {
return;
}
const modal = await ModalController.create({
await CoreDomUtils.openModal({
component: CoreViewerImageComponent,
componentProps: {
title,
@ -1732,7 +1752,6 @@ export class CoreDomUtilsProvider {
cssClass: fullScreen ? 'core-modal-fullscreen' : '',
});
await modal.present();
}
/**

View File

@ -19,11 +19,12 @@ import { ModalOptions } from '@ionic/core';
import { CoreApp } from '@services/app';
import { CoreLang } from '@services/lang';
import { CoreAnyError, CoreError } from '@classes/errors/error';
import { makeSingleton, ModalController, Translate } from '@singletons';
import { makeSingleton, Translate } from '@singletons';
import { CoreWSFile } from '@services/ws';
import { Locutus } from '@singletons/locutus';
import { CoreViewerTextComponent } from '@features/viewer/components/text/text';
import { CoreFileHelper } from '@services/file-helper';
import { CoreDomUtils } from './dom';
/**
* Different type of errors the app can treat.
@ -1097,9 +1098,7 @@ export class CoreTextUtilsProvider {
...options,
};
const modal = await ModalController.create(modalOptions);
await modal.present();
await CoreDomUtils.openModal(modalOptions);
}
}

View File

@ -26,7 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTextUtils } from '@services/utils/text';
import { CoreWSError } from '@classes/errors/wserror';
import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, QRScanner, Translate, ModalController } from '@singletons';
import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, QRScanner, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { CoreFileSizeSum } from '@services/plugin-file-delegate';
import { CoreViewerQRScannerComponent } from '@features/viewer/components/qr-scanner/qr-scanner';
@ -1515,20 +1515,14 @@ export class CoreUtilsProvider {
* @param title Title of the modal. Defaults to "QR reader".
* @return Promise resolved with the captured text or undefined if cancelled or error.
*/
async scanQR(title?: string): Promise<string> {
const modal = await ModalController.create({
async scanQR(title?: string): Promise<string | undefined> {
return await CoreDomUtils.openModal<string>({
component: CoreViewerQRScannerComponent,
cssClass: 'core-modal-fullscreen',
componentProps: {
title,
},
});
await modal.present();
const result = await modal.onWillDismiss();
return result.data;
}
/**

View File

@ -50,6 +50,11 @@ ion-item.ion-text-wrap ion-label {
white-space: normal !important;
}
// Buttons.
.button-clear {
--ion-color-primary: var(--ion-text-color);
}
// It fixes the click on links where ion-ripple-effect is present.
.ion-activatable ion-label,
.item-multiple-items ion-label {