Merge pull request #2978 from dpalou/MOBILE-3887

Mobile 3887
main
Noel De Martin 2021-10-20 16:05:28 +02:00 committed by GitHub
commit 28bb27bd65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 196 additions and 264 deletions

View File

@ -36,7 +36,7 @@
<ion-label> <ion-label>
<p class="item-heading">{{ notification.subject }}</p> <p class="item-heading">{{ notification.subject }}</p>
<p *ngIf="notification.userfromfullname">{{ notification.userfromfullname }}</p> <p *ngIf="notification.useridfrom > 0">{{ notification.userfromfullname }}</p>
</ion-label> </ion-label>
<ion-note slot="end" class="ion-float-end ion-text-end"> <ion-note slot="end" class="ion-float-end ion-text-end">
{{ notification.timecreated | coreDateDayOrTime }} {{ notification.timecreated | coreDateDayOrTime }}

View File

@ -21,8 +21,11 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreEvents, CoreEventObserver } from '@singletons/events'; import { CoreEvents, CoreEventObserver } from '@singletons/events';
import { AddonNotifications, AddonNotificationsAnyNotification, AddonNotificationsProvider } from '../../services/notifications'; import {
import { AddonNotificationsHelper } from '../../services/notifications-helper'; AddonNotifications,
AddonNotificationsNotificationMessageFormatted,
AddonNotificationsProvider,
} from '../../services/notifications';
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
/** /**
@ -89,9 +92,7 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
this.loadMoreError = false; this.loadMoreError = false;
try { try {
const result = await AddonNotificationsHelper.getNotifications(refresh ? [] : this.notifications, { const result = await AddonNotifications.getNotifications(refresh ? [] : this.notifications);
onlyPopupNotifications: true,
});
const notifications = result.notifications.map((notification) => this.formatText(notification)); const notifications = result.notifications.map((notification) => this.formatText(notification));
@ -156,9 +157,9 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
try { try {
this.loadingMarkAllNotificationsAsRead = true; this.loadingMarkAllNotificationsAsRead = true;
const unread = await AddonNotifications.getUnreadNotificationsCount(); const unreadCountData = await AddonNotifications.getUnreadNotificationsCount();
this.canMarkAllNotificationsAsRead = unread > 0; this.canMarkAllNotificationsAsRead = unreadCountData.count > 0;
} finally { } finally {
this.loadingMarkAllNotificationsAsRead = false; this.loadingMarkAllNotificationsAsRead = false;
} }
@ -198,14 +199,14 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
* *
* @param notification The notification object. * @param notification The notification object.
*/ */
protected formatText(notification: AddonNotificationsAnyNotification): FormattedNotification { protected formatText(notification: AddonNotificationsNotificationMessageFormatted): FormattedNotification {
const formattedNotification: FormattedNotification = notification; const formattedNotification: FormattedNotification = notification;
formattedNotification.displayfullhtml = this.shouldDisplayFullHtml(notification); formattedNotification.displayfullhtml = this.shouldDisplayFullHtml(notification);
formattedNotification.iconurl = formattedNotification.iconurl || undefined; // Make sure the property exists. formattedNotification.iconurl = formattedNotification.iconurl || undefined; // Make sure the property exists.
formattedNotification.mobiletext = formattedNotification.displayfullhtml ? formattedNotification.mobiletext = formattedNotification.displayfullhtml ?
notification.fullmessagehtml : notification.fullmessagehtml :
CoreTextUtils.replaceNewLines(formattedNotification.mobiletext!.replace(/-{4,}/ig, ''), '<br>'); CoreTextUtils.replaceNewLines((formattedNotification.mobiletext || '').replace(/-{4,}/ig, ''), '<br>');
return formattedNotification; return formattedNotification;
} }
@ -253,7 +254,7 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
} }
type FormattedNotification = AddonNotificationsAnyNotification & { type FormattedNotification = AddonNotificationsNotificationMessageFormatted & {
displayfullhtml?: boolean; // Whether to display the full HTML of the notification. displayfullhtml?: boolean; // Whether to display the full HTML of the notification.
iconurl?: string; iconurl?: string;
}; };

View File

