/**
* Gestion des notifications dans le Bnum
* La gestion est indépendante des refresh Roundcube
* pour en faire plus régulièrement
*/
var current_desktop_notification = 0;
/**
* @typedef MelNotification
* @property {string} category
* @property {string} content
* @property {number} created
* @property {string} event
* @property {boolean} isread
* @property {boolean} local
* @property {number} modified
* @property {string} title
* @property {string} uid
*/
// Initialise les notifications et lance le timeout
// Pas de traitement si on est pas dans la metapage
if (window.rcmail) {
// Initialisation du js
rcmail.addEventListener('init', function () {
if (window == top) {
// On est dans la metapage traitement global
let notificationstack = document.getElementById('notificationstack');
let notificationunread = document.getElementById('notificationunread');
// Ajout du panneau de notification
if (!notificationstack) {
notificationstack = document.createElement('div');
notificationstack.id = 'notificationstack';
document.getElementById('layout').append(notificationstack);
}
// Ajout du nombre de notification non lues
if (!notificationunread) {
notificationunread = document.createElement('div');
notificationunread.id = 'notificationunread';
document
.querySelector('#notifications-icon')
.append(notificationunread);
}
// Initialisation de la current
current_desktop_notification = 0;
// Afficher les notifications depuis le storage
setTimeout(() => {
// Lancement des notifications
m_mp_NotificationStartup();
}, 500);
// Gérer les notifications venant des autres frames
window.addEventListener(
'message',
(event) => {
if (
event.data &&
event.data.type &&
event.data.type == 'notification'
) {
m_mp_NotificationRun(event.data.notification);
}
},
false,
);
// Tout passer en lu à la fermeture
if (rcmail.env.notifications_set_read_on_panel_close) {
$('#notification-dropdown').on('hide.bs.dropdown', function () {
let notifications = m_mp_NotificationsGet(),
uids = [];
for (const uid in notifications) {
if (Object.hasOwnProperty.call(notifications, uid)) {
if (!notifications[uid].isread) {
uids.push(btoa(uid));
}
}
}
m_mp_NotificationsAction('read', uids);
});
}
}
// Ajouter le support des autres applications qui envoi des notifications
rcmail.addEventListener('plugin.push_notification', m_mp_NotificationRun);
});
// Action plugin.notifications_refresh
rcmail.addEventListener(
'responseafterplugin.notifications_refresh',
function (evt) {
if (evt.response.notifications.length) {
// Récupération des notifications du storage
let notifications = m_mp_NotificationsGet(),
newNotifications = {};
// Initialisation de la current
current_desktop_notification = 0;
for (const notification of evt.response.notifications) {
if (!notifications[notification.uid] && !notification.isread) {
// On ne fait poper que les nouvelles notifications
m_mp_ShowNotification(notification);
// Ajoute la notification à la liste des nouvelles notifications
newNotifications[notification.uid] = notification;
} else if (notifications[notification.uid]) {
notifications[notification.uid].isread = notification.isread;
notifications[notification.uid].todelete = false;
} else if (
m_mp_NotificationSettings('notifications_center', notification)
) {
// Ajoute la notification à la liste des nouvelles notifications
newNotifications[notification.uid] = notification;
}
}
// Merge les notifications
m_mp_NotificationsMerge(
m_mp_NotificationsDelete(notifications),
newNotifications,
);
} else {
// Rafraichir les notifications du panel pour actualiser les dates
m_mp_NotificationsAppendToPanel(m_mp_NotificationsGet());
}
// Positionne le last dans le storage
rcmail.mel_storage_set('notification_last', evt.response.last);
// Relance du process des notifications
m_mp_NotificationProcess();
},
);
// Action plugin.notifications_action
rcmail.addEventListener(
'responseafterplugin.notifications_action',
function (evt) {
if (evt.response.success) {
// Lancement du traitement
m_mp_NotificationProcessAfterAction(
m_mp_NotificationsGet(),
evt.response.uids,
evt.response.act,
);
}
},
);
}
/**
* Retourne les notifications depuis le storage
*
* @returns notifications
*/
function m_mp_NotificationsGet() {
// Récupération des notifications du storage
let notifications = rcmail.mel_storage_get('notifications', true);
return notifications ?? {};
}
/**
* Enregistre les notifications dans le storage
*
* @param {*} notifications
*/
function m_mp_NotificationsSet(notifications) {
rcmail.mel_storage_set('notifications', notifications, true);
}
/**
* Lancement de la mécanique des notifications
*/
function m_mp_NotificationStartup() {
// Récupération et nettoyage des notifications du storage
let notifications = m_mp_NotificationsClean(m_mp_NotificationsGet());
// Affiche les notifications dans le panel
m_mp_NotificationsAppendToPanel(notifications);
// Filtrer les notifications au démarrage
// m_mp_NotificationFilter();
// Lance le refresh immédiatement
m_mp_NotificationRefresh();
}
/**
* Nettoyage des notifications au démarrage
*
* @param {*} notifications
* @returns
*/
function m_mp_NotificationsClean(notifications) {
let hasChanged = false;
// Parcourir les notifications et ne garder que les locales
for (const uid in notifications) {
if (Object.hasOwnProperty.call(notifications, uid)) {
if (!notifications[uid].local) {
notifications[uid].todelete = true;
hasChanged = true;
}
}
}
// On enregistre les modifications dans le storage
if (hasChanged) {
m_mp_NotificationsSet(notifications);
}
// Nettoyage du last
rcmail.mel_storage_remove('notification_last');
return notifications;
}
/**
* Supprime les notifications à supprimer
*
* @param {*} notifications
* @returns
*/
function m_mp_NotificationsDelete(notifications) {
for (const uid in notifications) {
if (
Object.hasOwnProperty.call(notifications, uid) &&
notifications[uid].todelete
) {
delete notifications[uid];
}
}
return notifications;
}
/**
* Lancer une notification indirecte (ne passe pas par les notifications Bnum)
*
* @param {*} notification
*/
function m_mp_NotificationRun(notification) {
// Est-ce qu'on est dans la metapage
if (window == top) {
// Récupération des notifications du storage
let notifications = m_mp_NotificationsGet(),
newNotifications = {};
if (
!notifications[notification.uid] &&
!notification.isread &&
!notification.isdeleted
) {
// On ne fait poper que les nouvelles notifications
m_mp_ShowNotification(notification);
}
// Si la notification est déjà dans la liste
if (notifications[notification.uid]) {
notifications[notification.uid].isread = notification.isread;
notifications[notification.uid].modified = notification.modified;
notifications = m_mp_NotificationsSort(notifications);
// Actualiser les non lues et ajouter dans le panel
m_mp_NotificationsAppendToPanel(notifications);
// Filtrer les notifications si besoin
// m_mp_NotificationFilter();
// Enregistre les notifications dans le storage
m_mp_NotificationsSet(notifications);
} else if (
m_mp_NotificationSettings('notifications_center', notification)
) {
// Ajoute la notification à la liste des nouvelles notifications
newNotifications[notification.uid] = notification;
// Merge les notifications
m_mp_NotificationsMerge(notifications, newNotifications);
}
} else {
top.m_mp_NotificationRun(notification);
}
}
/**
* Merge les nouvelles notifications avec les anciennes et met dans le storage
*
* @param {*} notifications
* @param {*} newNotifications
*/
function m_mp_NotificationsMerge(notifications, newNotifications) {
// Ajoute les nouvelles notifications avant les anciennes en les triant
notifications = m_mp_NotificationsSort({
...newNotifications,
...notifications,
});
// Actualiser les non lues et ajouter dans le panel
m_mp_NotificationsAppendToPanel(notifications);
// Filtrer les notifications si besoin
// m_mp_NotificationFilter();
// Enregistre les notifications dans le storage
m_mp_NotificationsSet(notifications);
}
/**
* Tri les notifications par modified
*
* @param {*} notifications
*/
function m_mp_NotificationsSort(notifications) {
// Compatible uniquement ES10
return Object.fromEntries(
Object.entries(notifications).sort((a, b) => {
return b[1].modified - a[1].modified;
}),
);
}
/**
* Process de gestion des notifications
* Génère un timeout et le nettoie si nécessaire
*/
function m_mp_NotificationProcess() {
if (rcmail.env.notification_timeout) {
clearTimeout(rcmail.env.notification_timeout);
}
rcmail.env.notification_timeout = setTimeout(() => {
m_mp_NotificationRefresh();
}, rcmail.env.notifications_refresh_interval * 1000);
}
/**
* Rafraichissement de la liste des notifications en XHR
*/
function m_mp_NotificationRefresh() {
rcmail.http_get('plugin.notifications_refresh', {
_last: rcmail.mel_storage_get('notification_last'),
});
}
/**
* Récupère les paramètres pour la notification et la key
*
* @param {*} key
* @param {*} notification
* @returns boolean
*/
function m_mp_NotificationSettings(key, notification) {
if (rcmail.env.notifications_settings[notification.category]) {
const settings = rcmail.env.notifications_settings[notification.category];
// Si on ne doit pas afficher la notification dans le centre de notification
if (settings[key] === false) {
return false;
} else if (
notification.category == 'mail' &&
settings['mailboxes'] &&
settings['mailboxes'][notification.mailbox] &&
settings['mailboxes'][notification.mailbox][key] === false
) {
// Paramètre spécifique pour la mailbox
return false;
}
}
return true;
}
/**
* Affichage d'une notification
*
* @param {MelNotification} notification
*/
function m_mp_ShowNotification(notification) {
// Gérer les notifications multiples
setTimeout(() => {
if (m_mp_NotificationSettings('inside_notification', notification)) {
let notificationstack = document.getElementById('notificationstack'),
article = m_mp_NotificationGetElement(notification, false);
// Ajoute la notification à la stack
notificationstack.append(article);
// Timeout pour enlever la notification
setTimeout(() => {
article.remove();
}, rcmail.env.notifications_show_duration * 1000);
}
// Envoyer la notification sur le desktop
m_mp_ShowDesktopNotification(notification);
switch (notification.category) {
case 'mail':
if (rcmail.env.notifications_sound_on_new_mail) PlaySound();
break;
default:
break;
}
}, current_desktop_notification++ * 1000);
}
function PlaySound(sound = 'sound', ext = 'mp3') {
var audio = new Audio(
window.location.origin +
window.location.pathname +
`/plugins/mel_notification/${sound}.${ext}`,
);
audio.addEventListener('ended', () => {
audio.remove();
audio = null;
});
audio.play();
}
/**
* Affiche une notification sur le bureau
*
* @param {MelNotification} notification
*/
function m_mp_ShowDesktopNotification(notification) {
if (m_mp_NotificationSettings('desktop_notification', notification)) {
let timeout = rcmail.env.notifications_desktop_duration || 10;
icon =
rcmail.env.notifications_icons[notification.category] ??
rcmail.env.notifications_icons['default'];
// Si l'utilisateur a permis les notifications
if (window.Notification && Notification.permission === 'granted') {
var n = new Notification(notification.title, {
dir: 'auto',
lang: '',
body: notification.content,
tag: 'mel_notification',
icon: rcmail.assets_path(icon),
});
n.onclick = () => {
window.focus();
};
setTimeout(() => {
n.close();
}, timeout * 1000);
} else {
Notification.requestPermission();
}
}
}
/**
* Lance une action en XHR sur les uids
*
* @param {string} action
* @param {*} uids
*/
function m_mp_NotificationsAction(action, uids) {
// Récupération des notifications du storage
let notifications = m_mp_NotificationsGet();
// Recherche les uid de notification locale
let localUids = [],
remoteUids = [];
for (const uid of uids) {
const clearUid = atob(uid);
if (notifications[clearUid]) {
if (notifications[clearUid].local) {
localUids.push(clearUid);
} else {
remoteUids.push(uid);
}
}
}
// Si on a des uids locaux
if (localUids.length) {
m_mp_NotificationProcessAfterAction(notifications, localUids, action);
}
// Si on a des uids serveur
if (remoteUids.length) {
// Lance la requête XHR
rcmail.http_post(
'plugin.notifications_action',
{
_act: action,
_uids: remoteUids,
},
rcmail.display_message(rcmail.get_label('loading'), 'loading'),
);
}
}
/**
* Traitement des notifications après l'action
*
* @param {*} notifications
* @param {*} uids
* @param {*} action
*/
function m_mp_NotificationProcessAfterAction(notifications, uids, action) {
for (const uid of uids) {
if (notifications[uid]) {
let object = document.querySelector('#notif' + uid.replace(/\W/g, '_'));
if (!object) {
continue;
}
// Traitement de l'action
switch (action) {
case 'read':
notifications[uid].isread = true;
object.className = object.className.replace(/ unread/g, '');
// object.querySelector('a.button.read').textContent = rcmail.get_label('mel_notification.Mark as unread');
// object.querySelector('a.button.read').title = rcmail.get_label('mel_notification.Mark as unread title');
object.title = rcmail.get_label(
'mel_notification.Mark as unread title',
);
break;
case 'unread':
notifications[uid].isread = false;
if (object.className.indexOf('unread') === -1) {
object.className += ' unread';
// object.querySelector('a.button.read').textContent = rcmail.get_label('mel_notification.Mark as read');
// object.querySelector('a.button.read').title = rcmail.get_label('mel_notification.Mark as read title');
object.title = rcmail.get_label(
'mel_notification.Mark as read title',
);
}
break;
case 'del':
if (notifications[uid].rizomo) {
notifications[uid].isdeleted = true;
} else {
delete notifications[uid];
}
object.remove();
break;
}
rcmail.triggerEvent('mel_notification.action.after', {
notification: notifications[uid],
action,
});
}
}
// Actualiser les non lues
m_mp_NotificationsRefreshUnread(notifications);
// Filtrer les notifications
// m_mp_NotificationFilter();
// Enregistre les notifications dans le storage
m_mp_NotificationsSet(notifications);
}
/**
* Affichage du nombre de non lus dans le Bienvenue
* @param {*} unread
*/
function m_mp_NotificationsShowUnread(unread) {
let notificationunread = document.getElementById('notificationunread');
// Afficher les non lues ou non
if (unread) {
notificationunread.className = 'active';
notificationunread.textContent = unread;
notificationunread.title =
unread === 1
? rcmail.get_label('mel_notification.Unread notification')
: rcmail
.get_label('mel_notification.X unread notifications')
.replace(/%d/, unread);
} else {
notificationunread.className = '';
notificationunread.textContent = '';
notificationunread.title = '';
}
}
/**
* Parcours les notifications pour donner les non lues
*
* @param {*} notifications
*/
function m_mp_NotificationsRefreshUnread(notifications) {
let unread = 0,
unreadCat = [];
for (const uid in notifications) {
if (Object.hasOwnProperty.call(notifications, uid)) {
const notification = notifications[uid];
// Gérer les paramètres du centre de notification et les deleted
if (
!m_mp_NotificationSettings('notifications_center', notification) ||
notification.isdeleted
) {
continue;
}
if (!notification.isread) {
unread++;
if (!unreadCat[notification.category]) {
unreadCat[notification.category] = 0;
}
unreadCat[notification.category]++;
}
}
}
// Actualiser les catégories du select
for (const category in rcmail.env.notifications_categories) {
if (
Object.hasOwnProperty.call(rcmail.env.notifications_categories, category)
) {
let option = document.querySelector(
'#notifications-panel .filters select option[value="' + category + '"]',
);
if (option) {
if (unreadCat[category]) {
option.text =
rcmail.env.notifications_categories[category] +
' (' +
unreadCat[category] +
')';
} else {
option.text = rcmail.env.notifications_categories[category];
}
}
}
}
// Afficher les non lues ou non
m_mp_NotificationsShowUnread(unread);
}
/**
* Ajoute la liste des notifications au panel
*
* @param {*} notifications
*/
function m_mp_NotificationsAppendToPanel(notifications) {
// Ajouter un element
let e = (className, ...elements) => {
let elem = document.createElement('div');
elem.className = className;
elem.append(...elements);
return elem;
};
let unread = 0,
unreadCat = [],
notificationspanel = document.getElementById('notifications-panel');
// Création initiale
if (notificationspanel.innerHTML == '') {
notificationspanel.append(
m_mp_NotificationsAppendFilters(),
e('dropdown-menu-scroll', e('content')),
);
}
let content = notificationspanel.querySelector('.content');
// Nettoie le notifications panel pour le refresh
content.innerHTML = '';
for (const uid in notifications) {
if (Object.hasOwnProperty.call(notifications, uid)) {
const notification = notifications[uid];
// Gérer les paramètres du centre de notification et les deleted
if (
!m_mp_NotificationSettings('notifications_center', notification) ||
notification.isdeleted
) {
continue;
}
if (!notification.isread) {
unread++;
if (!unreadCat[notification.category]) {
unreadCat[notification.category] = 0;
}
unreadCat[notification.category]++;
}
content.append(m_mp_NotificationGetElement(notification));
}
}
// Actualiser les catégories du select
for (const category in rcmail.env.notifications_categories) {
if (
Object.hasOwnProperty.call(rcmail.env.notifications_categories, category)
) {
let option = document.querySelector(
'#notifications-panel .filters select option[value="' + category + '"]',
);
if (option) {
if (unreadCat[category]) {
option.text =
rcmail.env.notifications_categories[category] +
' (' +
unreadCat[category] +
')';
} else {
option.text = rcmail.env.notifications_categories[category];
}
}
}
}
// Afficher les non lues ou non
m_mp_NotificationsShowUnread(unread);
}
/**
* Génère les filtres sur les notifications
*/
function m_mp_NotificationsAppendFilters() {
// Ajouter un element
let e = (className, ...elements) => {
let elem = document.createElement('div');
elem.className = className;
elem.append(...elements);
return elem;
};
// Ajouter un element
let t = (className, textContent) => {
let elem = document.createElement('h6'),
span = document.createElement('span');
elem.className = className;
span.className = 'font-weight-bold blue-color text-center';
span.textContent = textContent;
elem.append(span);
return elem;
};
// Création d'un bouton
let b = (
href,
className,
textContent,
title,
iconContent = null,
onclick = null,
newtab = false,
) => {
let button = document.createElement('a'),
span = document.createElement('span'),
icon = document.createElement('span');
button.className =
className + ' transparent-icon-button dropdown-header-button';
button.href = href;
button.textContent = textContent;
button.title = title;
if (onclick) {
button.onclick = onclick;
}
if (newtab) {
button.target = '_blank';
}
span.className = 'filters_button';
if (iconContent) {
icon.className = 'material-symbols-outlined blue-color';
icon.textContent = iconContent;
button.append(icon);
}
span.append(button);
return span;
};
//Icons
let settings = document.createElement('span'),
delete_all = document.createElement('span');
settings.className =
'material-symbols-outlined fw-300 blue-color text-center';
settings.innerText = 'settings';
delete_all.className = 'material-symbols-outlined fw-300 blue-color';
delete_all.innerText = 'delete';
// Select
let select = document.createElement('select'),
option = document.createElement('option');
text = document.createElement('p');
select.className =
'categories input-mel mel-input custom-select pretty-select';
select.setAttribute('aria-labelledby', 'mel-notification-title');
text.className = 'mb-0 notification-header-size';
// All categories
option.value = 'all';
option.text = rcmail.get_label('mel_notification.all');
select.add(option);
// Parcourir les categories de filtre
for (const key in rcmail.env.notifications_categories) {
if (Object.hasOwnProperty.call(rcmail.env.notifications_categories, key)) {
if (rcmail.env.notifications_settings[key]) {
// Si on ne doit pas afficher la catégorie dans le centre de notification
if (
rcmail.env.notifications_settings[key]['notifications_center'] ===
false
) {
continue;
}
}
option = document.createElement('option');
option.value = key;
option.text = rcmail.env.notifications_categories[key];
select.add(option);
}
}
// onchange event
// select.onchange = () => {
// m_mp_NotificationFilter();
// };
let title = t(
'title text-sm font-weight-normal mb-1 text-center',
rcmail.get_label('mel_notification.Notifications'),
);
title.id = 'mel-notification-title';
// Ajouter les filters
let filters = e(
'notifications-header border-radius-md px-2 mb-2',
e(
'd-flex py-1 justify-content-between mx-2',
e(
'my-auto ml-1',
b(
rcmail.url('settings/settings') + '&_open_section=notifications',
'manage',
'',
rcmail.get_label('mel_notification.Manage notifications title'),
'settings',
),
),
e('d-flex flex-column justify-content-center', title, text),
e(
'my-auto dropdown-header-button',
b(
'#',
'delete',
'',
rcmail.get_label('mel_notification.Delete all title'),
'delete',
() => {
if (
confirm(rcmail.get_label('mel_notification.Delete all confirm'))
) {
let notifications = m_mp_NotificationsGet(),
uids = [];
// filter = document.querySelector('#notifications-panel > .filters select.categories').value;
for (const uid in notifications) {
if (Object.hasOwnProperty.call(notifications, uid)) {
// if (filter == 'all' || filter == notifications[uid].category) {
uids.push(btoa(uid));
// }
}
}
m_mp_NotificationsAction('del', uids);
}
},
),
),
),
);
return filters;
}
/**
* Filtrer les notifications en fonction du select
*/
function m_mp_NotificationFilter() {
let select = document.querySelector(
'#notifications-panel > .filters select.categories',
);
if (
document.querySelector('#notifications-panel > .content > .nonotification')
)
document
.querySelector('#notifications-panel > .content > .nonotification')
.remove();
// Enlever tous les hidden
for (const article of document.querySelectorAll(
'#notifications-panel article.hidden',
)) {
article.className = article.className.replace(/ hidden/, '');
}
// Ajouter les hidden nécessaire
if (select.value != 'all') {
for (const article of document.querySelectorAll(
'#notifications-panel article:not(.' + select.value + ')',
)) {
article.className += ' hidden';
}
// Est-ce qu'on a des notifications à afficher ?
if (
!document.querySelectorAll('#notifications-panel article.' + select.value)
.length
) {
let div = document.createElement('div');
div.className = 'nonotification';
div.textContent = rcmail
.get_label('mel_notification.No notification for')
.replace(/%s/, rcmail.env.notifications_categories[select.value]);
document.querySelector('#notifications-panel > .content').append(div);
}
} else {
// Est-ce qu'on a des notifications à afficher ?
if (!document.querySelectorAll('#notifications-panel article').length) {
let div = document.createElement('div');
div.className = 'nonotification';
div.textContent = rcmail
.get_label('mel_notification.No notification')
.replace(/%s/, rcmail.env.notifications_categories[select.value]);
document.querySelector('#notifications-panel > .content').append(div);
}
}
}
/**
* Retourne une date lisible à partir du modified
*
* @param {*} created
* @returns
*/
function m_mp_NotificationGetDate(created) {
let date = new Date(created * 1000),
now = Date.now() / 1000,
text = '',
title = date.toLocaleString();
const diff = now - created;
if (diff < 120) {
// Si cela fait moins de 2 min
text = rcmail.get_label('mel_notification.now');
} else if (diff < 3600) {
// Si cela fait moins d'une heure
const min = Math.floor(diff / 60);
text = rcmail
.get_label('mel_notification.X minutes ago')
.replace(/%d/, min);
} else if (diff < 86400) {
// Si cela fait moins de 24h
const hours = Math.floor(diff / 3600);
text = rcmail
.get_label('mel_notification.X hours ago')
.replace(/%d/, hours);
} else if (diff < 604800) {
// Si cela fait moins de 7 jours
const _string = date.toString().split(' '),
day = rcmail.get_label(
'mel_notification.' + _string[0].toLocaleLowerCase(),
),
hour = _string[4].substring(0, 5);
text = rcmail
.get_label('mel_notification.last day')
.replace(/%s/, day)
.replace(/%h/, hour);
} else {
// Sinon on affiche la date
text = ` - ${title}`;
}
// Return time and title
return {
title: title,
text: text,
};
}
class html_notification extends mel_html2 {
constructor(notification, isPanel) {
super('a', {
attribs: {
id: 'notif' + notification.uid.replace(/\W/g, '_'),
class: `dropdown-item p-2 mb-2 rounded ${notification.isread ? '' : 'unread'}`,
},
});
let _icon = new mel_html(
'span',
{ class: 'material-symbols-outlined notification-icon' },
rcmail.env.notifications_material_icons[notification.category] ??
notification.category,
);
let _category = new mel_html2('h6', {
attribs: { class: 'notification-category' },
contents: [
new mel_html(
'span',
{},
rcmail.env.notifications_categories[notification.category] ??
notification.category,
),
],
});
let _title = new mel_html(
'p',
{ class: 'notification-title' },
notification.title,
);
const _action = this._getNotificationAction(notification);
// Notification dans le menu
if (isPanel) {
// Traitement de la date
let _date_info = m_mp_NotificationGetDate(notification.modified);
let _date = new mel_html(
'span',
{ class: 'date notification-date', title: _date_info.title },
[_date_info.text],
);
_category.addContent(_date);
let _button = new mel_html2('a', {
attribs: {
class: 'p-2 my-auto',
href: '#',
title: rcmail.get_label('mel_notification.Delete title'),
},
contents: [this._getButtonIcon('close')],
});
_button.onclick.push((e) => {
e.stopPropagation();
e.preventDefault();
m_mp_NotificationsAction('del', [btoa(notification.uid)]);
});
if (notification.action) {
for (const key in notification.action) {
if (Object.hasOwnProperty.call(notification.action, key)) {
const action = notification.action[key];
this.attribs['href'] = action.href ?? '#';
if (action.command || action.click) {
this.onclick.push(
function (current_action, element, e) {
if (current_action.command) {
rcmail.command(
current_action.command,
current_action.params ?? '',
e,
);
m_mp_NotificationsAction('read', [btoa(notification.uid)]);
} else if (current_action.click) {
element.click(e);
m_mp_NotificationsAction('read', [btoa(notification.uid)]);
}
e.stopPropagation();
},
action,
_action,
);
}
this.attribs['title'] = rcmail.get_label(
'mel_notification.Action title',
);
break;
}
}
}
this.addContent(
new mel_html2('div', {
attribs: { class: 'd-flex py-1' },
contents: [
_icon,
new mel_html2('div', {
attribs: {
class: 'd-flex flex-column justify-content-center w-100',
},
contents: [_category, _title],
}),
_button,
],
}),
);
}
// Notification en pop-up
else {
let _button = new mel_html2('a', {
attribs: {
class: 'p-2 my-auto',
href: _action?.href,
title: rcmail.get_label('mel_notification.Action title'),
},
contents: [this._getButtonIcon('open_in_new')],
});
_button.onclick.push(() => {
_action.command
? (e) => {
rcmail.command(_action.command, _action.params ?? '', e);
e.stopPropagation();
}
: _action.click
? (e) => {
_action.click(e);
e.stopPropagation();
}
: (e) => {
e.stopPropagation();
};
});
this.onclick.push((e) => {
e = $(e.currentTarget);
// Passer en lu ?
if (rcmail.env.notifications_set_read_on_click) {
m_mp_NotificationsAction('read', [btoa(notification.uid)]);
}
e.remove();
});
this.addContent(
new mel_html2('div', {
attribs: { class: 'd-flex py-1' },
contents: [
_icon,
new mel_html2('div', {
attribs: { class: 'd-flex flex-column justify-content-center' },
contents: [_category, _title],
}),
_button,
],
}),
);
}
}
_getButtonIcon(icon) {
return new mel_html(
'span',
{ class: 'material-symbols-outlined notification-button-icon' },
icon,
);
}
_getNotificationAction(notification) {
if (notification.action) {
for (const key in notification.action) {
if (Object.hasOwnProperty.call(notification.action, key)) {
return notification.action[key];
}
}
}
}
}
/**
* Génére un DOM element à partir d'une notification
*
* @param {*} notification
* @param {boolean} isPanel
* @returns
*/
function m_mp_NotificationGetElement(notification, isPanel = true) {
return new html_notification(notification, isPanel).generate()[0];
}