From 468400b13ca94869b6ee28b9409454e994d8a7fd Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 10 Mar 2021 11:20:10 +0100 Subject: [PATCH 1/3] MOBILE-3634 core: Add ionic5 and app version classes to body --- src/app/app.component.ts | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 96d103515..105795baa 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -33,6 +33,10 @@ import { CoreWindow } from '@singletons/window'; import { CoreCustomURLSchemes } from '@services/urlschemes'; import { CoreUtils } from '@services/utils/utils'; import { CoreUrlUtils } from '@services/utils/url'; +import { CoreConstants } from '@/core/constants'; + +const MOODLE_VERSION_PREFIX = 'version-'; +const MOODLEAPP_VERSION_PREFIX = 'moodleapp-'; @Component({ selector: 'app-root', @@ -60,6 +64,8 @@ export class AppComponent implements OnInit, AfterViewInit { ngOnInit(): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any const win = window; + document.body.classList.add('ionic5'); + this.addVersionClass(MOODLEAPP_VERSION_PREFIX, CoreConstants.CONFIG.versionname.replace('-dev', '')); CoreEvents.on(CoreEvents.LOGOUT, () => { // Go to sites page when user is logged out. @@ -69,7 +75,7 @@ export class AppComponent implements OnInit, AfterViewInit { CoreLang.clearCustomStrings(); // Remove version classes from body. - this.removeVersionClass(); + this.removeVersionClass(MOODLE_VERSION_PREFIX); }); // Listen for session expired events. @@ -173,8 +179,8 @@ export class AppComponent implements OnInit, AfterViewInit { const info = site.getInfo(); if (info) { // Add version classes to body. - this.removeVersionClass(); - this.addVersionClass(CoreSites.getReleaseNumber(info.release || '')); + this.removeVersionClass(MOODLE_VERSION_PREFIX); + this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(info.release || '')); } } @@ -186,8 +192,8 @@ export class AppComponent implements OnInit, AfterViewInit { this.loadCustomStrings(); // Add version classes to body. - this.removeVersionClass(); - this.addVersionClass(CoreSites.getReleaseNumber(data.release || '')); + this.removeVersionClass(MOODLE_VERSION_PREFIX); + this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(data.release || '')); } }); @@ -196,8 +202,8 @@ export class AppComponent implements OnInit, AfterViewInit { this.loadCustomStrings(); // Add version classes to body. - this.removeVersionClass(); - this.addVersionClass(CoreSites.getReleaseNumber(data.release || '')); + this.removeVersionClass(MOODLE_VERSION_PREFIX); + this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(data.release || '')); } }); @@ -262,29 +268,32 @@ export class AppComponent implements OnInit, AfterViewInit { /** * Convenience function to add version to body classes. * + * @param prefix Prefix to add to the class. * @param release Current release number of the site. */ - protected addVersionClass(release: string): void { + protected addVersionClass(prefix: string, release: string): void { const parts = release.split('.', 3); parts[1] = parts[1] || '0'; parts[2] = parts[2] || '0'; document.body.classList.add( - 'version-' + parts[0], - 'version-' + parts[0] + '-' + parts[1], - 'version-' + parts[0] + '-' + parts[1] + '-' + parts[2], + prefix + parts[0], + prefix + parts[0] + '-' + parts[1], + prefix + parts[0] + '-' + parts[1] + '-' + parts[2], ); } /** * Convenience function to remove all version classes form body. + * + * @param prefix Prefix of to the class. */ - protected removeVersionClass(): void { + protected removeVersionClass(prefix: string): void { const remove: string[] = []; Array.from(document.body.classList).forEach((tempClass) => { - if (tempClass.substring(0, 8) == 'version-') { + if (tempClass.substring(0, 8) == prefix) { remove.push(tempClass); } }); From a3f4fa2234541d54776dd144728f8272d9ae54b7 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 10 Mar 2021 11:20:24 +0100 Subject: [PATCH 2/3] MOBILE-3634 remotethemes: Support remote themes --- src/addons/addons.module.ts | 2 + .../remotethemes/remotethemes.module.ts | 37 ++ .../remotethemes/services/remotethemes.ts | 452 ++++++++++++++++++ .../services/pushnotifications.ts | 2 +- src/core/services/local-notifications.ts | 3 +- src/core/singletons/events.ts | 11 +- 6 files changed, 503 insertions(+), 4 deletions(-) create mode 100644 src/addons/remotethemes/remotethemes.module.ts create mode 100644 src/addons/remotethemes/services/remotethemes.ts diff --git a/src/addons/addons.module.ts b/src/addons/addons.module.ts index 6bf6d8aa5..1f507b5b8 100644 --- a/src/addons/addons.module.ts +++ b/src/addons/addons.module.ts @@ -27,6 +27,7 @@ import { AddonModModule } from './mod/mod.module'; import { AddonQbehaviourModule } from './qbehaviour/qbehaviour.module'; import { AddonQtypeModule } from './qtype/qtype.module'; import { AddonBlogModule } from './blog/blog.module'; +import { AddonRemoteThemesModule } from './remotethemes/remotethemes.module'; @NgModule({ imports: [ @@ -43,6 +44,7 @@ import { AddonBlogModule } from './blog/blog.module'; AddonModModule, AddonQbehaviourModule, AddonQtypeModule, + AddonRemoteThemesModule, ], }) export class AddonsModule {} diff --git a/src/addons/remotethemes/remotethemes.module.ts b/src/addons/remotethemes/remotethemes.module.ts new file mode 100644 index 000000000..7a2b74e1d --- /dev/null +++ b/src/addons/remotethemes/remotethemes.module.ts @@ -0,0 +1,37 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; +import { AddonRemoteThemes, AddonRemoteThemesProvider } from './services/remotethemes'; + +// List of providers (without handlers). +export const ADDON_REMOTETHEMES_SERVICES: Type[] = [ + AddonRemoteThemesProvider, +]; + +@NgModule({ + declarations: [], + imports: [], + providers: [ + { + provide: APP_INITIALIZER, + multi: true, + deps: [], + useFactory: () => async () => { + await AddonRemoteThemes.initialize(); + }, + }, + ], +}) +export class AddonRemoteThemesModule {} diff --git a/src/addons/remotethemes/services/remotethemes.ts b/src/addons/remotethemes/services/remotethemes.ts new file mode 100644 index 000000000..eea64fc8e --- /dev/null +++ b/src/addons/remotethemes/services/remotethemes.ts @@ -0,0 +1,452 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable } from '@angular/core'; +import { Md5 } from 'ts-md5/dist/md5'; + +import { CoreConstants } from '@/core/constants'; +import { CoreError } from '@classes/errors/error'; +import { CoreSitePublicConfigResponse } from '@classes/site'; +import { CoreApp } from '@services/app'; +import { CoreFile } from '@services/file'; +import { CoreFilepool } from '@services/filepool'; +import { CoreSites } from '@services/sites'; +import { CoreUtils } from '@services/utils/utils'; +import { CoreWS } from '@services/ws'; +import { CoreLogger } from '@singletons/logger'; +import { makeSingleton } from '@singletons'; +import { CoreEvents } from '@singletons/events'; + +const SEPARATOR_35 = /\/\*\*? *3\.5(\.0)? *styles? *\*\//i; // A comment like "/* 3.5 styles */". +const TMP_SITE_ID = 'tmpsite'; + +/** + * Service to handle remote themes. A remote theme is a CSS sheet stored in the site that allows customising the Mobile app. + */ +@Injectable({ providedIn: 'root' }) +export class AddonRemoteThemesProvider { + + static readonly COMPONENT = 'mmaRemoteStyles'; + + protected logger: CoreLogger; + protected stylesEls: {[siteId: string]: { element: HTMLStyleElement; hash: string }} = {}; + + constructor() { + this.logger = CoreLogger.getInstance('AddonRemoteThemesProvider'); + } + + /** + * Initialize remote themes. + */ + async initialize(): Promise { + this.listenEvents(); + + // Preload the current site styles first, we want this to be fast. + await this.preloadCurrentSite(); + + // Preload the styles of the rest of sites. + await this.preloadSites(); + } + + /** + * Listen events. + */ + protected listenEvents(): void { + let addingSite: string | undefined; + + // When a new site is added to the app, add its styles. + CoreEvents.on(CoreEvents.SITE_ADDED, async (data) => { + addingSite = data.siteId; + + try { + await this.addSite(data.siteId); + + if (addingSite == data.siteId) { + addingSite = undefined; + } + + // User has logged in, remove tmp styles and enable loaded styles. + if (data.siteId == CoreSites.getCurrentSiteId()) { + this.unloadTmpStyles(); + this.enable(data.siteId); + } + } catch (error) { + this.logger.error('Error adding remote styles for new site', error); + } + }); + + // Update styles when current site is updated. + CoreEvents.on(CoreEvents.SITE_UPDATED, (data) => { + if (data.siteId === CoreSites.getCurrentSiteId()) { + this.load(data.siteId).catch((error) => { + this.logger.error('Error loading site after site update', error); + }); + } + }); + + // Enable styles of current site on login. + CoreEvents.on(CoreEvents.LOGIN, (data) => { + this.unloadTmpStyles(); + this.enable(data.siteId); + }); + + // Disable added styles on logout. + CoreEvents.on(CoreEvents.LOGOUT, () => { + this.clear(); + }); + + // Remove site styles when a site is deleted. + CoreEvents.on(CoreEvents.SITE_DELETED, (site) => { + this.removeSite(site.getId()); + }); + + // Load temporary styles when site config is checked in login. + CoreEvents.on(CoreEvents.LOGIN_SITE_CHECKED, (data) => { + this.loadTmpStylesForSiteConfig(data.config).catch((error) => { + this.logger.error('Error loading tmp styles', error); + }); + }); + + // Unload temporary styles when site config is "unchecked" in login. + CoreEvents.on(CoreEvents.LOGIN_SITE_UNCHECKED, (data) => { + if (data.siteId && data.siteId === addingSite) { + // The tmp styles are from a site that is being added permanently. + // Wait for the final site styles to be loaded before removing the tmp styles so there is no blink effect. + return; + } + + // The tmp styles are from a site that wasn't added in the end. Just remove them. + this.unloadTmpStyles(); + }); + } + + /** + * Add a style element for a site and load the styles for that element. The style will be disabled. + * + * @param siteId Site ID. + * @return Promise resolved when added and loaded. + */ + async addSite(siteId?: string): Promise { + if (!siteId || this.stylesEls[siteId]) { + // Invalid site ID or style already added. + return; + } + + // Create the style and add it to the header. + this.initSiteStyleElement(siteId, true); + + try { + await this.load(siteId, true); + } catch (error) { + this.logger.error('Error loading site after site init', error); + } + } + + /** + * Clear styles added to the DOM, disabling them all. + */ + clear(): void { + // Disable all the styles. + this.disableElementsBySelector('style[id*=mobilecssurl]'); + + // Set StatusBar properties. + CoreApp.setStatusBarColor(); + } + + /** + * Create a style element. + * + * @param id ID to set to the element. + * @param disabled Whether the element should be disabled. + * @return New element. + */ + protected createStyleElement(id: string, disabled: boolean): HTMLStyleElement { + const styleEl = document.createElement('style'); + + styleEl.setAttribute('id', id); + this.disableElement(styleEl, disabled); + + return styleEl; + } + + /** + * Enabled or disable a certain style element. + * + * @param element The element to enable or disable. + * @param disable Whether to disable or enable the element. + */ + disableElement(element: HTMLStyleElement, disable: boolean): void { + // Setting disabled should be enough, but we also set the attribute so it can be seen in the DOM which ones are disabled. + // Cast to any because the HTMLStyleElement type doesn't define the disabled attribute. + ( element).disabled = !!disable; // eslint-disable-line @typescript-eslint/no-explicit-any + + if (disable) { + element.setAttribute('disabled', 'true'); + } else { + element.removeAttribute('disabled'); + + if (element.innerHTML != '') { + CoreApp.setStatusBarColor(); + } + } + } + + /** + * Disable all the style elements based on a query selector. + * + * @param selector The selector to get the style elements. + */ + protected disableElementsBySelector(selector: string): void { + const styles = Array.from(document.querySelectorAll(selector)); + + styles.forEach((style) => { + this.disableElement(style, true); + }); + } + + /** + * Downloads a CSS file and remove old files if needed. + * + * @param siteId Site ID. + * @param url File URL. + * @return Promise resolved when the file is downloaded. + */ + protected async downloadFileAndRemoveOld(siteId: string, url: string): Promise { + + try { + // Check if the file is downloaded. + const state = await CoreFilepool.getFileStateByUrl(siteId, url); + + if (state == CoreConstants.NOT_DOWNLOADED) { + // File not downloaded, URL has changed or first time. Delete downloaded CSS files. + await CoreFilepool.removeFilesByComponent(siteId, AddonRemoteThemesProvider.COMPONENT, 1); + } + } catch { + // An error occurred while getting state (shouldn't happen). Don't delete downloaded file. + } + + return CoreFilepool.downloadUrl(siteId, url, false, AddonRemoteThemesProvider.COMPONENT, 1); + } + + /** + * Enable the styles of a certain site. + * + * @param siteId Site ID. If not defined, current site. + */ + enable(siteId?: string): void { + siteId = siteId || CoreSites.getCurrentSiteId(); + + if (this.stylesEls[siteId]) { + this.disableElement(this.stylesEls[siteId].element, false); + } + } + + /** + * Get remote styles of a certain site. + * + * @param siteId Site ID. If not defined, current site. + * @return Promise resolved with the styles and the URL of the CSS file, + * resolved with undefined if no styles to load. + */ + async get(siteId?: string): Promise<{fileUrl: string; styles: string} | undefined> { + siteId = siteId || CoreSites.getCurrentSiteId(); + + const site = await CoreSites.getSite(siteId); + const infos = site.getInfo(); + + if (!infos?.mobilecssurl) { + if (infos?.mobilecssurl === '') { + // CSS URL is empty. Delete downloaded files (if any). + CoreFilepool.removeFilesByComponent(siteId, AddonRemoteThemesProvider.COMPONENT, 1); + } + + return; + } + + let fileUrl = infos.mobilecssurl; + + if (CoreFile.isAvailable()) { + // The file system is available. Download the file and remove old CSS files if needed. + fileUrl = await this.downloadFileAndRemoveOld(siteId, fileUrl); + } + + this.logger.debug('Loading styles from: ', fileUrl); + + // Get the CSS content using HTTP because we will treat the styles before saving them in the file. + const text = await CoreWS.getText(fileUrl); + + return { fileUrl, styles: this.get35Styles(text) }; + } + + /** + * Check if the CSS code has a separator for 3.5 styles. If it does, get only the styles after the separator. + * + * @param cssCode The CSS code to check. + * @return The filtered styles. + */ + protected get35Styles(cssCode: string): string { + const separatorPos = cssCode.search(SEPARATOR_35); + if (separatorPos > -1) { + return cssCode.substr(separatorPos).replace(SEPARATOR_35, ''); + } + + return cssCode; + } + + /** + * Init the style element for a site. + * + * @param siteId Site ID. + * @param disabled Whether the element should be disabled. + */ + protected initSiteStyleElement(siteId: string, disabled: boolean): void { + if (this.stylesEls[siteId]) { + // Already initialized, ignore. + return; + } + + // Create the style and add it to the header. + const styleEl = this.createStyleElement('mobilecssurl-' + siteId, disabled); + + document.head.appendChild(styleEl); + this.stylesEls[siteId] = { + element: styleEl, + hash: '', + }; + } + + /** + * Load styles for a certain site. + * + * @param siteId Site ID. If not defined, current site. + * @param disabled Whether loaded styles should be disabled. + * @return Promise resolved when styles are loaded. + */ + async load(siteId?: string, disabled?: boolean): Promise { + siteId = siteId || CoreSites.getCurrentSiteId(); + disabled = !!disabled; + + if (!siteId || !this.stylesEls[siteId]) { + throw new CoreError('Cannot load remote styles, site not found: ${siteId}'); + } + + this.logger.debug('Load site', siteId, disabled); + + // Enable or disable the styles. + this.disableElement(this.stylesEls[siteId].element, disabled); + + const data = await this.get(siteId); + + if (typeof data == 'undefined') { + // Nothing to load. + return; + } + + const hash = Md5.hashAsciiStr(data.styles); + + // Update the styles only if they have changed. + if (this.stylesEls[siteId].hash !== hash) { + this.stylesEls[siteId].element.innerHTML = data.styles; + this.stylesEls[siteId].hash = hash; + + // Adding styles to a style element automatically enables it. Disable it again. + if (disabled) { + this.disableElement(this.stylesEls[siteId].element, true); + } + } + + // Styles have been loaded, now treat the CSS. + CoreUtils.ignoreErrors( + CoreFilepool.treatCSSCode(siteId, data.fileUrl, data.styles, AddonRemoteThemesProvider.COMPONENT, 2), + ); + } + + /** + * Load styles for a temporary site. These styles aren't prefetched. + * + * @param url URL to get the styles from. + * @return Promise resolved when loaded. + */ + async loadTmpStyles(url?: string): Promise { + if (!url) { + return; + } + + let text = await CoreWS.getText(url); + + text = this.get35Styles(text); + + this.initSiteStyleElement(TMP_SITE_ID, false); + this.stylesEls[TMP_SITE_ID].element.innerHTML = text; + } + + /** + * Load styles for a temporary site, given its public config. These styles aren't prefetched. + * + * @param config Site public config. + * @return Promise resolved when loaded. + */ + loadTmpStylesForSiteConfig(config: CoreSitePublicConfigResponse): Promise { + return this.loadTmpStyles(config.mobilecssurl); + } + + /** + * Preload the styles of the current site (stored in DB). + * + * @return Promise resolved when loaded. + */ + async preloadCurrentSite(): Promise { + const siteId = await CoreUtils.ignoreErrors(CoreSites.getStoredCurrentSiteId()); + + if (!siteId) { + // No current site stored. + return; + } + + return this.addSite(siteId); + } + + /** + * Preload the styles of all the stored sites. + * + * @return Promise resolved when loaded. + */ + async preloadSites(): Promise { + const ids = await CoreSites.getSitesIds(); + + await CoreUtils.allPromises(ids.map((siteId) => this.addSite(siteId))); + } + + /** + * Remove the styles of a certain site. + * + * @param siteId Site ID. + */ + removeSite(siteId: string): void { + if (siteId && this.stylesEls[siteId]) { + document.head.removeChild(this.stylesEls[siteId].element); + delete this.stylesEls[siteId]; + } + } + + /** + * Unload styles for a temporary site. + */ + unloadTmpStyles(): void { + return this.removeSite(TMP_SITE_ID); + } + +} + +export const AddonRemoteThemes = makeSingleton(AddonRemoteThemesProvider); diff --git a/src/core/features/pushnotifications/services/pushnotifications.ts b/src/core/features/pushnotifications/services/pushnotifications.ts index c6c0c6f99..40090c253 100644 --- a/src/core/features/pushnotifications/services/pushnotifications.ts +++ b/src/core/features/pushnotifications/services/pushnotifications.ts @@ -89,7 +89,7 @@ export class CorePushNotificationsProvider { } }); - CoreEvents.on(CoreEvents.SITE_DELETED, async (site: CoreSite) => { + CoreEvents.on(CoreEvents.SITE_DELETED, async (site) => { try { await Promise.all([ this.unregisterDeviceOnMoodle(site), diff --git a/src/core/services/local-notifications.ts b/src/core/services/local-notifications.ts index 2e18fc047..df0869718 100644 --- a/src/core/services/local-notifications.ts +++ b/src/core/services/local-notifications.ts @@ -22,7 +22,6 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { SQLiteDB } from '@classes/sqlitedb'; -import { CoreSite } from '@classes/site'; import { CoreQueueRunner } from '@classes/queue-runner'; import { CoreError } from '@classes/errors/error'; import { CoreConstants } from '@/core/constants'; @@ -125,7 +124,7 @@ export class CoreLocalNotificationsProvider { this.createDefaultChannel(); }); - CoreEvents.on(CoreEvents.SITE_DELETED, (site: CoreSite) => { + CoreEvents.on(CoreEvents.SITE_DELETED, (site) => { if (site) { this.cancelSiteNotifications(site.id!); } diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts index 849475ae4..2e7e148c8 100644 --- a/src/core/singletons/events.ts +++ b/src/core/singletons/events.ts @@ -16,7 +16,7 @@ import { Params } from '@angular/router'; import { Subject } from 'rxjs'; import { CoreLogger } from '@singletons/logger'; -import { CoreSiteInfoResponse } from '@classes/site'; +import { CoreSite, CoreSiteInfoResponse, CoreSitePublicConfigResponse } from '@classes/site'; /** * Observer instance to stop listening to an event. @@ -34,6 +34,7 @@ export interface CoreEventObserver { export interface CoreEventsData { [CoreEvents.SITE_UPDATED]: CoreEventSiteUpdatedData; [CoreEvents.SITE_ADDED]: CoreEventSiteAddedData; + [CoreEvents.SITE_DELETED]: CoreSite; [CoreEvents.SESSION_EXPIRED]: CoreEventSessionExpiredData; [CoreEvents.CORE_LOADING_CHANGED]: CoreEventLoadingChangedData; [CoreEvents.COURSE_STATUS_CHANGED]: CoreEventCourseStatusChanged; @@ -46,6 +47,7 @@ export interface CoreEventsData { [CoreEvents.SECTION_STATUS_CHANGED]: CoreEventSectionStatusChangedData; [CoreEvents.ACTIVITY_DATA_SENT]: CoreEventActivityDataSentData; [CoreEvents.IAB_LOAD_START]: InAppBrowserEvent; + [CoreEvents.LOGIN_SITE_CHECKED]: CoreEventLoginSiteCheckedData; }; /* @@ -340,3 +342,10 @@ export type CoreEventSectionStatusChangedData = CoreEventSiteData & { export type CoreEventActivityDataSentData = CoreEventSiteData & { module: string; }; + +/** + * Data passed to LOGIN_SITE_CHECKED event. + */ +export type CoreEventLoginSiteCheckedData = { + config: CoreSitePublicConfigResponse; +}; From 7e8e49707f3712a8dd0b845171d5a4009f8416f8 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 10 Mar 2021 12:30:18 +0100 Subject: [PATCH 3/3] MOBILE-3634 core: Augment CoreEventsData everywhere --- .../components/myoverview/myoverview.ts | 4 +-- .../recentlyaccessedcourses.ts | 2 +- .../starredcourses/starredcourses.ts | 2 +- .../calendar/components/calendar/calendar.ts | 3 +- .../calendar/components/filter/filter.ts | 2 +- .../upcoming-events/upcoming-events.ts | 3 +- src/addons/calendar/pages/day/day.page.ts | 17 +++++---- .../pages/edit-event/edit-event.page.ts | 7 ++-- src/addons/calendar/pages/event/event.page.ts | 9 +++-- src/addons/calendar/pages/index/index.page.ts | 14 ++++---- src/addons/calendar/pages/list/list.page.ts | 19 +++++----- src/addons/calendar/services/calendar-sync.ts | 2 +- src/addons/calendar/services/calendar.ts | 21 +++++++++++ .../pages/contacts-35/contacts.page.ts | 3 +- .../messages/pages/contacts/contacts.page.ts | 6 ++-- .../pages/discussion/discussion.page.ts | 23 +++++------- .../pages/discussions-35/discussions.page.ts | 6 ++-- .../group-conversations.page.ts | 22 ++++-------- .../messages/pages/search/search.page.ts | 3 +- .../messages/services/handlers/mainmenu.ts | 17 ++++----- src/addons/messages/services/messages-sync.ts | 4 +-- src/addons/messages/services/messages.ts | 21 +++++++++++ .../mod/assign/components/index/index.ts | 9 ++--- .../components/submission/submission.ts | 10 +++--- src/addons/mod/assign/pages/edit/edit.ts | 10 +++--- .../submission-list/submission-list.page.ts | 5 ++- src/addons/mod/assign/services/assign-sync.ts | 6 ++-- src/addons/mod/assign/services/assign.ts | 18 ++++++++++ src/addons/mod/forum/services/sync.ts | 6 ++-- .../mod/lesson/components/index/index.ts | 3 +- .../mod/lesson/pages/player/player.page.ts | 4 +-- src/addons/mod/lesson/services/lesson-sync.ts | 6 ++-- src/addons/mod/lesson/services/lesson.ts | 25 ++++++++++--- src/addons/mod/quiz/components/index/index.ts | 2 +- .../mod/quiz/pages/player/player.page.ts | 7 ++-- src/addons/mod/quiz/services/quiz-sync.ts | 6 ++-- src/addons/mod/quiz/services/quiz.ts | 18 ++++++++-- .../notifications/pages/settings/settings.ts | 4 +-- .../services/handlers/mainmenu.ts | 7 ++-- src/app/app.component.ts | 22 +++++------- src/core/classes/site.ts | 4 +-- .../send-message-form/send-message-form.ts | 4 +-- .../components/user-avatar/user-avatar.ts | 4 +-- .../comments/components/comments/comments.ts | 8 ++--- .../comments/pages/viewer/viewer.page.ts | 8 ++--- .../comments/services/comments-sync.ts | 6 ++-- .../features/comments/services/comments.ts | 16 +++++++++ .../course/classes/main-resource-component.ts | 4 +-- .../course/components/format/format.ts | 6 ++-- .../course/components/module/module.ts | 4 +-- .../course/pages/contents/contents.ts | 10 +++--- src/core/features/course/pages/index/index.ts | 4 +-- .../features/course/services/course-helper.ts | 8 ++--- src/core/features/course/services/course.ts | 17 +++++++-- .../services/module-prefetch-delegate.ts | 8 ++--- src/core/features/course/services/sync.ts | 6 ++-- .../course-progress/course-progress.ts | 6 ++-- .../courses/pages/my-courses/my-courses.ts | 3 +- src/core/features/courses/services/courses.ts | 30 +++++++++++++--- .../features/login/services/login-helper.ts | 4 +-- .../rating/components/aggregate/aggregate.ts | 4 +-- .../features/rating/components/rate/rate.ts | 4 +-- src/core/features/settings/pages/site/site.ts | 4 +-- .../settings/pages/space-usage/space-usage.ts | 4 +-- .../pages/synchronization/synchronization.ts | 4 +-- .../services/siteplugins-helper.ts | 4 +-- .../features/user/pages/about/about.page.ts | 4 +-- .../user/pages/profile/profile.page.ts | 12 +++---- .../features/user/services/user-delegate.ts | 2 +- src/core/features/user/services/user.ts | 20 +++++++++-- src/core/singletons/events.ts | 36 ++++++++++++------- 71 files changed, 373 insertions(+), 263 deletions(-) diff --git a/src/addons/block/myoverview/components/myoverview/myoverview.ts b/src/addons/block/myoverview/components/myoverview/myoverview.ts index 44624701f..630d60a28 100644 --- a/src/addons/block/myoverview/components/myoverview/myoverview.ts +++ b/src/addons/block/myoverview/components/myoverview/myoverview.ts @@ -17,7 +17,7 @@ import { IonSearchbar } from '@ionic/angular'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreSites } from '@services/sites'; -import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData, CoreCourses } from '@features/courses/services/courses'; +import { CoreCoursesProvider, CoreCourses } from '@features/courses/services/courses'; import { CoreCoursesHelper, CoreEnrolledCourseDataWithOptions } from '@features/courses/services/courses-helper'; import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper'; import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate'; @@ -160,7 +160,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem this.coursesObserver = CoreEvents.on( CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, - (data: CoreCoursesMyCoursesUpdatedEventData) => { + (data) => { if (data.action == CoreCoursesProvider.ACTION_ENROL || data.action == CoreCoursesProvider.ACTION_STATE_CHANGED) { this.refreshCourseList(); diff --git a/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts b/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts index 8ed2d001e..3b6d98336 100644 --- a/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts +++ b/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts @@ -76,7 +76,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom this.coursesObserver = CoreEvents.on( CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, - (data: CoreCoursesMyCoursesUpdatedEventData) => { + (data) => { if (this.shouldRefreshOnUpdatedEvent(data)) { this.refreshCourseList(); diff --git a/src/addons/block/starredcourses/components/starredcourses/starredcourses.ts b/src/addons/block/starredcourses/components/starredcourses/starredcourses.ts index fb105df7a..edafb09e6 100644 --- a/src/addons/block/starredcourses/components/starredcourses/starredcourses.ts +++ b/src/addons/block/starredcourses/components/starredcourses/starredcourses.ts @@ -75,7 +75,7 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im this.coursesObserver = CoreEvents.on( CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, - (data: CoreCoursesMyCoursesUpdatedEventData) => { + (data) => { if (this.shouldRefreshOnUpdatedEvent(data)) { this.refreshCourseList(); diff --git a/src/addons/calendar/components/calendar/calendar.ts b/src/addons/calendar/components/calendar/calendar.ts index 09391982a..34eb7ee31 100644 --- a/src/addons/calendar/components/calendar/calendar.ts +++ b/src/addons/calendar/components/calendar/calendar.ts @@ -34,7 +34,6 @@ import { AddonCalendarWeek, AddonCalendarWeekDaysTranslationKeys, AddonCalendarEventToDisplay, - AddonCalendarUpdatedEventEvent, AddonCalendarDayName, } from '../../services/calendar'; import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper'; @@ -105,7 +104,7 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro // Listen for events "undeleted" (offline). this.undeleteEventObserver = CoreEvents.on( AddonCalendarProvider.UNDELETED_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (!data || !data.eventId) { return; } diff --git a/src/addons/calendar/components/filter/filter.ts b/src/addons/calendar/components/filter/filter.ts index 63a29d00e..11ecb8eb8 100644 --- a/src/addons/calendar/components/filter/filter.ts +++ b/src/addons/calendar/components/filter/filter.ts @@ -78,7 +78,7 @@ export class AddonCalendarFilterPopoverComponent implements OnInit { this.filter.filtered = this.filter.courseId > 0 || this.types.some((name) => !this.filter[name]); - CoreEvents.trigger(AddonCalendarProvider.FILTER_CHANGED_EVENT, this.filter); + CoreEvents.trigger(AddonCalendarProvider.FILTER_CHANGED_EVENT, this.filter); } } diff --git a/src/addons/calendar/components/upcoming-events/upcoming-events.ts b/src/addons/calendar/components/upcoming-events/upcoming-events.ts index abd2c1b9c..ae0448d60 100644 --- a/src/addons/calendar/components/upcoming-events/upcoming-events.ts +++ b/src/addons/calendar/components/upcoming-events/upcoming-events.ts @@ -20,7 +20,6 @@ import { AddonCalendarProvider, AddonCalendarEventToDisplay, AddonCalendar, - AddonCalendarUpdatedEventEvent, } from '../../services/calendar'; import { AddonCalendarHelper, AddonCalendarFilter } from '../../services/calendar-helper'; import { AddonCalendarOffline } from '../../services/calendar-offline'; @@ -75,7 +74,7 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On // Listen for events "undeleted" (offline). this.undeleteEventObserver = CoreEvents.on( AddonCalendarProvider.UNDELETED_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (!data || !data.eventId) { return; } diff --git a/src/addons/calendar/pages/day/day.page.ts b/src/addons/calendar/pages/day/day.page.ts index 2bd06f1c4..9e40f97a1 100644 --- a/src/addons/calendar/pages/day/day.page.ts +++ b/src/addons/calendar/pages/day/day.page.ts @@ -26,11 +26,10 @@ import { AddonCalendarEventToDisplay, AddonCalendarCalendarDay, AddonCalendarEventType, - AddonCalendarUpdatedEventEvent, } from '../../services/calendar'; import { AddonCalendarOffline } from '../../services/calendar-offline'; import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper'; -import { AddonCalendarSync, AddonCalendarSyncEvents, AddonCalendarSyncProvider } from '../../services/calendar-sync'; +import { AddonCalendarSync, AddonCalendarSyncProvider } from '../../services/calendar-sync'; import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses'; import { CoreCoursesHelper } from '@features/courses/services/courses-helper'; import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter'; @@ -114,7 +113,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { // Listen for events added. When an event is added, reload the data. this.newEventObserver = CoreEvents.on( AddonCalendarProvider.NEW_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (data && data.eventId) { this.loaded = false; this.refreshData(true, true); @@ -132,7 +131,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { // Listen for events edited. When an event is edited, reload the data. this.editEventObserver = CoreEvents.on( AddonCalendarProvider.EDIT_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (data && data.eventId) { this.loaded = false; this.refreshData(true, true); @@ -148,7 +147,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { }, this.currentSiteId); // Refresh data if calendar events are synchronized manually but not by this page. - this.manualSyncObserver = CoreEvents.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data: AddonCalendarSyncEvents) => { + this.manualSyncObserver = CoreEvents.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data) => { if (data && (data.source != 'day' || data.year != this.year || data.month != this.month || data.day != this.day)) { this.loaded = false; this.refreshData(false, true); @@ -158,7 +157,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { // Update the events when an event is deleted. this.deleteEventObserver = CoreEvents.on( AddonCalendarProvider.DELETED_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (data && !data.sent) { // Event was deleted in offline. Just mark it as deleted, no need to refresh. this.hasOffline = this.markAsDeleted(data.eventId, true) || this.hasOffline; @@ -174,7 +173,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { // Listen for events "undeleted" (offline). this.undeleteEventObserver = CoreEvents.on( AddonCalendarProvider.UNDELETED_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (!data || !data.eventId) { return; } @@ -206,7 +205,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { this.filterChangedObserver = CoreEvents.on( AddonCalendarProvider.FILTER_CHANGED_EVENT, - async (data: AddonCalendarFilter) => { + async (data) => { this.filter = data; // Course viewed has changed, check if the user can create events for this course calendar. @@ -507,7 +506,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { result.month = this.month; result.year = this.year; - CoreEvents.trigger(AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId); + CoreEvents.trigger(AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId); } } catch (error) { if (showErrors) { diff --git a/src/addons/calendar/pages/edit-event/edit-event.page.ts b/src/addons/calendar/pages/edit-event/edit-event.page.ts index 38d9c3207..2fc986fcf 100644 --- a/src/addons/calendar/pages/edit-event/edit-event.page.ts +++ b/src/addons/calendar/pages/edit-event/edit-event.page.ts @@ -24,7 +24,7 @@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; import { CoreCategoryData, CoreCourses, CoreCourseSearchedData, CoreEnrolledCourseData } from '@features/courses/services/courses'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; -import { CoreEditorRichTextEditorComponent } from '@features/editor/components/rich-text-editor/rich-text-editor.ts'; +import { CoreEditorRichTextEditorComponent } from '@features/editor/components/rich-text-editor/rich-text-editor'; import { AddonCalendarProvider, AddonCalendarGetCalendarAccessInformationWSResponse, @@ -32,7 +32,6 @@ import { AddonCalendarEventType, AddonCalendar, AddonCalendarSubmitCreateUpdateFormDataWSParams, - AddonCalendarUpdatedEventEvent, } from '../../services/calendar'; import { AddonCalendarOffline } from '../../services/calendar-offline'; import { AddonCalendarEventTypeOption, AddonCalendarHelper } from '../../services/calendar-helper'; @@ -552,14 +551,14 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { if (this.eventId && this.eventId > 0) { // Editing an event. - CoreEvents.trigger( + CoreEvents.trigger( AddonCalendarProvider.EDIT_EVENT_EVENT, { eventId: this.eventId }, this.currentSite.getId(), ); } else { if (event) { - CoreEvents.trigger( + CoreEvents.trigger( AddonCalendarProvider.NEW_EVENT_EVENT, { eventId: event.id! }, this.currentSite.getId(), diff --git a/src/addons/calendar/pages/event/event.page.ts b/src/addons/calendar/pages/event/event.page.ts index e1501f7ca..3355c3c3f 100644 --- a/src/addons/calendar/pages/event/event.page.ts +++ b/src/addons/calendar/pages/event/event.page.ts @@ -22,7 +22,6 @@ import { AddonCalendarEventToDisplay, AddonCalendarGetEventsEvent, AddonCalendarProvider, - AddonCalendarUpdatedEventEvent, } from '../../services/calendar'; import { AddonCalendarHelper } from '../../services/calendar-helper'; import { AddonCalendarOffline } from '../../services/calendar-offline'; @@ -107,7 +106,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy { this.asyncConstructor(); // Listen for event edited. If current event is edited, reload the data. - this.editEventObserver = CoreEvents.on(AddonCalendarProvider.EDIT_EVENT_EVENT, (data: AddonCalendarUpdatedEventEvent) => { + this.editEventObserver = CoreEvents.on(AddonCalendarProvider.EDIT_EVENT_EVENT, (data) => { if (data && data.eventId == this.eventId) { this.eventLoaded = false; this.refreshEvent(true, false); @@ -205,7 +204,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy { // Trigger a manual sync event. result.source = 'event'; - CoreEvents.trigger( + CoreEvents.trigger( AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId, @@ -505,7 +504,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy { } // Trigger an event. - CoreEvents.trigger(AddonCalendarProvider.DELETED_EVENT_EVENT, { + CoreEvents.trigger(AddonCalendarProvider.DELETED_EVENT_EVENT, { eventId: this.eventId, sent: sent, }, CoreSites.getCurrentSiteId()); @@ -543,7 +542,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy { await AddonCalendarOffline.unmarkDeleted(this.event.id); // Trigger an event. - CoreEvents.trigger(AddonCalendarProvider.UNDELETED_EVENT_EVENT, { + CoreEvents.trigger(AddonCalendarProvider.UNDELETED_EVENT_EVENT, { eventId: this.eventId, }, CoreSites.getCurrentSiteId()); diff --git a/src/addons/calendar/pages/index/index.page.ts b/src/addons/calendar/pages/index/index.page.ts index c7095bbc9..b93e09a8b 100644 --- a/src/addons/calendar/pages/index/index.page.ts +++ b/src/addons/calendar/pages/index/index.page.ts @@ -19,9 +19,9 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreCoursesHelper } from '@features/courses/services/courses-helper'; -import { AddonCalendar, AddonCalendarProvider, AddonCalendarUpdatedEventEvent } from '../../services/calendar'; +import { AddonCalendar, AddonCalendarProvider } from '../../services/calendar'; import { AddonCalendarOffline } from '../../services/calendar-offline'; -import { AddonCalendarSync, AddonCalendarSyncEvents, AddonCalendarSyncProvider } from '../../services/calendar-sync'; +import { AddonCalendarSync, AddonCalendarSyncProvider } from '../../services/calendar-sync'; import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper'; import { Network, NgZone, PopoverController } from '@singletons'; import { Subscription } from 'rxjs'; @@ -88,7 +88,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { this.currentSiteId = CoreSites.getCurrentSiteId(); // Listen for events added. When an event is added, reload the data. - this.newEventObserver = CoreEvents.on( + this.newEventObserver = CoreEvents.on( AddonCalendarProvider.NEW_EVENT_EVENT, (data) => { if (data && data.eventId) { @@ -106,7 +106,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { }, this.currentSiteId); // Listen for events edited. When an event is edited, reload the data. - this.editEventObserver = CoreEvents.on( + this.editEventObserver = CoreEvents.on( AddonCalendarProvider.EDIT_EVENT_EVENT, (data) => { if (data && data.eventId) { @@ -124,7 +124,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { }, this.currentSiteId); // Refresh data if calendar events are synchronized manually but not by this page. - this.manualSyncObserver = CoreEvents.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data) => { + this.manualSyncObserver = CoreEvents.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data) => { if (data && data.source != 'index') { this.loaded = false; this.refreshData(false, false); @@ -142,7 +142,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { this.hasOffline = await AddonCalendarOffline.hasOfflineData(); }, this.currentSiteId); - this.filterChangedObserver = CoreEvents.on( + this.filterChangedObserver = CoreEvents.on( AddonCalendarProvider.FILTER_CHANGED_EVENT, async (filterData) => { this.filter = filterData; @@ -209,7 +209,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { // Trigger a manual sync event. result.source = 'index'; - CoreEvents.trigger( + CoreEvents.trigger( AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId, diff --git a/src/addons/calendar/pages/list/list.page.ts b/src/addons/calendar/pages/list/list.page.ts index a6f6ab0f9..79cf722a5 100644 --- a/src/addons/calendar/pages/list/list.page.ts +++ b/src/addons/calendar/pages/list/list.page.ts @@ -18,11 +18,10 @@ import { AddonCalendarProvider, AddonCalendar, AddonCalendarEventToDisplay, - AddonCalendarUpdatedEventEvent, } from '../../services/calendar'; import { AddonCalendarOffline } from '../../services/calendar-offline'; import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper'; -import { AddonCalendarSync, AddonCalendarSyncEvents, AddonCalendarSyncProvider } from '../../services/calendar-sync'; +import { AddonCalendarSync, AddonCalendarSyncProvider } from '../../services/calendar-sync'; import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreTimeUtils } from '@services/utils/time'; @@ -115,7 +114,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { } // Listen for events added. When an event is added, reload the data. - this.newEventObserver = CoreEvents.on(AddonCalendarProvider.NEW_EVENT_EVENT, (data) => { + this.newEventObserver = CoreEvents.on(AddonCalendarProvider.NEW_EVENT_EVENT, (data) => { if (data && data.eventId) { this.eventsLoaded = false; this.refreshEvents(true, false).finally(() => { @@ -143,7 +142,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { }, this.currentSiteId); // Listen for events edited. When an event is edited, reload the data. - this.editEventObserver = CoreEvents.on(AddonCalendarProvider.EDIT_EVENT_EVENT, (data: AddonCalendarUpdatedEventEvent) => { + this.editEventObserver = CoreEvents.on(AddonCalendarProvider.EDIT_EVENT_EVENT, (data) => { if (data && data.eventId) { this.eventsLoaded = false; this.refreshEvents(true, false); @@ -151,7 +150,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { }, this.currentSiteId); // Refresh data if calendar events are synchronized automatically. - this.syncObserver = CoreEvents.on(AddonCalendarSyncProvider.AUTO_SYNCED, (data) => { + this.syncObserver = CoreEvents.on(AddonCalendarSyncProvider.AUTO_SYNCED, (data) => { this.eventsLoaded = false; this.refreshEvents(); @@ -163,7 +162,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { }, this.currentSiteId); // Refresh data if calendar events are synchronized manually but not by this page. - this.manualSyncObserver = CoreEvents.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data: AddonCalendarSyncEvents) => { + this.manualSyncObserver = CoreEvents.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data) => { if (data && data.source != 'list') { this.eventsLoaded = false; this.refreshEvents(); @@ -179,7 +178,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { // Update the list when an event is deleted. this.deleteEventObserver = CoreEvents.on( AddonCalendarProvider.DELETED_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (data && !data.sent) { // Event was deleted in offline. Just mark it as deleted, no need to refresh. this.markAsDeleted(data.eventId, true); @@ -201,7 +200,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { // Listen for events "undeleted" (offline). this.undeleteEventObserver = CoreEvents.on( AddonCalendarProvider.UNDELETED_EVENT_EVENT, - (data: AddonCalendarUpdatedEventEvent) => { + (data) => { if (!data || !data.eventId) { return; } @@ -221,7 +220,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { ); this.filterChangedObserver = - CoreEvents.on(AddonCalendarProvider.FILTER_CHANGED_EVENT, async (data: AddonCalendarFilter) => { + CoreEvents.on(AddonCalendarProvider.FILTER_CHANGED_EVENT, async (data) => { this.filter = data; // Course viewed has changed, check if the user can create events for this course calendar. @@ -305,7 +304,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy { // Trigger a manual sync event. result.source = 'list'; - CoreEvents.trigger( + CoreEvents.trigger( AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId, diff --git a/src/addons/calendar/services/calendar-sync.ts b/src/addons/calendar/services/calendar-sync.ts index ed43cc834..c75e4834a 100644 --- a/src/addons/calendar/services/calendar-sync.ts +++ b/src/addons/calendar/services/calendar-sync.ts @@ -70,7 +70,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider(AddonCalendarSyncProvider.AUTO_SYNCED, result, siteId); + CoreEvents.trigger(AddonCalendarSyncProvider.AUTO_SYNCED, result, siteId); } } diff --git a/src/addons/calendar/services/calendar.ts b/src/addons/calendar/services/calendar.ts index e1f4cead8..e9d725c08 100644 --- a/src/addons/calendar/services/calendar.ts +++ b/src/addons/calendar/services/calendar.ts @@ -37,6 +37,8 @@ import { AddonCalendarOfflineEventDBRecord } from './database/calendar-offline'; import { AddonCalendarMainMenuHandlerService } from './handlers/mainmenu'; import { SafeUrl } from '@angular/platform-browser'; import { CoreNavigator } from '@services/navigator'; +import { AddonCalendarFilter } from './calendar-helper'; +import { AddonCalendarSyncEvents, AddonCalendarSyncProvider } from './calendar-sync'; const ROOT_CACHE_KEY = 'mmaCalendar:'; @@ -51,6 +53,25 @@ export enum AddonCalendarEventType { USER = 'user', } +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [AddonCalendarProvider.NEW_EVENT_EVENT]: AddonCalendarUpdatedEventEvent; + [AddonCalendarProvider.EDIT_EVENT_EVENT]: AddonCalendarUpdatedEventEvent; + [AddonCalendarProvider.DELETED_EVENT_EVENT]: AddonCalendarUpdatedEventEvent; + [AddonCalendarProvider.UNDELETED_EVENT_EVENT]: AddonCalendarUpdatedEventEvent; + [AddonCalendarProvider.FILTER_CHANGED_EVENT]: AddonCalendarFilter; + [AddonCalendarSyncProvider.MANUAL_SYNCED]: AddonCalendarSyncEvents; + [AddonCalendarSyncProvider.AUTO_SYNCED]: AddonCalendarSyncEvents; + } + +} + /** * Service to handle calendar events. */ diff --git a/src/addons/messages/pages/contacts-35/contacts.page.ts b/src/addons/messages/pages/contacts-35/contacts.page.ts index 51da338ad..bd0f98e2b 100644 --- a/src/addons/messages/pages/contacts-35/contacts.page.ts +++ b/src/addons/messages/pages/contacts-35/contacts.page.ts @@ -21,7 +21,6 @@ import { AddonMessagesSearchContactsContact, AddonMessagesGetContactsContact, AddonMessages, - AddonMessagesMemberInfoChangedEventData, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreApp } from '@services/app'; @@ -71,7 +70,7 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy { this.loadingMessage = this.loadingMessages; // Refresh the list when a contact request is confirmed. - this.memberInfoObserver = CoreEvents.on( + this.memberInfoObserver = CoreEvents.on( AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { if (data.contactRequestConfirmed) { diff --git a/src/addons/messages/pages/contacts/contacts.page.ts b/src/addons/messages/pages/contacts/contacts.page.ts index 5aee7da4e..9843c5f51 100644 --- a/src/addons/messages/pages/contacts/contacts.page.ts +++ b/src/addons/messages/pages/contacts/contacts.page.ts @@ -17,9 +17,7 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { AddonMessages, - AddonMessagesContactRequestCountEventData, AddonMessagesConversationMember, - AddonMessagesMemberInfoChangedEventData, AddonMessagesProvider, } from '../../services/messages'; import { CoreNavigator } from '@services/navigator'; @@ -63,7 +61,7 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy { this.siteId = CoreSites.getCurrentSiteId(); // Update the contact requests badge. - this.contactRequestsCountObserver = CoreEvents.on( + this.contactRequestsCountObserver = CoreEvents.on( AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT, (data) => { this.requestsBadge = data.count > 0 ? String(data.count) : ''; @@ -72,7 +70,7 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy { ); // Update block status of a user. - this.memberInfoObserver = CoreEvents.on( + this.memberInfoObserver = CoreEvents.on( AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { if (data.userBlocked || data.userUnblocked) { diff --git a/src/addons/messages/pages/discussion/discussion.page.ts b/src/addons/messages/pages/discussion/discussion.page.ts index 0cc44be66..a66e6af9a 100644 --- a/src/addons/messages/pages/discussion/discussion.page.ts +++ b/src/addons/messages/pages/discussion/discussion.page.ts @@ -23,16 +23,11 @@ import { AddonMessagesConversationMember, AddonMessagesGetMessagesMessage, AddonMessages, - AddonMessagesMemberInfoChangedEventData, - AddonMessagesReadChangedEventData, - AddonMessagesNewMessagedEventData, - AddonMessagesUpdateConversationListEventData, AddonMessagesConversationMessageFormatted, - AddonMessagesOpenConversationEventData, AddonMessagesSendMessageResults, } from '../../services/messages'; import { AddonMessagesOffline, AddonMessagesOfflineMessagesDBRecordFormatted } from '../../services/messages-offline'; -import { AddonMessagesSync, AddonMessagesSyncEvents, AddonMessagesSyncProvider } from '../../services/messages-sync'; +import { AddonMessagesSync, AddonMessagesSyncProvider } from '../../services/messages-sync'; import { CoreUser } from '@features/user/services/user'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; @@ -126,7 +121,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView this.logger = CoreLogger.getInstance('AddonMessagesDiscussionPage'); // Refresh data if this discussion is synchronized automatically. - this.syncObserver = CoreEvents.on(AddonMessagesSyncProvider.AUTO_SYNCED, (data) => { + this.syncObserver = CoreEvents.on(AddonMessagesSyncProvider.AUTO_SYNCED, (data) => { if ((data.userId && data.userId == this.userId) || (data.conversationId && data.conversationId == this.conversationId)) { // Fetch messages. @@ -140,7 +135,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView }, this.siteId); // Refresh data if info of a mamber of the conversation have changed. - this.memberInfoObserver = CoreEvents.on( + this.memberInfoObserver = CoreEvents.on( AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { if (data.userId && (this.members[data.userId] || this.otherMember && data.userId == this.otherMember.id)) { @@ -804,7 +799,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView } if (readChanged) { - CoreEvents.trigger(AddonMessagesProvider.READ_CHANGED_EVENT, { + CoreEvents.trigger(AddonMessagesProvider.READ_CHANGED_EVENT, { conversationId: this.conversationId, userId: this.userId, }, this.siteId); @@ -829,7 +824,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView if (trigger) { // Update discussions last message. - CoreEvents.trigger(AddonMessagesProvider.NEW_MESSAGE_EVENT, { + CoreEvents.trigger(AddonMessagesProvider.NEW_MESSAGE_EVENT, { conversationId: this.conversationId, userId: this.userId, message: this.lastMessage.text, @@ -1324,7 +1319,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView // Open user conversation. if (splitViewLoaded) { // Notify the left pane to load it, this way the right conversation will be highlighted. - CoreEvents.trigger( + CoreEvents.trigger( AddonMessagesProvider.OPEN_CONVERSATION_EVENT, { userId: result.data }, this.siteId, @@ -1360,7 +1355,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView // Get the conversation data so it's cached. Don't block the user for this. AddonMessages.getConversation(this.conversation.id, undefined, true); - CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, { + CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, { conversationId: this.conversation.id, action: 'favourite', value: this.conversation.isfavourite, @@ -1393,7 +1388,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView // Get the conversation data so it's cached. Don't block the user for this. AddonMessages.getConversation(this.conversation.id, undefined, true); - CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, { + CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, { conversationId: this.conversation.id, action: 'mute', value: this.conversation.ismuted, @@ -1501,7 +1496,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView try { await AddonMessages.deleteConversation(this.conversation.id); - CoreEvents.trigger( + CoreEvents.trigger( AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, { conversationId: this.conversation.id, diff --git a/src/addons/messages/pages/discussions-35/discussions.page.ts b/src/addons/messages/pages/discussions-35/discussions.page.ts index e1f7e9f5c..3f8e8370e 100644 --- a/src/addons/messages/pages/discussions-35/discussions.page.ts +++ b/src/addons/messages/pages/discussions-35/discussions.page.ts @@ -19,9 +19,7 @@ import { AddonMessages, AddonMessagesDiscussion, AddonMessagesMessageAreaContact, - AddonMessagesNewMessagedEventData, AddonMessagesProvider, - AddonMessagesReadChangedEventData, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; @@ -74,7 +72,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { this.siteId = CoreSites.getCurrentSiteId(); // Update discussions when new message is received. - this.newMessagesObserver = CoreEvents.on( + this.newMessagesObserver = CoreEvents.on( AddonMessagesProvider.NEW_MESSAGE_EVENT, (data) => { if (data.userId && this.discussions) { @@ -96,7 +94,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { ); // Update discussions when a message is read. - this.readChangedObserver = CoreEvents.on( + this.readChangedObserver = CoreEvents.on( AddonMessagesProvider.READ_CHANGED_EVENT, (data) => { if (data.userId && this.discussions) { diff --git a/src/addons/messages/pages/group-conversations/group-conversations.page.ts b/src/addons/messages/pages/group-conversations/group-conversations.page.ts index a198e06c6..27f6b30f8 100644 --- a/src/addons/messages/pages/group-conversations/group-conversations.page.ts +++ b/src/addons/messages/pages/group-conversations/group-conversations.page.ts @@ -20,13 +20,7 @@ import { AddonMessagesProvider, AddonMessagesConversationFormatted, AddonMessages, - AddonMessagesMemberInfoChangedEventData, - AddonMessagesContactRequestCountEventData, - AddonMessagesUnreadConversationCountsEventData, - AddonMessagesReadChangedEventData, - AddonMessagesUpdateConversationListEventData, AddonMessagesNewMessagedEventData, - AddonMessagesOpenConversationEventData, } from '../../services/messages'; import { AddonMessagesOffline, @@ -113,7 +107,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { this.currentUserId = CoreSites.getCurrentSiteUserId(); // Update conversations when new message is received. - this.newMessagesObserver = CoreEvents.on( + this.newMessagesObserver = CoreEvents.on( AddonMessagesProvider.NEW_MESSAGE_EVENT, (data) => { // Check if the new message belongs to the option that is currently expanded. @@ -157,9 +151,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { ); // Update conversations when a message is read. - this.readChangedObserver = CoreEvents.on(AddonMessagesProvider.READ_CHANGED_EVENT, ( - data, - ) => { + this.readChangedObserver = CoreEvents.on(AddonMessagesProvider.READ_CHANGED_EVENT, (data) => { if (data.conversationId) { const conversation = this.findConversation(data.conversationId); @@ -175,7 +167,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { }, this.siteId); // Load a discussion if we receive an event to do so. - this.openConversationObserver = CoreEvents.on( + this.openConversationObserver = CoreEvents.on( AddonMessagesProvider.OPEN_CONVERSATION_EVENT, (data) => { if (data.conversationId || data.userId) { @@ -197,7 +189,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { }); // Update conversations if we receive an event to do so. - this.updateConversationListObserver = CoreEvents.on( + this.updateConversationListObserver = CoreEvents.on( AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, (data) => { if (data && data.action == 'mute') { @@ -231,7 +223,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { }); // Update unread conversation counts. - this.cronObserver = CoreEvents.on( + this.cronObserver = CoreEvents.on( AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT, (data) => { this.favourites.unread = data.favourites; @@ -242,7 +234,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { ); // Update the contact requests badge. - this.contactRequestsCountObserver = CoreEvents.on( + this.contactRequestsCountObserver = CoreEvents.on( AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT, (data) => { this.contactRequestsCount = data.count; @@ -251,7 +243,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { ); // Update block status of a user. - this.memberInfoObserver = CoreEvents.on( + this.memberInfoObserver = CoreEvents.on( AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { if (!data.userBlocked && !data.userUnblocked) { diff --git a/src/addons/messages/pages/search/search.page.ts b/src/addons/messages/pages/search/search.page.ts index 7d98abb95..e7e2e33e2 100644 --- a/src/addons/messages/pages/search/search.page.ts +++ b/src/addons/messages/pages/search/search.page.ts @@ -19,7 +19,6 @@ import { AddonMessagesProvider, AddonMessagesConversationMember, AddonMessagesMessageAreaContact, - AddonMessagesMemberInfoChangedEventData, AddonMessages, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; @@ -72,7 +71,7 @@ export class AddonMessagesSearchPage implements OnDestroy { constructor() { // Update block status of a user. - this.memberInfoObserver = CoreEvents.on( + this.memberInfoObserver = CoreEvents.on( AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { if (!data.userBlocked && !data.userUnblocked) { diff --git a/src/addons/messages/services/handlers/mainmenu.ts b/src/addons/messages/services/handlers/mainmenu.ts index c8ef29716..4461ee4f9 100644 --- a/src/addons/messages/services/handlers/mainmenu.ts +++ b/src/addons/messages/services/handlers/mainmenu.ts @@ -16,8 +16,6 @@ import { Injectable } from '@angular/core'; import { AddonMessagesProvider, AddonMessages, - AddonMessagesUnreadConversationCountsEventData, - AddonMessagesContactRequestCountEventData, } from '../messages'; import { CoreMainMenuHandler, CoreMainMenuHandlerToDisplay } from '@features/mainmenu/services/mainmenu-delegate'; import { CoreCronHandler } from '@services/cron'; @@ -58,16 +56,13 @@ export class AddonMessagesMainMenuHandlerService implements CoreMainMenuHandler, constructor() { - CoreEvents.on( - AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT, - (data) => { - this.unreadCount = data.favourites + data.individual + data.group + data.self; - this.orMore = !!data.orMore; - this.updateBadge(data.siteId!); - }, - ); + CoreEvents.on(AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT, (data) => { + this.unreadCount = data.favourites + data.individual + data.group + data.self; + this.orMore = !!data.orMore; + this.updateBadge(data.siteId!); + }); - CoreEvents.on(AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT, (data) => { + CoreEvents.on(AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT, (data) => { this.contactRequestsCount = data.count; this.updateBadge(data.siteId!); }); diff --git a/src/addons/messages/services/messages-sync.ts b/src/addons/messages/services/messages-sync.ts index 94b5d2d9c..9a5edf592 100644 --- a/src/addons/messages/services/messages-sync.ts +++ b/src/addons/messages/services/messages-sync.ts @@ -112,7 +112,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider(AddonMessagesSyncProvider.AUTO_SYNCED, result, siteId); + CoreEvents.trigger(AddonMessagesSyncProvider.AUTO_SYNCED, result, siteId); return; })); @@ -125,7 +125,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider(AddonMessagesSyncProvider.AUTO_SYNCED, result, siteId); + CoreEvents.trigger(AddonMessagesSyncProvider.AUTO_SYNCED, result, siteId); return; })); diff --git a/src/addons/messages/services/messages.ts b/src/addons/messages/services/messages.ts index ab326200b..e987af5e7 100644 --- a/src/addons/messages/services/messages.ts +++ b/src/addons/messages/services/messages.ts @@ -31,9 +31,30 @@ import { CoreWSExternalWarning } from '@services/ws'; import { makeSingleton } from '@singletons'; import { CoreError } from '@classes/errors/error'; import { AddonMessagesMainMenuHandlerService } from './handlers/mainmenu'; +import { AddonMessagesSyncEvents, AddonMessagesSyncProvider } from './messages-sync'; const ROOT_CACHE_KEY = 'mmaMessages:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [AddonMessagesProvider.NEW_MESSAGE_EVENT]: AddonMessagesNewMessagedEventData; + [AddonMessagesProvider.READ_CHANGED_EVENT]: AddonMessagesReadChangedEventData; + [AddonMessagesProvider.OPEN_CONVERSATION_EVENT]: AddonMessagesOpenConversationEventData; + [AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT]: AddonMessagesUpdateConversationListEventData; + [AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT]: AddonMessagesMemberInfoChangedEventData; + [AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT]: AddonMessagesUnreadConversationCountsEventData; + [AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT]: AddonMessagesContactRequestCountEventData; + [AddonMessagesSyncProvider.AUTO_SYNCED]: AddonMessagesSyncEvents; + } + +} + /** * Service to handle messages. */ diff --git a/src/addons/mod/assign/components/index/index.ts b/src/addons/mod/assign/components/index/index.ts index 6b1849cd8..ab7786eb0 100644 --- a/src/addons/mod/assign/components/index/index.ts +++ b/src/addons/mod/assign/components/index/index.ts @@ -31,11 +31,8 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { AddonModAssign, AddonModAssignAssign, - AddonModAssignGradedEventData, AddonModAssignProvider, AddonModAssignSubmissionGradingSummary, - AddonModAssignSubmissionSavedEventData, - AddonModAssignSubmittedForGradingEventData, } from '../../services/assign'; import { AddonModAssignOffline } from '../../services/assign-offline'; import { @@ -107,7 +104,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo this.currentSite = CoreSites.getCurrentSite(); // Listen to events. - this.savedObserver = CoreEvents.on( + this.savedObserver = CoreEvents.on( AddonModAssignProvider.SUBMISSION_SAVED_EVENT, (data) => { if (this.assign && data.assignmentId == this.assign.id && data.userId == this.currentUserId) { @@ -118,7 +115,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo this.siteId, ); - this.submittedObserver = CoreEvents.on( + this.submittedObserver = CoreEvents.on( AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, (data) => { if (this.assign && data.assignmentId == this.assign.id && data.userId == this.currentUserId) { @@ -132,7 +129,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo this.siteId, ); - this.gradedObserver = CoreEvents.on(AddonModAssignProvider.GRADED_EVENT, (data) => { + this.gradedObserver = CoreEvents.on(AddonModAssignProvider.GRADED_EVENT, (data) => { if (this.assign && data.assignmentId == this.assign.id && data.userId == this.currentUserId) { // Assignment graded, refresh data. this.showLoadingAndRefresh(true, false); diff --git a/src/addons/mod/assign/components/submission/submission.ts b/src/addons/mod/assign/components/submission/submission.ts index a70ec103d..827ba257c 100644 --- a/src/addons/mod/assign/components/submission/submission.ts +++ b/src/addons/mod/assign/components/submission/submission.ts @@ -24,9 +24,7 @@ import { AddonModAssignPlugin, AddonModAssign, AddonModAssignGetSubmissionStatusWSResponse, - AddonModAssignSubmittedForGradingEventData, AddonModAssignSavePluginData, - AddonModAssignGradedEventData, } from '../../services/assign'; import { AddonModAssignAutoSyncData, @@ -312,7 +310,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can if (!this.assign!.submissiondrafts) { // No drafts allowed, so it was submitted. Trigger event. - CoreEvents.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, { + CoreEvents.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, { assignmentId: this.assign!.id, submissionId: this.userSubmission!.id, userId: this.currentUserId, @@ -482,7 +480,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can const result = await AddonModAssignSync.syncAssign(this.assign.id); if (result && result.updated) { - CoreEvents.trigger(AddonModAssignSyncProvider.MANUAL_SYNCED, { + CoreEvents.trigger(AddonModAssignSyncProvider.MANUAL_SYNCED, { assignId: this.assign.id, warnings: result.warnings, gradesBlocked: result.gradesBlocked, @@ -840,7 +838,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can ); // Submitted, trigger event. - CoreEvents.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, { + CoreEvents.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, { assignmentId: this.assign!.id, submissionId: this.userSubmission!.id, userId: this.currentUserId, @@ -915,7 +913,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can // Invalidate and refresh data. this.invalidateAndRefresh(true); - CoreEvents.trigger(AddonModAssignProvider.GRADED_EVENT, { + CoreEvents.trigger(AddonModAssignProvider.GRADED_EVENT, { assignmentId: this.assign!.id, submissionId: this.submitId, userId: this.currentUserId, diff --git a/src/addons/mod/assign/pages/edit/edit.ts b/src/addons/mod/assign/pages/edit/edit.ts index 31f2d9a7b..a85013e36 100644 --- a/src/addons/mod/assign/pages/edit/edit.ts +++ b/src/addons/mod/assign/pages/edit/edit.ts @@ -22,7 +22,7 @@ import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSync } from '@services/sync'; import { CoreDomUtils } from '@services/utils/dom'; import { Translate } from '@singletons'; -import { CoreEventActivityDataSentData, CoreEvents } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModAssignAssign, AddonModAssignSubmission, @@ -31,8 +31,6 @@ import { AddonModAssignSubmissionStatusOptions, AddonModAssignGetSubmissionStatusWSResponse, AddonModAssignSavePluginData, - AddonModAssignSubmissionSavedEventData, - AddonModAssignSubmittedForGradingEventData, } from '../../services/assign'; import { AddonModAssignHelper } from '../../services/assign-helper'; import { AddonModAssignOffline } from '../../services/assign-offline'; @@ -351,13 +349,13 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave { AddonModAssignHelper.clearSubmissionPluginTmpData(this.assign!, this.userSubmission, inputData); if (sent) { - CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'assign' }); + CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'assign' }); } // Submission saved, trigger events. CoreDomUtils.triggerFormSubmittedEvent(this.formElement, sent, CoreSites.getCurrentSiteId()); - CoreEvents.trigger( + CoreEvents.trigger( AddonModAssignProvider.SUBMISSION_SAVED_EVENT, { assignmentId: this.assign!.id, @@ -369,7 +367,7 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave { if (!this.assign!.submissiondrafts) { // No drafts allowed, so it was submitted. Trigger event. - CoreEvents.trigger( + CoreEvents.trigger( AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, { assignmentId: this.assign!.id, diff --git a/src/addons/mod/assign/pages/submission-list/submission-list.page.ts b/src/addons/mod/assign/pages/submission-list/submission-list.page.ts index db08d6509..fe21ced82 100644 --- a/src/addons/mod/assign/pages/submission-list/submission-list.page.ts +++ b/src/addons/mod/assign/pages/submission-list/submission-list.page.ts @@ -29,7 +29,6 @@ import { AddonModAssignSubmission, AddonModAssignProvider, AddonModAssign, - AddonModAssignGradedEventData, } from '../../services/assign'; import { AddonModAssignHelper, AddonModAssignSubmissionFormatted } from '../../services/assign-helper'; import { AddonModAssignOffline } from '../../services/assign-offline'; @@ -80,7 +79,7 @@ export class AddonModAssignSubmissionListPage implements AfterViewInit, OnDestro this.submissions = new AddonModAssignSubmissionListManager(AddonModAssignSubmissionListPage); // Update data if some grade changes. - this.gradedObserver = CoreEvents.on( + this.gradedObserver = CoreEvents.on( AddonModAssignProvider.GRADED_EVENT, (data) => { if ( @@ -162,7 +161,7 @@ export class AddonModAssignSubmissionListPage implements AfterViewInit, OnDestro const result = await AddonModAssignSync.syncAssign(this.assign.id); if (result && result.updated) { - CoreEvents.trigger( + CoreEvents.trigger( AddonModAssignSyncProvider.MANUAL_SYNCED, { assignId: this.assign.id, diff --git a/src/addons/mod/assign/services/assign-sync.ts b/src/addons/mod/assign/services/assign-sync.ts index df803848c..b09b7b388 100644 --- a/src/addons/mod/assign/services/assign-sync.ts +++ b/src/addons/mod/assign/services/assign-sync.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSyncBlockedError } from '@classes/base-sync'; import { @@ -131,7 +131,7 @@ export class AddonModAssignSyncProvider extends CoreCourseActivitySyncBaseProvid : await this.syncAssignIfNeeded(assignId, siteId); if (result?.updated) { - CoreEvents.trigger(AddonModAssignSyncProvider.AUTO_SYNCED, { + CoreEvents.trigger(AddonModAssignSyncProvider.AUTO_SYNCED, { assignId: assignId, warnings: result.warnings, gradesBlocked: result.gradesBlocked, @@ -555,7 +555,7 @@ export type AddonModAssignSyncResult = { /** * Data passed to AUTO_SYNCED event. */ -export type AddonModAssignAutoSyncData = CoreEventSiteData & { +export type AddonModAssignAutoSyncData = { assignId: number; warnings: string[]; gradesBlocked: number[]; // Whether some grade couldn't be synced because it was blocked. UserId fields of the blocked grade. diff --git a/src/addons/mod/assign/services/assign.ts b/src/addons/mod/assign/services/assign.ts index b9e800d3e..f575c07ee 100644 --- a/src/addons/mod/assign/services/assign.ts +++ b/src/addons/mod/assign/services/assign.ts @@ -32,9 +32,27 @@ import { AddonModAssignSubmissionDelegate } from './submission-delegate'; import { CoreComments } from '@features/comments/services/comments'; import { AddonModAssignSubmissionFormatted } from './assign-helper'; import { CoreWSError } from '@classes/errors/wserror'; +import { AddonModAssignAutoSyncData, AddonModAssignManualSyncData, AddonModAssignSyncProvider } from './assign-sync'; const ROOT_CACHE_KEY = 'mmaModAssign:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [AddonModAssignProvider.SUBMISSION_SAVED_EVENT]: AddonModAssignSubmissionSavedEventData; + [AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT]: AddonModAssignSubmittedForGradingEventData; + [AddonModAssignProvider.GRADED_EVENT]: AddonModAssignGradedEventData; + [AddonModAssignSyncProvider.MANUAL_SYNCED]: AddonModAssignManualSyncData; + [AddonModAssignSyncProvider.AUTO_SYNCED]: AddonModAssignAutoSyncData; + } + +} + /** * Service that provides some functions for assign. */ diff --git a/src/addons/mod/forum/services/sync.ts b/src/addons/mod/forum/services/sync.ts index 17d26ce26..d655b8074 100644 --- a/src/addons/mod/forum/services/sync.ts +++ b/src/addons/mod/forum/services/sync.ts @@ -27,7 +27,7 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton, Translate } from '@singletons'; import { CoreArray } from '@singletons/array'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModForum, AddonModForumAddDiscussionPostWSOptionsObject, @@ -669,7 +669,7 @@ export type AddonModForumSyncResult = { /** * Data passed to AUTO_SYNCED event. */ -export type AddonModForumAutoSyncData = CoreEventSiteData & { +export type AddonModForumAutoSyncData = { forumId: number; userId: number; warnings: string[]; @@ -679,7 +679,7 @@ export type AddonModForumAutoSyncData = CoreEventSiteData & { /** * Data passed to MANUAL_SYNCED event. */ -export type AddonModForumManualSyncData = CoreEventSiteData & { +export type AddonModForumManualSyncData = { forumId: number; userId: number; source: string; diff --git a/src/addons/mod/lesson/components/index/index.ts b/src/addons/mod/lesson/components/index/index.ts index e616492f8..41074093a 100644 --- a/src/addons/mod/lesson/components/index/index.ts +++ b/src/addons/mod/lesson/components/index/index.ts @@ -34,7 +34,6 @@ import { AddonModLesson, AddonModLessonAttemptsOverviewsStudentWSData, AddonModLessonAttemptsOverviewWSData, - AddonModLessonDataSentData, AddonModLessonGetAccessInformationWSResponse, AddonModLessonLessonWSData, AddonModLessonPreventAccessReason, @@ -435,7 +434,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo this.hasPlayed = true; this.dataSentObserver?.off(); - this.dataSentObserver = CoreEvents.on(AddonModLessonProvider.DATA_SENT_EVENT, (data) => { + this.dataSentObserver = CoreEvents.on(AddonModLessonProvider.DATA_SENT_EVENT, (data) => { // Ignore launch sending because it only affects timers. if (data.lessonId === this.lesson?.id && data.type != 'launch') { this.dataSent = true; diff --git a/src/addons/mod/lesson/pages/player/player.page.ts b/src/addons/mod/lesson/pages/player/player.page.ts index 470bd1c0c..e6d39e5d8 100644 --- a/src/addons/mod/lesson/pages/player/player.page.ts +++ b/src/addons/mod/lesson/pages/player/player.page.ts @@ -27,7 +27,7 @@ import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; import { CoreWSExternalFile } from '@services/ws'; import { ModalController, Translate } from '@singletons'; -import { CoreEventActivityDataSentData, CoreEvents } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModLessonMenuModalPage } from '../../components/menu-modal/menu-modal'; import { AddonModLesson, @@ -412,7 +412,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { this.messages = this.messages.concat(data.messages); this.processData = undefined; - CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'lesson' }); + CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'lesson' }); // Format activity link if present. if (this.eolData.activitylink) { diff --git a/src/addons/mod/lesson/services/lesson-sync.ts b/src/addons/mod/lesson/services/lesson-sync.ts index 298dfd9d2..c9f673191 100644 --- a/src/addons/mod/lesson/services/lesson-sync.ts +++ b/src/addons/mod/lesson/services/lesson-sync.ts @@ -27,7 +27,7 @@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton, Translate } from '@singletons'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModLessonRetakeFinishedInSyncDBRecord, RETAKES_FINISHED_SYNC_TABLE_NAME } from './database/lesson'; import { AddonModLessonGetPasswordResult, AddonModLessonPrefetchHandler } from './handlers/prefetch'; import { AddonModLesson, AddonModLessonLessonWSData, AddonModLessonProvider } from './lesson'; @@ -145,7 +145,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid if (result?.updated) { // Sync successful, send event. - CoreEvents.trigger(AddonModLessonSyncProvider.AUTO_SYNCED, { + CoreEvents.trigger(AddonModLessonSyncProvider.AUTO_SYNCED, { lessonId: lesson.id, warnings: result.warnings, }, siteId); @@ -512,7 +512,7 @@ export type AddonModLessonSyncResult = { /** * Data passed to AUTO_SYNCED event. */ -export type AddonModLessonAutoSyncData = CoreEventSiteData & { +export type AddonModLessonAutoSyncData = { lessonId: number; warnings: string[]; }; diff --git a/src/addons/mod/lesson/services/lesson.ts b/src/addons/mod/lesson/services/lesson.ts index 255482aea..5bff0aceb 100644 --- a/src/addons/mod/lesson/services/lesson.ts +++ b/src/addons/mod/lesson/services/lesson.ts @@ -24,12 +24,27 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModLessonPasswordDBRecord, PASSWORD_TABLE_NAME } from './database/lesson'; import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline'; +import { AddonModLessonAutoSyncData, AddonModLessonSyncProvider } from './lesson-sync'; const ROOT_CACHE_KEY = 'mmaModLesson:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [AddonModLessonProvider.DATA_SENT_EVENT]: AddonModLessonDataSentData; + [AddonModLessonSyncProvider.AUTO_SYNCED]: AddonModLessonAutoSyncData; + } + +} + /** * Service that provides some features for lesson. * @@ -944,7 +959,7 @@ export class AddonModLessonProvider { const response = await this.finishRetakeOnline(lesson.id, options); - CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { + CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { lessonId: lesson.id, type: 'finish', courseId: courseId, @@ -2750,7 +2765,7 @@ export class AddonModLessonProvider { const response = await site.write('mod_lesson_launch_attempt', params); - CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { + CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { lessonId: id, type: 'launch', }, CoreSites.getCurrentSiteId()); @@ -3002,7 +3017,7 @@ export class AddonModLessonProvider { if (!options.offline) { const response = await this.processPageOnline(lesson.id, pageId, data, options); - CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { + CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { lessonId: lesson.id, type: 'process', courseId: courseId, @@ -4226,7 +4241,7 @@ export type AddonModLessonContentPageOrRecord = AddonModLessonWSContentPageViewe /** * Data passed to DATA_SENT_EVENT event. */ -export type AddonModLessonDataSentData = CoreEventSiteData & { +export type AddonModLessonDataSentData = { lessonId: number; type: string; courseId?: number; diff --git a/src/addons/mod/quiz/components/index/index.ts b/src/addons/mod/quiz/components/index/index.ts index f81710cc9..46b9c15e7 100644 --- a/src/addons/mod/quiz/components/index/index.ts +++ b/src/addons/mod/quiz/components/index/index.ts @@ -109,7 +109,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp super.ngOnInit(); // Listen for attempt finished events. - this.finishedObserver = CoreEvents.on( + this.finishedObserver = CoreEvents.on( AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, (data) => { // Go to review attempt if an attempt in this quiz was finished and synced. diff --git a/src/addons/mod/quiz/pages/player/player.page.ts b/src/addons/mod/quiz/pages/player/player.page.ts index 1e88da13a..d956922f9 100644 --- a/src/addons/mod/quiz/pages/player/player.page.ts +++ b/src/addons/mod/quiz/pages/player/player.page.ts @@ -27,7 +27,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; import { ModalController, Translate } from '@singletons'; -import { CoreEventActivityDataSentData, CoreEvents } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModQuizAutoSave } from '../../classes/auto-save'; import { AddonModQuizNavigationModalComponent, @@ -35,7 +35,6 @@ import { } from '../../components/navigation-modal/navigation-modal'; import { AddonModQuiz, - AddonModQuizAttemptFinishedData, AddonModQuizAttemptWSData, AddonModQuizGetAttemptAccessInformationWSResponse, AddonModQuizGetQuizAccessInformationWSResponse, @@ -400,13 +399,13 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave { await this.processAttempt(userFinish, timeUp); // Trigger an event to notify the attempt was finished. - CoreEvents.trigger(AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, { + CoreEvents.trigger(AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, { quizId: this.quiz!.id, attemptId: this.attempt!.id, synced: !this.offline, }, CoreSites.getCurrentSiteId()); - CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'quiz' }); + CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: 'quiz' }); // Leave the player. this.forceLeave = true; diff --git a/src/addons/mod/quiz/services/quiz-sync.ts b/src/addons/mod/quiz/services/quiz-sync.ts index b3424d191..35e7c0de1 100644 --- a/src/addons/mod/quiz/services/quiz-sync.ts +++ b/src/addons/mod/quiz/services/quiz-sync.ts @@ -26,7 +26,7 @@ import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSync } from '@services/sync'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton, Translate } from '@singletons'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonModQuizAttemptDBRecord } from './database/quiz'; import { AddonModQuizPrefetchHandler } from './handlers/prefetch'; import { AddonModQuiz, AddonModQuizAttemptWSData, AddonModQuizProvider, AddonModQuizQuizWSData } from './quiz'; @@ -222,7 +222,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider if (data) { // Sync successful. Send event. - CoreEvents.trigger(AddonModQuizSyncProvider.AUTO_SYNCED, { + CoreEvents.trigger(AddonModQuizSyncProvider.AUTO_SYNCED, { quizId: quiz.id, attemptFinished: data.attemptFinished, warnings: data.warnings, @@ -506,7 +506,7 @@ type FinishSyncOptions = { /** * Data passed to AUTO_SYNCED event. */ -export type AddonModQuizAutoSyncData = CoreEventSiteData & { +export type AddonModQuizAutoSyncData = { quizId: number; attemptFinished: boolean; warnings: string[]; diff --git a/src/addons/mod/quiz/services/quiz.ts b/src/addons/mod/quiz/services/quiz.ts index 33e3cbd89..c732bc937 100644 --- a/src/addons/mod/quiz/services/quiz.ts +++ b/src/addons/mod/quiz/services/quiz.ts @@ -36,14 +36,28 @@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; -import { CoreEventSiteData } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; import { AddonModQuizAccessRuleDelegate } from './access-rules-delegate'; import { AddonModQuizAttempt } from './quiz-helper'; import { AddonModQuizOffline, AddonModQuizQuestionsWithAnswers } from './quiz-offline'; +import { AddonModQuizAutoSyncData, AddonModQuizSyncProvider } from './quiz-sync'; const ROOT_CACHE_KEY = 'mmaModQuiz:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [AddonModQuizProvider.ATTEMPT_FINISHED_EVENT]: AddonModQuizAttemptFinishedData; + [AddonModQuizSyncProvider.AUTO_SYNCED]: AddonModQuizAutoSyncData; + } + +} + /** * Service that provides some features for quiz. */ @@ -2385,7 +2399,7 @@ export type AddonModQuizViewQuizWSParams = { /** * Data passed to ATTEMPT_FINISHED_EVENT event. */ -export type AddonModQuizAttemptFinishedData = CoreEventSiteData & { +export type AddonModQuizAttemptFinishedData = { quizId: number; attemptId: number; synced: boolean; diff --git a/src/addons/notifications/pages/settings/settings.ts b/src/addons/notifications/pages/settings/settings.ts index 6b430204d..5524486a4 100644 --- a/src/addons/notifications/pages/settings/settings.ts +++ b/src/addons/notifications/pages/settings/settings.ts @@ -24,7 +24,7 @@ import { CoreUser } from '@features/user/services/user'; import { AddonMessageOutputDelegate, AddonMessageOutputHandlerData } from '@addons/messageoutput/services/messageoutput-delegate'; import { CoreConstants } from '@/core/constants'; import { CoreError } from '@classes/errors/error'; -import { CoreEventNotificationSoundChangedData, CoreEvents } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { AddonNotifications, AddonNotificationsPreferencesProcessor, @@ -277,7 +277,7 @@ export class AddonNotificationsSettingsPage implements OnInit, OnDestroy { await CoreUtils.ignoreErrors(CoreConfig.set(CoreConstants.SETTINGS_NOTIFICATION_SOUND, enabled ? 1 : 0)); const siteId = CoreSites.getCurrentSiteId(); - CoreEvents.trigger(CoreEvents.NOTIFICATION_SOUND_CHANGED, { enabled }, siteId); + CoreEvents.trigger(CoreEvents.NOTIFICATION_SOUND_CHANGED, { enabled }, siteId); CoreLocalNotifications.rescheduleAll(); } diff --git a/src/addons/notifications/services/handlers/mainmenu.ts b/src/addons/notifications/services/handlers/mainmenu.ts index c7312e305..dbf5aeb1e 100644 --- a/src/addons/notifications/services/handlers/mainmenu.ts +++ b/src/addons/notifications/services/handlers/mainmenu.ts @@ -17,12 +17,11 @@ import { Injectable } from '@angular/core'; import { CoreSites } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton } from '@singletons'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '@features/mainmenu/services/mainmenu-delegate'; import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { AddonNotifications, AddonNotificationsProvider } from '../notifications'; -import { AddonMessagesReadChangedEventData } from '@addons/messages/services/messages'; /** * Handler to inject an option into main menu. @@ -49,11 +48,11 @@ export class AddonNotificationsMainMenuHandlerService implements CoreMainMenuHan * Initialize the handler. */ initialize(): void { - CoreEvents.on(AddonNotificationsProvider.READ_CHANGED_EVENT, (data) => { + CoreEvents.on(AddonNotificationsProvider.READ_CHANGED_EVENT, (data) => { this.updateBadge(data.siteId); }); - CoreEvents.on(AddonNotificationsProvider.READ_CRON_EVENT, (data: CoreEventSiteData) => { + CoreEvents.on(AddonNotificationsProvider.READ_CRON_EVENT, (data) => { this.updateBadge(data.siteId); }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 105795baa..c88c155cc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -17,13 +17,7 @@ import { IonRouterOutlet } from '@ionic/angular'; import { CoreLang } from '@services/lang'; import { CoreLoginHelper } from '@features/login/services/login-helper'; -import { - CoreEvents, - CoreEventSessionExpiredData, - CoreEventSiteAddedData, - CoreEventSiteData, - CoreEventSiteUpdatedData, -} from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { Network, NgZone, Platform, SplashScreen } from '@singletons'; import { CoreApp } from '@services/app'; import { CoreSites } from '@services/sites'; @@ -79,20 +73,20 @@ export class AppComponent implements OnInit, AfterViewInit { }); // Listen for session expired events. - CoreEvents.on(CoreEvents.SESSION_EXPIRED, (data: CoreEventSessionExpiredData) => { + CoreEvents.on(CoreEvents.SESSION_EXPIRED, (data) => { CoreLoginHelper.sessionExpired(data); }); // Listen for passwordchange and usernotfullysetup events to open InAppBrowser. - CoreEvents.on(CoreEvents.PASSWORD_CHANGE_FORCED, (data: CoreEventSiteData) => { + CoreEvents.on(CoreEvents.PASSWORD_CHANGE_FORCED, (data) => { CoreLoginHelper.passwordChangeForced(data.siteId!); }); - CoreEvents.on(CoreEvents.USER_NOT_FULLY_SETUP, (data: CoreEventSiteData) => { + CoreEvents.on(CoreEvents.USER_NOT_FULLY_SETUP, (data) => { CoreLoginHelper.openInAppForEdit(data.siteId!, '/user/edit.php', 'core.usernotfullysetup'); }); // Listen for sitepolicynotagreed event to accept the site policy. - CoreEvents.on(CoreEvents.SITE_POLICY_NOT_AGREED, (data: CoreEventSiteData) => { + CoreEvents.on(CoreEvents.SITE_POLICY_NOT_AGREED, (data) => { CoreLoginHelper.sitePolicyNotAgreed(data.siteId); }); @@ -173,7 +167,7 @@ export class AppComponent implements OnInit, AfterViewInit { CoreWindow.open(url, name); }; - CoreEvents.on(CoreEvents.LOGIN, async (data: CoreEventSiteData) => { + CoreEvents.on(CoreEvents.LOGIN, async (data) => { if (data.siteId) { const site = await CoreSites.getSite(data.siteId); const info = site.getInfo(); @@ -187,7 +181,7 @@ export class AppComponent implements OnInit, AfterViewInit { this.loadCustomStrings(); }); - CoreEvents.on(CoreEvents.SITE_UPDATED, (data: CoreEventSiteUpdatedData) => { + CoreEvents.on(CoreEvents.SITE_UPDATED, (data) => { if (data.siteId == CoreSites.getCurrentSiteId()) { this.loadCustomStrings(); @@ -197,7 +191,7 @@ export class AppComponent implements OnInit, AfterViewInit { } }); - CoreEvents.on(CoreEvents.SITE_ADDED, (data: CoreEventSiteAddedData) => { + CoreEvents.on(CoreEvents.SITE_ADDED, (data) => { if (data.siteId == CoreSites.getCurrentSiteId()) { this.loadCustomStrings(); diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts index 0fe269dd8..82d64c17f 100644 --- a/src/core/classes/site.ts +++ b/src/core/classes/site.ts @@ -17,7 +17,7 @@ import { Md5 } from 'ts-md5/dist/md5'; import { CoreApp } from '@services/app'; import { CoreDB } from '@services/db'; -import { CoreEvents, CoreEventUserDeletedData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { CoreFile } from '@services/file'; import { CoreWS, @@ -593,7 +593,7 @@ export class CoreSite { error.message = Translate.instant('core.lostconnection'); } else if (error.errorcode === 'userdeleted') { // User deleted, trigger event. - CoreEvents.trigger(CoreEvents.USER_DELETED, { params: data }, this.id); + CoreEvents.trigger(CoreEvents.USER_DELETED, { params: data }, this.id); error.message = Translate.instant('core.userdeleted'); throw new CoreWSError(error); diff --git a/src/core/components/send-message-form/send-message-form.ts b/src/core/components/send-message-form/send-message-form.ts index 09a4db8b0..728643f46 100644 --- a/src/core/components/send-message-form/send-message-form.ts +++ b/src/core/components/send-message-form/send-message-form.ts @@ -63,8 +63,8 @@ export class CoreSendMessageFormComponent implements OnInit { // Nothing to do. }); - CoreEvents.on(CoreEvents.SEND_ON_ENTER_CHANGED, (newValue) => { - this.sendOnEnter = newValue; + CoreEvents.on(CoreEvents.SEND_ON_ENTER_CHANGED, (data) => { + this.sendOnEnter = data.sendOnEnter; }, CoreSites.getCurrentSiteId()); } diff --git a/src/core/components/user-avatar/user-avatar.ts b/src/core/components/user-avatar/user-avatar.ts index b53ef95fe..dd3884996 100644 --- a/src/core/components/user-avatar/user-avatar.ts +++ b/src/core/components/user-avatar/user-avatar.ts @@ -18,7 +18,7 @@ import { CoreApp } from '@services/app'; import { CoreSites } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreUserProvider, CoreUserBasicData, CoreUserProfilePictureUpdatedData } from '@features/user/services/user'; +import { CoreUserProvider, CoreUserBasicData } from '@features/user/services/user'; import { CoreNavigator } from '@services/navigator'; /** @@ -54,7 +54,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy { constructor() { this.currentUserId = CoreSites.getCurrentSiteUserId(); - this.pictureObserver = CoreEvents.on( + this.pictureObserver = CoreEvents.on( CoreUserProvider.PROFILE_PICTURE_UPDATED, (data) => { if (data.userId == this.userId) { diff --git a/src/core/features/comments/components/comments/comments.ts b/src/core/features/comments/components/comments/comments.ts index 8d591ad31..15a06523f 100644 --- a/src/core/features/comments/components/comments/comments.ts +++ b/src/core/features/comments/components/comments/comments.ts @@ -15,9 +15,7 @@ import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChange, OnInit } from '@angular/core'; import { CoreComments, - CoreCommentsCountChangedEventData, CoreCommentsProvider, - CoreCommentsRefreshCommentsEventData, } from '../../services/comments'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; @@ -72,10 +70,10 @@ export class CoreCommentsCommentsComponent implements OnInit, OnChanges, OnDestr }, CoreSites.getCurrentSiteId()); // Refresh comments if event received. - this.refreshCommentsObserver = CoreEvents.on( + this.refreshCommentsObserver = CoreEvents.on( CoreCommentsProvider.REFRESH_COMMENTS_EVENT, (data) => { - // Verify these comments need to be updated. + // Verify these comments need to be updated. if (this.undefinedOrEqual(data, 'contextLevel') && this.undefinedOrEqual(data, 'instanceId') && this.undefinedOrEqual(data, 'component') && this.undefinedOrEqual(data, 'itemId') && this.undefinedOrEqual(data, 'area')) { @@ -87,7 +85,7 @@ export class CoreCommentsCommentsComponent implements OnInit, OnChanges, OnDestr ); // Refresh comments count if event received. - this.commentsCountObserver = CoreEvents.on( + this.commentsCountObserver = CoreEvents.on( CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, (data) => { // Verify these comments need to be updated. diff --git a/src/core/features/comments/pages/viewer/viewer.page.ts b/src/core/features/comments/pages/viewer/viewer.page.ts index 5a4a2ae24..4c8bf2b2b 100644 --- a/src/core/features/comments/pages/viewer/viewer.page.ts +++ b/src/core/features/comments/pages/viewer/viewer.page.ts @@ -20,13 +20,11 @@ import { CoreSites } from '@services/sites'; import { CoreComments, CoreCommentsCommentBasicData, - CoreCommentsCountChangedEventData, CoreCommentsData, CoreCommentsProvider, } from '@features/comments/services/comments'; import { CoreCommentsSync, - CoreCommentsSyncAutoSyncData, CoreCommentsSyncProvider, } from '@features/comments/services/comments-sync'; import { IonContent, IonRefresher } from '@ionic/angular'; @@ -86,7 +84,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { this.currentUserId = CoreSites.getCurrentSiteUserId(); // Refresh data if comments are synchronized automatically. - this.syncObserver = CoreEvents.on(CoreCommentsSyncProvider.AUTO_SYNCED, (data) => { + this.syncObserver = CoreEvents.on(CoreCommentsSyncProvider.AUTO_SYNCED, (data) => { if (data.contextLevel == this.contextLevel && data.instanceId == this.instanceId && data.componentName == this.componentName && data.itemId == this.itemId && data.area == this.area) { // Show the sync warnings. @@ -298,7 +296,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { this.comments = [addedComments].concat(this.comments); this.canDeleteComments = this.addDeleteCommentsAvailable; - CoreEvents.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { + CoreEvents.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { contextLevel: this.contextLevel, instanceId: this.instanceId, component: this.componentName, @@ -360,7 +358,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { if (index >= 0) { this.comments.splice(index, 1); - CoreEvents.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { + CoreEvents.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { contextLevel: this.contextLevel, instanceId: this.instanceId, component: this.componentName, diff --git a/src/core/features/comments/services/comments-sync.ts b/src/core/features/comments/services/comments-sync.ts index 68e6754ff..be1974e52 100644 --- a/src/core/features/comments/services/comments-sync.ts +++ b/src/core/features/comments/services/comments-sync.ts @@ -14,7 +14,7 @@ import { Injectable } from '@angular/core'; import { CoreSyncBaseProvider } from '@classes/base-sync'; -import { CoreComments, CoreCommentsCountChangedEventData, CoreCommentsProvider } from './comments'; +import { CoreComments, CoreCommentsProvider } from './comments'; import { CoreEvents } from '@singletons/events'; import { makeSingleton, Translate } from '@singletons'; import { CoreCommentsOffline } from './comments-offline'; @@ -94,7 +94,7 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider(CoreCommentsSyncProvider.AUTO_SYNCED, { + CoreEvents.trigger(CoreCommentsSyncProvider.AUTO_SYNCED, { contextLevel: comment.contextlevel, instanceId: comment.instanceid, componentName: comment.component, @@ -262,7 +262,7 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { + CoreEvents.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { contextLevel: contextLevel, instanceId: instanceId, component, diff --git a/src/core/features/comments/services/comments.ts b/src/core/features/comments/services/comments.ts index 3792c1274..fac2b906c 100644 --- a/src/core/features/comments/services/comments.ts +++ b/src/core/features/comments/services/comments.ts @@ -22,9 +22,25 @@ import { CoreWSExternalWarning } from '@services/ws'; import { makeSingleton } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { CoreCommentsOffline } from './comments-offline'; +import { CoreCommentsSyncAutoSyncData, CoreCommentsSyncProvider } from './comments-sync'; const ROOT_CACHE_KEY = 'mmComments:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [CoreCommentsProvider.REFRESH_COMMENTS_EVENT]: CoreCommentsRefreshCommentsEventData; + [CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT]: CoreCommentsCountChangedEventData; + [CoreCommentsSyncProvider.AUTO_SYNCED]: CoreCommentsSyncAutoSyncData; + } + +} + /** * Service that provides some features regarding comments. */ diff --git a/src/core/features/course/classes/main-resource-component.ts b/src/core/features/course/classes/main-resource-component.ts index d479f665e..0b849707c 100644 --- a/src/core/features/course/classes/main-resource-component.ts +++ b/src/core/features/course/classes/main-resource-component.ts @@ -26,7 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreTextErrorObject, CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; -import { CoreEventObserver, CoreEventPackageStatusChanged, CoreEvents } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; import { CoreCourseContentsPage } from '../pages/contents/contents'; import { CoreCourse } from '../services/course'; @@ -314,7 +314,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, } // Listen for changes on this module status. - this.statusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { + this.statusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { if (!this.module || data.componentId != this.module.id || data.component != this.component) { return; } diff --git a/src/core/features/course/components/format/format.ts b/src/core/features/course/components/format/format.ts index 301d34cc2..afbefe842 100644 --- a/src/core/features/course/components/format/format.ts +++ b/src/core/features/course/components/format/format.ts @@ -44,7 +44,7 @@ import { CoreCourseSectionWithStatus, } from '@features/course/services/course-helper'; import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; -import { CoreEventObserver, CoreEvents, CoreEventSectionStatusChangedData, CoreEventSelectCourseTabData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { IonContent, IonRefresher } from '@ionic/angular'; import { CoreUtils } from '@services/utils/utils'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; @@ -123,7 +123,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { */ ngOnInit(): void { // Listen for section status changes. - this.sectionStatusObserver = CoreEvents.on( + this.sectionStatusObserver = CoreEvents.on( CoreEvents.SECTION_STATUS_CHANGED, async (data) => { if (!this.downloadEnabled || !this.sections?.length || !data.sectionId || data.courseId != this.course?.id) { @@ -155,7 +155,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { ); // Listen for select course tab events to select the right section if needed. - this.selectTabObserver = CoreEvents.on(CoreEvents.SELECT_COURSE_TAB, (data) => { + this.selectTabObserver = CoreEvents.on(CoreEvents.SELECT_COURSE_TAB, (data) => { if (data.name) { return; } diff --git a/src/core/features/course/components/module/module.ts b/src/core/features/course/components/module/module.ts index b1bdd5a0d..0241aa2a5 100644 --- a/src/core/features/course/components/module/module.ts +++ b/src/core/features/course/components/module/module.ts @@ -16,7 +16,7 @@ import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angu import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreEventObserver, CoreEventPackageStatusChanged, CoreEvents } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreCourseHelper, CoreCourseModule, @@ -99,7 +99,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { this.prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module); this.canCheckUpdates = CoreCourseModulePrefetchDelegate.canCheckUpdates(); - this.statusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { + this.statusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { if (!this.module || data.componentId != this.module.id || !this.prefetchHandler || data.component != this.prefetchHandler.component) { return; diff --git a/src/core/features/course/pages/contents/contents.ts b/src/core/features/course/pages/contents/contents.ts index 489fc3aef..1a3c4823c 100644 --- a/src/core/features/course/pages/contents/contents.ts +++ b/src/core/features/course/pages/contents/contents.ts @@ -36,13 +36,11 @@ import { CoreCourseOptionsDelegate, CoreCourseOptionsMenuHandlerToDisplay, } from '@features/course/services/course-options-delegate'; -import { CoreCourseAutoSyncData, CoreCourseSync, CoreCourseSyncProvider } from '@features/course/services/sync'; +import { CoreCourseSync, CoreCourseSyncProvider } from '@features/course/services/sync'; import { CoreCourseFormatComponent } from '../../components/format/format'; import { CoreEvents, CoreEventObserver, - CoreEventCourseStatusChanged, - CoreEventCompletionModuleViewedData, } from '@singletons/events'; import { CoreNavigator } from '@services/navigator'; import { CoreConstants } from '@/core/constants'; @@ -123,7 +121,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { protected async initListeners(): Promise { if (this.downloadCourseEnabled) { // Listen for changes in course status. - this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data) => { + this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data) => { if (data.courseId == this.course.id || data.courseId == CoreCourseProvider.ALL_COURSES_CLEARED) { this.updateCourseStatus(data.status); } @@ -136,7 +134,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { return; } - this.completionObserver = CoreEvents.on( + this.completionObserver = CoreEvents.on( CoreEvents.COMPLETION_MODULE_VIEWED, (data) => { if (data && data.courseId == this.course.id) { @@ -145,7 +143,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { }, ); - this.syncObserver = CoreEvents.on(CoreCourseSyncProvider.AUTO_SYNCED, (data) => { + this.syncObserver = CoreEvents.on(CoreCourseSyncProvider.AUTO_SYNCED, (data) => { if (!data || data.courseId != this.course.id) { return; } diff --git a/src/core/features/course/pages/index/index.ts b/src/core/features/course/pages/index/index.ts index 87062e459..3ef58db7d 100644 --- a/src/core/features/course/pages/index/index.ts +++ b/src/core/features/course/pages/index/index.ts @@ -19,7 +19,7 @@ import { CoreTabsOutletTab, CoreTabsOutletComponent } from '@components/tabs-out import { CoreCourseFormatDelegate } from '../../services/format-delegate'; import { CoreCourseOptionsDelegate } from '../../services/course-options-delegate'; import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; -import { CoreEventObserver, CoreEvents, CoreEventSelectCourseTabData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course'; import { CoreCourseHelper } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; @@ -52,7 +52,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { }; constructor() { - this.selectTabObserver = CoreEvents.on(CoreEvents.SELECT_COURSE_TAB, (data) => { + this.selectTabObserver = CoreEvents.on(CoreEvents.SELECT_COURSE_TAB, (data) => { if (!data.name) { // If needed, set sectionId and sectionNumber. They'll only be used if the content tabs hasn't been loaded yet. if (data.sectionId) { diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index 70465dc51..88d7bbb4b 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -29,7 +29,7 @@ import { import { CoreConstants } from '@/core/constants'; import { CoreLogger } from '@singletons/logger'; import { makeSingleton, Translate } from '@singletons'; -import { CoreFilepool, CoreFilepoolComponentFileEventData } from '@services/filepool'; +import { CoreFilepool } from '@services/filepool'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { @@ -61,7 +61,7 @@ import { CoreFile } from '@services/file'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreTextUtils } from '@services/utils/text'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreEventObserver, CoreEventPackageStatusChanged, CoreEvents } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreFilterHelper } from '@features/filter/services/filter-helper'; import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreSiteHome } from '@features/sitehome/services/sitehome'; @@ -975,7 +975,7 @@ export class CoreCourseHelperProvider { } if (!instance.contextMenuStatusObserver && component) { - instance.contextMenuStatusObserver = CoreEvents.on( + instance.contextMenuStatusObserver = CoreEvents.on( CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { if (data.componentId == module.id && data.component == component) { @@ -994,7 +994,7 @@ export class CoreCourseHelperProvider { instance.size = moduleSize > 0 ? CoreTextUtils.bytesToSize(moduleSize, 2) : ''; }, 1000); - instance.contextFileStatusObserver = CoreEvents.on( + instance.contextFileStatusObserver = CoreEvents.on( CoreEvents.COMPONENT_FILE_ACTION, (data) => { if (data.component != component || data.componentId != module.id) { diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index fb7f5c2af..4052c53da 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -31,7 +31,6 @@ import { CoreCourseOffline } from './course-offline'; import { CoreError } from '@classes/errors/error'; import { CoreCourseAnyCourseData, - CoreCoursesMyCoursesUpdatedEventData, CoreCoursesProvider, } from '../../courses/services/courses'; import { CoreDomUtils } from '@services/utils/dom'; @@ -42,9 +41,23 @@ import { CoreCourseFormatDelegate } from './format-delegate'; import { CoreCronDelegate } from '@services/cron'; import { CoreCourseLogCronHandler } from './handlers/log-cron'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; +import { CoreCourseAutoSyncData, CoreCourseSyncProvider } from './sync'; const ROOT_CACHE_KEY = 'mmCourse:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [CoreCourseSyncProvider.AUTO_SYNCED]: CoreCourseAutoSyncData; + } + +} + /** * Service that provides some features regarding a course. */ @@ -902,7 +915,7 @@ export class CoreCourseProvider { if (!response.status) { throw Error('WS core_course_view_course failed.'); } else { - CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, { + CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, { courseId: courseId, action: CoreCoursesProvider.ACTION_VIEW, }, site.getId()); diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index a223ebac9..f06387f67 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -18,7 +18,7 @@ import { Md5 } from 'ts-md5/dist/md5'; import { CoreFile } from '@services/file'; import { CoreFileHelper } from '@services/file-helper'; -import { CoreFilepool, CoreFilepoolComponentFileEventData } from '@services/filepool'; +import { CoreFilepool } from '@services/filepool'; import { CoreSites } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; @@ -28,7 +28,7 @@ import { CoreSiteWSPreSets } from '@classes/site'; import { CoreConstants } from '@/core/constants'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { makeSingleton } from '@singletons'; -import { CoreEventPackageStatusChanged, CoreEvents, CoreEventSectionStatusChangedData } from '@singletons/events'; +import { CoreEvents, CoreEventSectionStatusChangedData } from '@singletons/events'; import { CoreError } from '@classes/errors/error'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { CHECK_UPDATES_TIMES_TABLE, CoreCourseCheckUpdatesDBRecord } from './database/module-prefetch'; @@ -62,12 +62,12 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { + CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { this.updateStatusCache(data.status, data.component, data.componentId); }, CoreSites.getCurrentSiteId()); // If a file inside a module is downloaded/deleted, clear the corresponding cache. - CoreEvents.on(CoreEvents.COMPONENT_FILE_ACTION, (data) => { + CoreEvents.on(CoreEvents.COMPONENT_FILE_ACTION, (data) => { if (!CoreFilepool.isFileEventDownloadedOrDeleted(data)) { return; } diff --git a/src/core/features/course/services/sync.ts b/src/core/features/course/services/sync.ts index 2bb742073..dbd7b6440 100644 --- a/src/core/features/course/services/sync.ts +++ b/src/core/features/course/services/sync.ts @@ -27,7 +27,7 @@ import { CoreWSExternalWarning } from '@services/ws'; import { CoreCourseManualCompletionDBRecord } from './database/course'; import { CoreNetworkError } from '@classes/errors/network-error'; import { makeSingleton, Translate } from '@singletons'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; /** * Service to sync course offline data. This only syncs the offline data of the course itself, not the offline data of @@ -87,7 +87,7 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider(CoreCourseSyncProvider.AUTO_SYNCED, { + CoreEvents.trigger(CoreCourseSyncProvider.AUTO_SYNCED, { courseId: completion.courseid, warnings: result.warnings, }, siteId); @@ -253,7 +253,7 @@ export type CoreCourseSyncResult = { /** * Data passed to AUTO_SYNCED event. */ -export type CoreCourseAutoSyncData = CoreEventSiteData & { +export type CoreCourseAutoSyncData = { courseId: number; warnings: CoreWSExternalWarning[]; }; diff --git a/src/core/features/courses/components/course-progress/course-progress.ts b/src/core/features/courses/components/course-progress/course-progress.ts index acc8e9b69..dff808d28 100644 --- a/src/core/features/courses/components/course-progress/course-progress.ts +++ b/src/core/features/courses/components/course-progress/course-progress.ts @@ -16,7 +16,7 @@ import { Component, Input, OnInit, OnDestroy } from '@angular/core'; import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreCourses, CoreCoursesMyCoursesUpdatedEventData, CoreCoursesProvider } from '@features/courses/services/courses'; +import { CoreCourses, CoreCoursesProvider } from '@features/courses/services/courses'; import { CoreCourse, CoreCourseProvider } from '@features/course/services/course'; import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper'; import { PopoverController, Translate } from '@singletons'; @@ -258,7 +258,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy { ); this.course.hidden = hide; - CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, { + CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, { courseId: this.course.id, course: this.course, action: CoreCoursesProvider.ACTION_STATE_CHANGED, @@ -287,7 +287,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy { await CoreCourses.setFavouriteCourse(this.course.id, favourite); this.course.isfavourite = favourite; - CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, { + CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, { courseId: this.course.id, course: this.course, action: CoreCoursesProvider.ACTION_STATE_CHANGED, diff --git a/src/core/features/courses/pages/my-courses/my-courses.ts b/src/core/features/courses/pages/my-courses/my-courses.ts index d09a985fc..252ba4357 100644 --- a/src/core/features/courses/pages/my-courses/my-courses.ts +++ b/src/core/features/courses/pages/my-courses/my-courses.ts @@ -19,7 +19,6 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreCoursesProvider, - CoreCoursesMyCoursesUpdatedEventData, CoreCourses, } from '../../services/courses'; import { CoreCoursesHelper, CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper'; @@ -59,7 +58,7 @@ export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy { // Update list if user enrols in a course. this.myCoursesObserver = CoreEvents.on( CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, - (data: CoreCoursesMyCoursesUpdatedEventData) => { + (data) => { if (data.action == CoreCoursesProvider.ACTION_ENROL) { this.fetchCourses(); diff --git a/src/core/features/courses/services/courses.ts b/src/core/features/courses/services/courses.ts index cacb90551..0e4d56c9b 100644 --- a/src/core/features/courses/services/courses.ts +++ b/src/core/features/courses/services/courses.ts @@ -18,11 +18,26 @@ import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { makeSingleton } from '@singletons'; import { CoreStatusWithWarningsWSResponse, CoreWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; -import { CoreEvents, CoreEventSiteData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { CoreWSError } from '@classes/errors/wserror'; const ROOT_CACHE_KEY = 'mmCourses:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [CoreCoursesProvider.EVENT_MY_COURSES_CHANGED]: CoreCoursesMyCoursesChangedEventData; + [CoreCoursesProvider.EVENT_MY_COURSES_UPDATED]: CoreCoursesMyCoursesUpdatedEventData; + [CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED]: CoreCoursesDashboardDownloadEnabledChangedEventData; + } + +} + /** * Service that provides some features regarding lists of courses and categories. */ @@ -853,7 +868,7 @@ export class CoreCoursesProvider { if (added.length || removed.length) { // At least 1 course was added or removed, trigger the event. - CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_CHANGED, { + CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_CHANGED, { added: added, removed: removed, }, site.getId()); @@ -1169,7 +1184,7 @@ export const CoreCourses = makeSingleton(CoreCoursesProvider); /** * Data sent to the EVENT_MY_COURSES_UPDATED. */ -export type CoreCoursesMyCoursesUpdatedEventData = CoreEventSiteData & { +export type CoreCoursesMyCoursesUpdatedEventData = { action: string; // Action performed. courseId?: number; // Course ID affected (if any). course?: CoreCourseAnyCourseData; // Course affected (if any). @@ -1180,11 +1195,18 @@ export type CoreCoursesMyCoursesUpdatedEventData = CoreEventSiteData & { /** * Data sent to the EVENT_MY_COURSES_CHANGED. */ -export type CoreCoursesMyCoursesChangedEventData = CoreEventSiteData & { +export type CoreCoursesMyCoursesChangedEventData = { added: number[]; removed: number[]; }; +/** + * Data sent to the EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED. + */ +export type CoreCoursesDashboardDownloadEnabledChangedEventData = { + enabled: boolean; +}; + /** * Params of core_enrol_get_users_courses WS. */ diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index 6a66670ba..0bb494c98 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -18,7 +18,7 @@ import { Md5 } from 'ts-md5/dist/md5'; import { CoreApp, CoreStoreConfig } from '@services/app'; import { CoreConfig } from '@services/config'; -import { CoreEvents, CoreEventSessionExpiredData } from '@singletons/events'; +import { CoreEvents, CoreEventSessionExpiredData, CoreEventSiteData } from '@singletons/events'; import { CoreSites, CoreLoginSiteInfo } from '@services/sites'; import { CoreWS, CoreWSExternalWarning } from '@services/ws'; import { CoreDomUtils } from '@services/utils/dom'; @@ -876,7 +876,7 @@ export class CoreLoginHelperProvider { * @param data Data received by the SESSION_EXPIRED event. * @return Promise resolved when done. */ - async sessionExpired(data: CoreEventSessionExpiredData): Promise { + async sessionExpired(data: CoreEventSessionExpiredData & CoreEventSiteData): Promise { const siteId = data?.siteId; const currentSite = CoreSites.getCurrentSite(); const siteUrl = currentSite?.getURL(); diff --git a/src/core/features/rating/components/aggregate/aggregate.ts b/src/core/features/rating/components/aggregate/aggregate.ts index e44935651..c6b572938 100644 --- a/src/core/features/rating/components/aggregate/aggregate.ts +++ b/src/core/features/rating/components/aggregate/aggregate.ts @@ -22,7 +22,7 @@ import { } from '@features/rating/services/rating'; import { CoreSites } from '@services/sites'; import { ModalController } from '@singletons'; -import { CoreEventObserver, CoreEvents, CoreEventSiteUpdatedData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreRatingRatingsComponent } from '../ratings/ratings'; /** @@ -54,7 +54,7 @@ export class CoreRatingAggregateComponent implements OnChanges, OnDestroy { this.disabled = CoreRating.isRatingDisabledInSite(); // Update visibility if current site info is updated. - this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { + this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { this.disabled = CoreRating.isRatingDisabledInSite(); }, CoreSites.getCurrentSiteId()); diff --git a/src/core/features/rating/components/rate/rate.ts b/src/core/features/rating/components/rate/rate.ts index 1dc6f71db..4a94297fe 100644 --- a/src/core/features/rating/components/rate/rate.ts +++ b/src/core/features/rating/components/rate/rate.ts @@ -25,7 +25,7 @@ import { CoreRatingOffline } from '@features/rating/services/rating-offline'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { Translate } from '@singletons'; -import { CoreEventObserver, CoreEvents, CoreEventSiteUpdatedData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; /** * Component that displays the user rating select. @@ -63,7 +63,7 @@ export class CoreRatingRateComponent implements OnChanges, OnDestroy { this.disabled = CoreRating.isRatingDisabledInSite(); // Update visibility if current site info is updated. - this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { + this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { this.disabled = CoreRating.isRatingDisabledInSite(); }, CoreSites.getCurrentSiteId()); } diff --git a/src/core/features/settings/pages/site/site.ts b/src/core/features/settings/pages/site/site.ts index c2d1421aa..3f62f3207 100644 --- a/src/core/features/settings/pages/site/site.ts +++ b/src/core/features/settings/pages/site/site.ts @@ -17,7 +17,7 @@ import { ActivatedRouteSnapshot, Params } from '@angular/router'; import { IonRefresher } from '@ionic/angular'; import { CoreSettingsDelegate, CoreSettingsHandlerToDisplay } from '../../services/settings-delegate'; -import { CoreEventObserver, CoreEvents, CoreEventSiteUpdatedData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; // import { CoreSharedFiles } from '@features/sharedfiles/services/sharedfiles'; @@ -62,7 +62,7 @@ export class CoreSitePreferencesPage implements AfterViewInit, OnDestroy { this.siteId = CoreSites.getCurrentSiteId(); this.handlers = new CoreSettingsSitePreferencesManager(CoreSitePreferencesPage); - this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, (data: CoreEventSiteUpdatedData) => { + this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, (data) => { if (data.siteId == this.siteId) { this.refreshData(); } diff --git a/src/core/features/settings/pages/space-usage/space-usage.ts b/src/core/features/settings/pages/space-usage/space-usage.ts index f214e0d70..af9d51202 100644 --- a/src/core/features/settings/pages/space-usage/space-usage.ts +++ b/src/core/features/settings/pages/space-usage/space-usage.ts @@ -18,7 +18,7 @@ import { IonRefresher } from '@ionic/angular'; import { CoreSiteBasicInfo, CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { Translate } from '@singletons'; -import { CoreEventObserver, CoreEvents, CoreEventSiteUpdatedData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSettingsHelper, CoreSiteSpaceUsage } from '../../services/settings-helper'; @@ -44,7 +44,7 @@ export class CoreSettingsSpaceUsagePage implements OnInit, OnDestroy { constructor() { this.currentSiteId = CoreSites.getCurrentSiteId(); - this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async (data: CoreEventSiteUpdatedData) => { + this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async (data) => { const site = await CoreSites.getSite(data.siteId); const siteEntry = this.sites.find((siteEntry) => siteEntry.id == site.id); diff --git a/src/core/features/settings/pages/synchronization/synchronization.ts b/src/core/features/settings/pages/synchronization/synchronization.ts index e55125c35..5b5b664c3 100644 --- a/src/core/features/settings/pages/synchronization/synchronization.ts +++ b/src/core/features/settings/pages/synchronization/synchronization.ts @@ -15,7 +15,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { CoreConstants } from '@/core/constants'; -import { CoreEventObserver, CoreEvents, CoreEventSiteUpdatedData } from '@singletons/events'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites, CoreSiteBasicInfo } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreConfig } from '@services/config'; @@ -42,7 +42,7 @@ export class CoreSettingsSynchronizationPage implements OnInit, OnDestroy { this.currentSiteId = CoreSites.getCurrentSiteId(); - this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async (data: CoreEventSiteUpdatedData) => { + this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async (data) => { const site = await CoreSites.getSite(data.siteId); const siteEntry = this.sites.find((siteEntry) => siteEntry.id == site.id); diff --git a/src/core/features/siteplugins/services/siteplugins-helper.ts b/src/core/features/siteplugins/services/siteplugins-helper.ts index 439340e14..7634174d6 100644 --- a/src/core/features/siteplugins/services/siteplugins-helper.ts +++ b/src/core/features/siteplugins/services/siteplugins-helper.ts @@ -27,7 +27,7 @@ import { CoreCourseOptionsDelegate } from '@features/course/services/course-opti import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; -import { CoreCoursesMyCoursesChangedEventData, CoreCoursesProvider } from '@features/courses/services/courses'; +import { CoreCoursesProvider } from '@features/courses/services/courses'; import { CoreMainMenuDelegate } from '@features/mainmenu/services/mainmenu-delegate'; import { CoreQuestionBehaviourDelegate } from '@features/question/services/behaviour-delegate'; import { CoreQuestionDelegate } from '@features/question/services/question-delegate'; @@ -142,7 +142,7 @@ export class CoreSitePluginsHelperProvider { }); // Re-load plugins restricted for courses when the list of user courses changes. - CoreEvents.on(CoreCoursesProvider.EVENT_MY_COURSES_CHANGED, (data) => { + CoreEvents.on(CoreCoursesProvider.EVENT_MY_COURSES_CHANGED, (data) => { if (data && data.siteId && data.siteId == CoreSites.getCurrentSiteId() && data.added && data.added.length) { this.reloadCourseRestrictHandlers(); } diff --git a/src/core/features/user/pages/about/about.page.ts b/src/core/features/user/pages/about/about.page.ts index 8598109cd..495c2bcdf 100644 --- a/src/core/features/user/pages/about/about.page.ts +++ b/src/core/features/user/pages/about/about.page.ts @@ -21,7 +21,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { CoreEvents } from '@singletons/events'; -import { CoreUser, CoreUserProfile, CoreUserProfileRefreshedData, CoreUserProvider } from '@features/user/services/user'; +import { CoreUser, CoreUserProfile, CoreUserProvider } from '@features/user/services/user'; import { CoreUserHelper } from '@features/user/services/user-helper'; import { CoreNavigator } from '@services/navigator'; @@ -102,7 +102,7 @@ export class CoreUserAboutPage implements OnInit { event?.detail.complete(); if (this.user) { - CoreEvents.trigger(CoreUserProvider.PROFILE_REFRESHED, { + CoreEvents.trigger(CoreUserProvider.PROFILE_REFRESHED, { courseId: this.courseId, userId: this.userId, user: this.user, diff --git a/src/core/features/user/pages/profile/profile.page.ts b/src/core/features/user/pages/profile/profile.page.ts index 7487b764a..5dc175524 100644 --- a/src/core/features/user/pages/profile/profile.page.ts +++ b/src/core/features/user/pages/profile/profile.page.ts @@ -25,8 +25,6 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreUser, CoreUserProfile, - CoreUserProfilePictureUpdatedData, - CoreUserProfileRefreshedData, CoreUserProvider, } from '@features/user/services/user'; import { CoreUserHelper } from '@features/user/services/user-helper'; @@ -63,7 +61,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { communicationHandlers: CoreUserProfileHandlerData[] = []; constructor() { - this.obsProfileRefreshed = CoreEvents.on(CoreUserProvider.PROFILE_REFRESHED, (data) => { + this.obsProfileRefreshed = CoreEvents.on(CoreUserProvider.PROFILE_REFRESHED, (data) => { if (!this.user || !data.user) { return; } @@ -182,7 +180,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { await CoreSites.updateSiteInfo(this.site.getId()); } catch { // Cannot update site info. Assume the profile image is the right one. - CoreEvents.trigger(CoreUserProvider.PROFILE_PICTURE_UPDATED, { + CoreEvents.trigger(CoreUserProvider.PROFILE_PICTURE_UPDATED, { userId: this.userId, picture: this.user.profileimageurl, }, this.site.getId()); @@ -193,7 +191,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { await this.refreshUser(); } else { // Now they're the same, send event to use the right avatar in the rest of the app. - CoreEvents.trigger(CoreUserProvider.PROFILE_PICTURE_UPDATED, { + CoreEvents.trigger(CoreUserProvider.PROFILE_PICTURE_UPDATED, { userId: this.userId, picture: this.user.profileimageurl, }, this.site.getId()); @@ -216,7 +214,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { const profileImageURL = await CoreUser.changeProfilePicture(result.itemid, this.userId, this.site!.getId()); - CoreEvents.trigger(CoreUserProvider.PROFILE_PICTURE_UPDATED, { + CoreEvents.trigger(CoreUserProvider.PROFILE_PICTURE_UPDATED, { userId: this.userId, picture: profileImageURL, }, this.site!.getId()); @@ -249,7 +247,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { event?.detail.complete(); if (this.user) { - CoreEvents.trigger(CoreUserProvider.PROFILE_REFRESHED, { + CoreEvents.trigger(CoreUserProvider.PROFILE_REFRESHED, { courseId: this.courseId, userId: this.userId, user: this.user, diff --git a/src/core/features/user/services/user-delegate.ts b/src/core/features/user/services/user-delegate.ts index ae44378b4..1f2205369 100644 --- a/src/core/features/user/services/user-delegate.ts +++ b/src/core/features/user/services/user-delegate.ts @@ -170,7 +170,7 @@ export class CoreUserDelegateService extends CoreDelegate(CoreUserDelegateService.UPDATE_HANDLER_EVENT, (data) => { + CoreEvents.on(CoreUserDelegateService.UPDATE_HANDLER_EVENT, (data) => { if (!data || !data.handler || !this.userHandlers[data.userId]) { return; } diff --git a/src/core/features/user/services/user.ts b/src/core/features/user/services/user.ts index ff530424d..41a4cd95b 100644 --- a/src/core/features/user/services/user.ts +++ b/src/core/features/user/services/user.ts @@ -22,14 +22,30 @@ import { CoreUserOffline } from './user-offline'; import { CoreLogger } from '@singletons/logger'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { makeSingleton } from '@singletons'; -import { CoreEvents, CoreEventUserDeletedData } from '@singletons/events'; +import { CoreEvents } from '@singletons/events'; import { CoreStatusWithWarningsWSResponse, CoreWSExternalWarning } from '@services/ws'; import { CoreError } from '@classes/errors/error'; import { USERS_TABLE_NAME, CoreUserDBRecord } from './database/user'; import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications'; +import { CoreUserDelegateService, CoreUserUpdateHandlerData } from './user-delegate'; const ROOT_CACHE_KEY = 'mmUser:'; +declare module '@singletons/events' { + + /** + * Augment CoreEventsData interface with events specific to this service. + * + * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation + */ + export interface CoreEventsData { + [CoreUserProvider.PROFILE_REFRESHED]: CoreUserProfileRefreshedData; + [CoreUserProvider.PROFILE_PICTURE_UPDATED]: CoreUserProfilePictureUpdatedData; + [CoreUserDelegateService.UPDATE_HANDLER_EVENT]: CoreUserUpdateHandlerData; + } + +} + /** * Service to provide user functionalities. */ @@ -45,7 +61,7 @@ export class CoreUserProvider { constructor() { this.logger = CoreLogger.getInstance('CoreUserProvider'); - CoreEvents.on(CoreEvents.USER_DELETED, (data) => { + CoreEvents.on(CoreEvents.USER_DELETED, (data) => { // Search for userid in params. let userId = 0; diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts index 2e7e148c8..14a44e3ff 100644 --- a/src/core/singletons/events.ts +++ b/src/core/singletons/events.ts @@ -17,6 +17,7 @@ import { Subject } from 'rxjs'; import { CoreLogger } from '@singletons/logger'; import { CoreSite, CoreSiteInfoResponse, CoreSitePublicConfigResponse } from '@classes/site'; +import { CoreFilepoolComponentFileEventData } from '@services/filepool'; /** * Observer instance to stop listening to an event. @@ -48,6 +49,8 @@ export interface CoreEventsData { [CoreEvents.ACTIVITY_DATA_SENT]: CoreEventActivityDataSentData; [CoreEvents.IAB_LOAD_START]: InAppBrowserEvent; [CoreEvents.LOGIN_SITE_CHECKED]: CoreEventLoginSiteCheckedData; + [CoreEvents.SEND_ON_ENTER_CHANGED]: CoreEventSendOnEnterChangedData; + [CoreEvents.COMPONENT_FILE_ACTION]: CoreFilepoolComponentFileEventData; }; /* @@ -108,13 +111,13 @@ export class CoreEvents { */ static on( eventName: Event, - callBack: (value: CoreEventData & { siteId?: string }) => void, + callBack: (value: CoreEventData & CoreEventSiteData) => void, siteId?: string, ): CoreEventObserver { // If it's a unique event and has been triggered already, call the callBack. // We don't need to create an observer because the event won't be triggered again. if (this.uniqueEvents[eventName]) { - callBack(this.uniqueEvents[eventName].data as CoreEventData & { siteId?: string }); + callBack(this.uniqueEvents[eventName].data as CoreEventData & CoreEventSiteData); // Return a fake observer to prevent errors. return { @@ -132,7 +135,7 @@ export class CoreEvents { } const subscription = this.observables[eventName].subscribe( - (value: CoreEventData & { siteId?: string }) => { + (value: CoreEventData & CoreEventSiteData) => { if (!siteId || value.siteId == siteId) { callBack(value); } @@ -243,17 +246,17 @@ export type CoreEventSiteData = { /** * Data passed to SITE_UPDATED event. */ -export type CoreEventSiteUpdatedData = CoreEventSiteData & CoreSiteInfoResponse; +export type CoreEventSiteUpdatedData = CoreSiteInfoResponse; /** * Data passed to SITE_ADDED event. */ -export type CoreEventSiteAddedData = CoreEventSiteData & CoreSiteInfoResponse; +export type CoreEventSiteAddedData = CoreSiteInfoResponse; /** * Data passed to SESSION_EXPIRED event. */ -export type CoreEventSessionExpiredData = CoreEventSiteData & { +export type CoreEventSessionExpiredData = { pageName?: string; params?: Params; }; @@ -286,7 +289,7 @@ export type CoreEventPackageStatusChanged = { /** * Data passed to USER_DELETED event. */ -export type CoreEventUserDeletedData = CoreEventSiteData & { +export type CoreEventUserDeletedData = { // eslint-disable-next-line @typescript-eslint/no-explicit-any params: any; // Params sent to the WS that failed. }; @@ -299,7 +302,7 @@ export enum CoreEventFormAction { /** * Data passed to FORM_ACTION event. */ -export type CoreEventFormActionData = CoreEventSiteData & { +export type CoreEventFormActionData = { action: CoreEventFormAction; // Action performed. form: HTMLElement; // Form element. online?: boolean; // Whether the data was sent to server or not. Only when submitting. @@ -308,14 +311,14 @@ export type CoreEventFormActionData = CoreEventSiteData & { /** * Data passed to NOTIFICATION_SOUND_CHANGED event. */ -export type CoreEventNotificationSoundChangedData = CoreEventSiteData & { +export type CoreEventNotificationSoundChangedData = { enabled: boolean; }; /** * Data passed to SELECT_COURSE_TAB event. */ -export type CoreEventSelectCourseTabData = CoreEventSiteData & { +export type CoreEventSelectCourseTabData = { name?: string; // Name of the tab's handler. If not set, load course contents. sectionId?: number; sectionNumber?: number; @@ -324,14 +327,14 @@ export type CoreEventSelectCourseTabData = CoreEventSiteData & { /** * Data passed to COMPLETION_MODULE_VIEWED event. */ -export type CoreEventCompletionModuleViewedData = CoreEventSiteData & { +export type CoreEventCompletionModuleViewedData = { courseId?: number; }; /** * Data passed to SECTION_STATUS_CHANGED event. */ -export type CoreEventSectionStatusChangedData = CoreEventSiteData & { +export type CoreEventSectionStatusChangedData = { courseId: number; sectionId?: number; }; @@ -339,7 +342,7 @@ export type CoreEventSectionStatusChangedData = CoreEventSiteData & { /** * Data passed to ACTIVITY_DATA_SENT event. */ -export type CoreEventActivityDataSentData = CoreEventSiteData & { +export type CoreEventActivityDataSentData = { module: string; }; @@ -349,3 +352,10 @@ export type CoreEventActivityDataSentData = CoreEventSiteData & { export type CoreEventLoginSiteCheckedData = { config: CoreSitePublicConfigResponse; }; + +/** + * Data passed to SEND_ON_ENTER_CHANGED event. + */ +export type CoreEventSendOnEnterChangedData = { + sendOnEnter: boolean; +};