@ -23,7 +23,7 @@
<ion-card> <ion-card>
<ion-item class="ion-text-wrap" *ngIf="preferences"> <ion-item class="ion-text-wrap" *ngIf="preferences">
<ion-label>{{ 'addon.notifications.notifications' | translate }}</ion-label> <ion-label>{{ 'addon.notifications.notifications' | translate }}</ion-label>
<ion-toggle [(ngModel)]="preferences!.enableall" (ngModelChange)="enableAll(preferences!.enableall)"></ion-toggle> <ion-toggle [(ngModel)]="preferences.enableall" (ngModelChange)="enableAll(preferences.enableall)"></ion-toggle>
</ion-item> </ion-item>
<ion-item class="ion-text-wrap" *ngIf="canChangeSound"> <ion-item class="ion-text-wrap" *ngIf="canChangeSound">
<ion-label>{{ 'addon.notifications.playsound' | translate }}</ion-label> <ion-label>{{ 'addon.notifications.playsound' | translate }}</ion-label>

View File

@ -161,7 +161,7 @@ export class AddonNotificationsSettingsPage implements OnInit, OnDestroy {
* @param name Name of the selected processor. * @param name Name of the selected processor.
*/ */
changeProcessor(name: string): void { changeProcessor(name: string): void {
const processor = this.preferences!.processors.find((processor) => processor.name == name); const processor = this.preferences?.processors.find((processor) => processor.name == name);
if (processor) { if (processor) {
this.loadProcessor(processor); this.loadProcessor(processor);
@ -246,6 +246,10 @@ export class AddonNotificationsSettingsPage implements OnInit, OnDestroy {
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async enableAll(enable?: boolean): Promise<void> { async enableAll(enable?: boolean): Promise<void> {
if (!this.preferences) {
return;
}
const modal = await CoreDomUtils.showModalLoading('core.sending', true); const modal = await CoreDomUtils.showModalLoading('core.sending', true);
try { try {
@ -256,7 +260,7 @@ export class AddonNotificationsSettingsPage implements OnInit, OnDestroy {
} catch (error) { } catch (error) {
// Show error and revert change. // Show error and revert change.
CoreDomUtils.showErrorModal(error); CoreDomUtils.showErrorModal(error);
this.preferences!.enableall = !this.preferences!.enableall; this.preferences.enableall = !this.preferences.enableall;
} finally { } finally {
modal.dismiss(); modal.dismiss();
} }

View File

@ -110,10 +110,12 @@ export class AddonNotificationsMainMenuHandlerService implements CoreMainMenuHan
} }
try { try {
const unreadCount = await AddonNotifications.getUnreadNotificationsCount(undefined, siteId); const unreadCountData = await AddonNotifications.getUnreadNotificationsCount(undefined, siteId);
this.handlerData.badge = unreadCount > 0 ? String(unreadCount) : ''; this.handlerData.badge = unreadCountData.count > 0 ?
CorePushNotifications.updateAddonCounter('AddonNotifications', unreadCount, siteId); unreadCountData.count + (unreadCountData.hasMore ? '+' : '') :
'';
CorePushNotifications.updateAddonCounter('AddonNotifications', unreadCountData.count, siteId);
} catch { } catch {
this.handlerData.badge = ''; this.handlerData.badge = '';
} finally { } finally {

View File

@ -14,20 +14,15 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { AddonMessageOutputDelegate } from '@addons/messageoutput/services/messageoutput-delegate'; import { AddonMessageOutputDelegate } from '@addons/messageoutput/services/messageoutput-delegate';
import { import {
AddonNotifications,
AddonNotificationsAnyNotification,
AddonNotificationsGetNotificationsOptions,
AddonNotificationsPreferences, AddonNotificationsPreferences,
AddonNotificationsPreferencesComponent, AddonNotificationsPreferencesComponent,
AddonNotificationsPreferencesNotification, AddonNotificationsPreferencesNotification,
AddonNotificationsPreferencesNotificationProcessor, AddonNotificationsPreferencesNotificationProcessor,
AddonNotificationsPreferencesProcessor, AddonNotificationsPreferencesProcessor,
AddonNotificationsProvider,
} from './notifications'; } from './notifications';
/** /**
@ -58,57 +53,6 @@ export class AddonNotificationsHelperProvider {
return formattedPreferences; return formattedPreferences;
} }
/**
* Get some notifications. It will try to use the new WS if available.
*
* @param notifications Current list of loaded notifications. It's used to calculate the offset.
* @param options Other options.
* @return Promise resolved with notifications and if can load more.
*/
async getNotifications(
notifications: AddonNotificationsAnyNotification[],
options?: AddonNotificationsHelperGetNotificationsOptions,
): Promise<{notifications: AddonNotificationsAnyNotification[]; canLoadMore: boolean}> {
notifications = notifications || [];
options = options || {};
options.limit = options.limit || AddonNotificationsProvider.LIST_LIMIT;
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
if (options.onlyPopupNotifications) {
return AddonNotifications.getPopupNotifications(notifications.length, options);
}
// Use get_messages. We need 2 calls, one for read and the other one for unread.
const unreadFrom = notifications.reduce((total, current) => total + (current.read ? 0 : 1), 0);
const unread = await AddonNotifications.getUnreadNotifications(unreadFrom, options);
let newNotifications = unread;
if (unread.length < options.limit) {
// Limit not reached. Get read notifications until reach the limit.
const readLimit = options.limit - unread.length;
const readFrom = notifications.length - unreadFrom;
const readOptions = Object.assign({}, options, { limit: readLimit });
try {
const read = await AddonNotifications.getReadNotifications(readFrom, readOptions);
newNotifications = unread.concat(read);
} catch (error) {
if (unread.length <= 0) {
throw error;
}
}
}
return {
notifications: newNotifications,
canLoadMore: notifications.length >= options.limit,
};
}
/** /**
* Get a certain processor from a list of processors. * Get a certain processor from a list of processors.
* *
@ -207,10 +151,3 @@ export type AddonNotificationsPreferencesNotificationFormatted = AddonNotificati
export type AddonNotificationsPreferencesProcessorFormatted = AddonNotificationsPreferencesProcessor & { export type AddonNotificationsPreferencesProcessorFormatted = AddonNotificationsPreferencesProcessor & {
supported?: boolean; // Calculated in the app. Whether the processor is supported in the app. supported?: boolean; // Calculated in the app. Whether the processor is supported in the app.
}; };
/**
* Options to pass to getNotifications.
*/
export type AddonNotificationsHelperGetNotificationsOptions = AddonNotificationsGetNotificationsOptions & {
onlyPopupNotifications?: boolean; // Whether to get only popup notifications.
};

View File

@ -22,6 +22,7 @@ import { CoreUser } from '@features/user/services/user';
import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
const ROOT_CACHE_KEY = 'mmaNotifications:'; const ROOT_CACHE_KEY = 'mmaNotifications:';
@ -46,24 +47,14 @@ export class AddonNotificationsProvider {
* Function to format notification data. * Function to format notification data.
* *
* @param notifications List of notifications. * @param notifications List of notifications.
* @param read Whether the notifications are read or unread.
* @return Promise resolved with notifications. * @return Promise resolved with notifications.
*/ */
protected async formatNotificationsData( protected async formatNotificationsData(
notifications: AddonNotificationsGetMessagesMessage[], notifications: AddonNotificationsNotificationMessage[],
read?: boolean, ): Promise<AddonNotificationsNotificationMessageFormatted[]> {
): Promise<AddonNotificationsGetMessagesMessageFormatted[]>;
protected async formatNotificationsData(
notifications: AddonNotificationsPopupNotification[],
read?: boolean,
): Promise<AddonNotificationsPopupNotificationFormatted[]>;
protected async formatNotificationsData(
notifications: (AddonNotificationsGetMessagesMessage | AddonNotificationsPopupNotification)[],
read?: boolean,
): Promise<AddonNotificationsAnyNotification[]> {
const promises = notifications.map(async (notificationRaw) => { const promises = notifications.map(async (notificationRaw) => {
const notification = <AddonNotificationsAnyNotification> notificationRaw; const notification = <AddonNotificationsNotificationMessageFormatted> notificationRaw;
// Set message to show. // Set message to show.
if (notification.component && notification.component == 'mod_forum') { if (notification.component && notification.component == 'mod_forum') {
@ -75,9 +66,7 @@ export class AddonNotificationsProvider {
notification.moodlecomponent = notification.component; notification.moodlecomponent = notification.component;
notification.notification = 1; notification.notification = 1;
notification.notif = 1; notification.notif = 1;
if (typeof read != 'undefined') { notification.read = notification.timeread > 0;
notification.read = read;
}
if (typeof notification.customdata == 'string') { if (typeof notification.customdata == 'string') {
notification.customdata = CoreTextUtils.parseJSON<Record<string, unknown>>(notification.customdata, {}); notification.customdata = CoreTextUtils.parseJSON<Record<string, unknown>>(notification.customdata, {});
@ -93,6 +82,15 @@ export class AddonNotificationsProvider {
} }
} }
if (!notification.iconurl) {
// The iconurl is only returned in 4.0 or above. Calculate it if not present.
if (notification.component && notification.component.startsWith('mod_')) {
notification.iconurl = await CoreCourseModuleDelegate.getModuleIconSrc(
notification.component.replace('mod_', ''),
);
}
}
if (notification.useridfrom > 0) { if (notification.useridfrom > 0) {
// Try to get the profile picture of the user. // Try to get the profile picture of the user.
try { try {
@ -153,32 +151,99 @@ export class AddonNotificationsProvider {
return ROOT_CACHE_KEY + 'list'; return ROOT_CACHE_KEY + 'list';
} }
/**
* Get some notifications.
*
* @param notifications Current list of loaded notifications. It's used to calculate the offset.
* @param options Other options.
* @return Promise resolved with notifications and if can load more.
*/
async getNotifications(
notifications: AddonNotificationsNotificationMessageFormatted[],
options?: AddonNotificationsGetNotificationsOptions,
): Promise<{notifications: AddonNotificationsNotificationMessageFormatted[]; canLoadMore: boolean}> {
notifications = notifications || [];
options = options || {};
options.limit = options.limit || AddonNotificationsProvider.LIST_LIMIT;
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
let newNotifications: AddonNotificationsNotificationMessageFormatted[];
// Request 1 more notification so we can know if there are more notifications.
const originalLimit = options.limit;
options.limit + 1;
const site = await CoreSites.getSite(options.siteId);
if (site.isVersionGreaterEqualThan('4.0')) {
// In 4.0 the app can request read and unread at the same time.
options.offset = notifications.length;
newNotifications = await this.getNotificationsWithStatus(
AddonNotificationsGetReadType.BOTH,
options,
);
} else {
// We need 2 calls, one for read and the other one for unread.
options.offset = notifications.reduce((total, current) => total + (current.read ? 0 : 1), 0);
const unread = await this.getNotificationsWithStatus(AddonNotificationsGetReadType.UNREAD, options);
newNotifications = unread;
if (unread.length < options.limit) {
// Limit not reached. Get read notifications until reach the limit.
const readOptions = {
...options,
offset: notifications.length - options.offset,
limit: options.limit - unread.length,
};
try {
const read = await this.getNotificationsWithStatus(AddonNotificationsGetReadType.READ, readOptions);
newNotifications = unread.concat(read);
} catch (error) {
if (unread.length <= 0) {
throw error;
}
}
}
}
return {
notifications: newNotifications.slice(0, originalLimit),
canLoadMore: newNotifications.length > originalLimit,
};
}
/** /**
* Get notifications from site. * Get notifications from site.
* *
* @param read True if should get read notifications, false otherwise. * @param read True if should get read notifications, false otherwise.
* @param offset Position of the first notification to get.
* @param options Other options. * @param options Other options.
* @return Promise resolved with notifications. * @return Promise resolved with notifications.
*/ */
async getNotifications( protected async getNotificationsWithStatus(
read: boolean, read: AddonNotificationsGetReadType,
offset: number, options: AddonNotificationsGetNotificationsOptions = {},
options?: AddonNotificationsGetNotificationsOptions, ): Promise<AddonNotificationsNotificationMessageFormatted[]> {
): Promise<AddonNotificationsGetMessagesMessageFormatted[]> { options.offset = options.offset || 0;
options = options || {};
options.limit = options.limit || AddonNotificationsProvider.LIST_LIMIT; options.limit = options.limit || AddonNotificationsProvider.LIST_LIMIT;
this.logger.debug(`Get ${(read ? 'read' : 'unread')} notifications from ${offset}. Limit: ${options.limit}`); const typeText = read === AddonNotificationsGetReadType.READ ?
'read' :
(read === AddonNotificationsGetReadType.UNREAD ? 'unread' : 'read and unread');
this.logger.debug(`Get ${typeText} notifications from ${options.offset}. Limit: ${options.limit}`);
const site = await CoreSites.getSite(options.siteId); const site = await CoreSites.getSite(options.siteId);
const data: AddonNotificationsGetMessagesWSParams = { const data: AddonNotificationsGetMessagesWSParams = {
useridto: site.getUserId(), useridto: site.getUserId(),
useridfrom: 0, useridfrom: 0,
type: 'notifications', type: 'notifications',
read: !!read, read: read,
newestfirst: true, newestfirst: true,
limitfrom: offset, limitfrom: options.offset,
limitnum: options.limit, limitnum: options.limit,
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
@ -191,78 +256,7 @@ export class AddonNotificationsProvider {
const notifications = response.messages; const notifications = response.messages;
return this.formatNotificationsData(notifications, read); return this.formatNotificationsData(notifications);
}
/**
* Get notifications from site using the new WebService.
*
* @param offset Position of the first notification to get.
* @param options Other options.
* @return Promise resolved with notifications and if can load more.
*/
async getPopupNotifications(
offset: number,
options?: AddonNotificationsGetNotificationsOptions,
): Promise<{notifications: AddonNotificationsPopupNotificationFormatted[]; canLoadMore: boolean}> {
options = options || {};
options.limit = options.limit || AddonNotificationsProvider.LIST_LIMIT;
this.logger.debug(`Get popup notifications from ${offset}. Limit: ${options.limit}`);
const site = await CoreSites.getSite(options.siteId);
const data: AddonNotificationsPopupGetPopupNotificationsWSParams = {
useridto: site.getUserId(),
newestfirst: true,
offset,
limit: options.limit + 1, // Get one more to calculate canLoadMore.
};
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getNotificationsCacheKey(),
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
// Get notifications.
const response = await site.read<AddonNotificationsGetPopupNotificationsResult>(
'message_popup_get_popup_notifications',
data,
preSets,
);
const notifications = await this.formatNotificationsData(response.notifications.slice(0, options.limit));
return {
canLoadMore: response.notifications.length > options.limit,
notifications,
};
}
/**
* Get read notifications from site.
*
* @param offset Position of the first notification to get.
* @param options Other options.
* @return Promise resolved with notifications.
*/
getReadNotifications(
offset: number,
options?: AddonNotificationsGetNotificationsOptions,
): Promise<AddonNotificationsGetMessagesMessageFormatted[]> {
return this.getNotifications(true, offset, options);
}
/**
* Get unread notifications from site.
*
* @param offset Position of the first notification to get.
* @param options Other options.
* @return Promise resolved with notifications.
*/
getUnreadNotifications(
offset: number,
options?: AddonNotificationsGetNotificationsOptions,
): Promise<AddonNotificationsGetMessagesMessageFormatted[]> {
return this.getNotifications(false, offset, options);
} }
/** /**
@ -272,26 +266,65 @@ export class AddonNotificationsProvider {
* @param siteId Site ID. If not defined, use current site. * @param siteId Site ID. If not defined, use current site.
* @return Promise resolved with the message notifications count. * @return Promise resolved with the message notifications count.
*/ */
async getUnreadNotificationsCount(userId?: number, siteId?: string): Promise<number> { async getUnreadNotificationsCount(userId?: number, siteId?: string): Promise<{ count: number; hasMore: boolean} > {
const site = await CoreSites.getSite(siteId); const site = await CoreSites.getSite(siteId);
userId = userId || site.getUserId(); // @since 4.0
const params: AddonNotificationsPopupGetUnreadPopupNotificationCountWSParams = { if (site.wsAvailable('core_message_get_unread_notification_count')) {
useridto: userId, const params: CoreMessageGetUnreadNotificationCountWSParams = {
}; useridto: userId || site.getUserId(),
const preSets: CoreSiteWSPreSets = { };
getFromCache: false,
emergencyCache: false,
saveToCache: false,
typeExpected: 'number',
};
try { const preSets: CoreSiteWSPreSets = {
return await site.read<number>('message_popup_get_unread_popup_notification_count', params, preSets); cacheKey: this.getUnreadNotificationsCountCacheKey(params.useridto),
} catch { getFromCache: false, // Always try to get the latest number.
// Return no messages if the call fails. typeExpected: 'number',
return 0; };
try {
const count = await site.read<number>('core_message_get_unread_notification_count', params, preSets);
return {
count,
hasMore: false,
};
} catch {
// Return no notifications if the call fails.
return {
count: 0,
hasMore: false,
};
}
} }
// Fallback call
try {
const unread = await this.getNotificationsWithStatus(AddonNotificationsGetReadType.UNREAD, {
limit: AddonNotificationsProvider.LIST_LIMIT + 1,
siteId,
});
return {
count: Math.min(unread.length, AddonNotificationsProvider.LIST_LIMIT),
hasMore: unread.length > AddonNotificationsProvider.LIST_LIMIT,
};
} catch {
// Return no notifications if the call fails.
return {
count: 0,
hasMore: false,
};
}
}
/**
* Get cache key for unread notifications count WS calls.
*
* @param userId User ID.
* @return Cache key.
*/
protected getUnreadNotificationsCountCacheKey(userId: number): string {
return `${ROOT_CACHE_KEY}count:${userId}`;
} }
/** /**
@ -427,7 +460,7 @@ export type AddonNotificationsGetMessagesWSParams = {
useridto: number; // The user id who received the message, 0 for any user. useridto: number; // The user id who received the message, 0 for any user.
useridfrom?: number; // The user id who send the message, 0 for any user. -10 or -20 for no-reply or support user. useridfrom?: number; // The user id who send the message, 0 for any user. -10 or -20 for no-reply or support user.
type?: string; // Type of message to return, expected values are: notifications, conversations and both. type?: string; // Type of message to return, expected values are: notifications, conversations and both.
read?: boolean; // True for getting read messages, false for unread. read?: AddonNotificationsGetReadType; // 0=unread, 1=read. @since 4.0 it also accepts 2=both.
newestfirst?: boolean; // True for ordering by newest first, false for oldest first. newestfirst?: boolean; // True for ordering by newest first, false for oldest first.
limitfrom?: number; // Limit from. limitfrom?: number; // Limit from.
limitnum?: number; // Limit number. limitnum?: number; // Limit number.
@ -437,14 +470,14 @@ export type AddonNotificationsGetMessagesWSParams = {
* Data returned by core_message_get_messages WS. * Data returned by core_message_get_messages WS.
*/ */
export type AddonNotificationsGetMessagesWSResponse = { export type AddonNotificationsGetMessagesWSResponse = {
messages: AddonNotificationsGetMessagesMessage[]; messages: AddonNotificationsNotificationMessage[];
warnings?: CoreWSExternalWarning[]; warnings?: CoreWSExternalWarning[];
}; };
/** /**
* Message data returned by core_message_get_messages. * Message data returned by core_message_get_messages.
*/ */
export type AddonNotificationsGetMessagesMessage = { export type AddonNotificationsNotificationMessage = {
id: number; // Message id. id: number; // Message id.
useridfrom: number; // User from id. useridfrom: number; // User from id.
useridto: number; // User to id. useridto: number; // User to id.
@ -464,70 +497,14 @@ export type AddonNotificationsGetMessagesMessage = {
component?: string; // @since 3.7. The component that generated the notification. component?: string; // @since 3.7. The component that generated the notification.
eventtype?: string; // @since 3.7. The type of notification. eventtype?: string; // @since 3.7. The type of notification.
customdata?: string; // @since 3.7. Custom data to be passed to the message processor. customdata?: string; // @since 3.7. Custom data to be passed to the message processor.
iconurl?: string; // @since 4.0. Icon URL, only for notifications.
}; };
/** /**
* Message data returned by core_message_get_messages with some calculated data. * Message data returned by core_message_get_messages with some calculated data.
*/ */
export type AddonNotificationsGetMessagesMessageFormatted = export type AddonNotificationsNotificationMessageFormatted =
Omit<AddonNotificationsGetMessagesMessage, 'customdata'> & AddonNotificationsNotificationCalculatedData; Omit<AddonNotificationsNotificationMessage, 'customdata'> & AddonNotificationsNotificationCalculatedData;
/**
* Params of message_popup_get_popup_notifications WS.
*/
export type AddonNotificationsPopupGetPopupNotificationsWSParams = {
useridto: number; // The user id who received the message, 0 for current user.
newestfirst?: boolean; // True for ordering by newest first, false for oldest first.
limit?: number; // The number of results to return.
offset?: number; // Offset the result set by a given amount.
};
/**
* Result of WS message_popup_get_popup_notifications.
*/
export type AddonNotificationsGetPopupNotificationsResult = {
notifications: AddonNotificationsPopupNotification[];
unreadcount: number; // The number of unread message for the given user.
};
/**
* Notification returned by message_popup_get_popup_notifications.
*/
export type AddonNotificationsPopupNotification = {
id: number; // Notification id (this is not guaranteed to be unique within this result set).
useridfrom: number; // User from id.
useridto: number; // User to id.
subject: string; // The notification subject.
shortenedsubject: string; // The notification subject shortened with ellipsis.
text: string; // The message text formated.
fullmessage: string; // The message.
fullmessageformat: number; // Fullmessage format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
fullmessagehtml: string; // The message in html.
smallmessage: string; // The shorten message.
contexturl: string; // Context URL.
contexturlname: string; // Context URL link name.
timecreated: number; // Time created.
timecreatedpretty: string; // Time created in a pretty format.
timeread: number; // Time read.
read: boolean; // Notification read status.
deleted: boolean; // Notification deletion status.
iconurl: string; // URL for notification icon.
component?: string; // The component that generated the notification.
eventtype?: string; // The type of notification.
customdata?: string; // @since 3.7. Custom data to be passed to the message processor.
};
/**
* Notification returned by message_popup_get_popup_notifications.
*/
export type AddonNotificationsPopupNotificationFormatted =
Omit<AddonNotificationsPopupNotification, 'customdata'> & AddonNotificationsNotificationCalculatedData;
/**
* Any kind of notification that can be retrieved.
*/
export type AddonNotificationsAnyNotification =
AddonNotificationsPopupNotificationFormatted | AddonNotificationsGetMessagesMessageFormatted;
/** /**
* Result of WS core_message_get_user_notification_preferences. * Result of WS core_message_get_user_notification_preferences.
@ -552,13 +529,6 @@ export type AddonNotificationsNotificationCalculatedData = {
customdata?: Record<string, unknown>; // Parsed custom data. customdata?: Record<string, unknown>; // Parsed custom data.
}; };
/**
* Params of message_popup_get_unread_popup_notification_count WS.
*/
export type AddonNotificationsPopupGetUnreadPopupNotificationCountWSParams = {
useridto: number; // The user id who received the message, 0 for any user.
};
/** /**
* Params of core_message_mark_all_notifications_as_read WS. * Params of core_message_mark_all_notifications_as_read WS.
*/ */
@ -585,8 +555,25 @@ export type CoreMessageMarkNotificationReadWSResponse = {
}; };
/** /**
* Options to pass to getNotifications and getPopupNotifications. * Params of core_message_get_unread_notification_count WS.
*/
export type CoreMessageGetUnreadNotificationCountWSParams = {
useridto: number; // User id who received the notification, 0 for any user.
};
/**
* Options to pass to getNotifications.
*/ */
export type AddonNotificationsGetNotificationsOptions = CoreSitesCommonWSOptions & { export type AddonNotificationsGetNotificationsOptions = CoreSitesCommonWSOptions & {
offset?: number; // Offset to use. Defaults to 0.
limit?: number; // Number of notifications to get. Defaults to LIST_LIMIT. limit?: number; // Number of notifications to get. Defaults to LIST_LIMIT.
}; };
/**
* Constants to get either read, unread or both notifications.
*/
export enum AddonNotificationsGetReadType {
UNREAD = 0,
READ = 1,
BOTH = 2,
}

View File

@ -86,6 +86,7 @@ export class CoreSite {
'3.9': 2020061500, '3.9': 2020061500,
'3.10': 2020110900, '3.10': 2020110900,
'3.11': 2021051700, '3.11': 2021051700,
'4.0': 2021100300, // @todo [4.0] replace with right value when released. Using a tmp value to be able to test new things.
}; };
// Possible cache update frequencies. // Possible cache update frequencies.