From c92672eaec72d483a074a6608e29b1f2904dbbc2 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 11 Dec 2025 16:44:29 +0100 Subject: [PATCH] Allow custom broadcast with filtered users --- .../src/less2/include/alertify.less | 4 -- .../src/less2/include/modals-ui-elements.less | 7 +++ .../src/less2/include/notifications.less | 3 + www/common/notifications.js | 36 +++++++++++- www/common/sframe-common-mailbox.js | 56 ++++++++++++++++++- 5 files changed, 98 insertions(+), 8 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 3328751d6..8044f6cdf 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -82,10 +82,6 @@ } } - .cp-admin-message { - color: @cryptpad_text_col; - } - .cp-inline-alert-text { flex: 1; } diff --git a/customize.dist/src/less2/include/modals-ui-elements.less b/customize.dist/src/less2/include/modals-ui-elements.less index d7d50a1a8..ba8ef31b5 100644 --- a/customize.dist/src/less2/include/modals-ui-elements.less +++ b/customize.dist/src/less2/include/modals-ui-elements.less @@ -365,6 +365,13 @@ } } + .alertify .dialog .msg div.cp-admin-message { + color: @cryptpad_text_col; + a { + color: @cryptpad_color_link; + } + } + .cp-userteam-picker { .cp-userteam-filter { margin: 5px 0; diff --git a/customize.dist/src/less2/include/notifications.less b/customize.dist/src/less2/include/notifications.less index 38d698a32..cd794667a 100644 --- a/customize.dist/src/less2/include/notifications.less +++ b/customize.dist/src/less2/include/notifications.less @@ -68,6 +68,9 @@ &.cp-clickable { cursor: pointer; } + a { + color: @cryptpad_color_link; + } } .cp-notification-dismiss { color: @cp_dropdown-fg; diff --git a/www/common/notifications.js b/www/common/notifications.js index 30a8d83f6..8b8b6ec4f 100644 --- a/www/common/notifications.js +++ b/www/common/notifications.js @@ -10,14 +10,21 @@ define([ '/common/common-ui-elements.js', '/common/common-util.js', '/common/common-constants.js', + '/components/marked/marked.min.js', '/customize/messages.js', '/customize/pages.js', '/common/common-icons.js', 'tui-date-picker' -], function($, h, Hash, UI, UIElements, Util, Constants, Messages, Pages, Icons, DatePicker) { +], function($, h, Hash, UI, UIElements, Util, Constants, Marked, Messages, Pages, Icons, DatePicker) { var handlers = {}; + var renderer = new Marked.Renderer(); + Marked.setOptions({ + renderer: renderer, + sanitize: true + }); + var defaultDismiss = function(common, data) { return function(e) { if (e) { @@ -531,12 +538,33 @@ define([ var toShow = text[myLang]; // Otherwise, fallback to the default language if it exists if (!toShow && defaultL) { toShow = text[defaultL]; } + toShow ||= text['default']; // No translation available, dismiss if (!toShow) { return defaultDismiss(common, data)(); } var slice = toShow.length > 200; var unsafe = toShow; - toShow = Util.fixHTML(toShow); + + if (content.markdown === true) { + toShow = Marked.parse(toShow); + slice = false; + content.handler = function () { + var content = h('div', [ + h('h4', Messages.broadcast_newCustom), + UI.setHTML(h('div.cp-admin-message'), toShow) + ]); + $(content).find('a').click(e => { + e.preventDefault(); + e.stopPropagation(); + const href = e.target.href || ''; + if (!/^(http|\/)/.test(href)) { return; } + common.openURL(e.target.href); + }); + UI.alert(content); + }; + } else { + toShow = Util.fixHTML(toShow); + } content.getFormatText = function () { if (slice) { @@ -553,7 +581,9 @@ define([ UI.alert(content); }; } - if (!content.archived) { + if (content.dismiss) { + content.dismissHandler = content.dismiss; + } else if (!content.archived) { content.dismissHandler = defaultDismiss(common, data); } }; diff --git a/www/common/sframe-common-mailbox.js b/www/common/sframe-common-mailbox.js index bb3fb7708..7d8e164c9 100644 --- a/www/common/sframe-common-mailbox.js +++ b/www/common/sframe-common-mailbox.js @@ -10,9 +10,10 @@ define([ '/common/common-ui-elements.js', '/common/notifications.js', '/common/hyperscript.js', + '/customize/application_config.js', '/customize/messages.js', '/common/common-icons.js', -], function ($, Util, Hash, UI, UIElements, Notifications, h, Messages, Icons) { +], function ($, Util, Hash, UI, UIElements, Notifications, h, AppConfig, Messages, Icons) { var Mailbox = {}; Mailbox.create = function (Common) { @@ -116,6 +117,13 @@ define([ } if (typeof(data.content.getFormatText) === "function") { $(notif).find('.cp-notification-content p').html(data.content.getFormatText()); + $(notif).find('a').click(e => { + e.preventDefault(); + e.stopPropagation(); + const href = e.target.href || ''; + if (!/^(http|\/)/.test(href)) { return; } + Common.openURL(e.target.href); + }); if (data.content.autorefresh) { var it = setInterval(function () { if (!data.content.autorefresh) { @@ -199,6 +207,52 @@ define([ onMessageHandlers.forEach(todo); }; + const custom = AppConfig.customBroadcast; + if (Array.isArray(custom)) { + const metadataMgr = Common.getMetadataMgr(); + const customBcast = () => { + const priv = metadataMgr.getPrivateData(); + if (priv.offline !== false) { return; } // reject undefined/true + const dismissed = priv.settings?.broadcast?.viewed || []; + const lang = Messages._getLanguage(); + custom.forEach(obj => { + const viewed = dismissed.includes(obj.id); + if (!obj.filter(metadataMgr)) { return; } + if (viewed) { return; } + const msg = obj.msg[lang] || obj.msg['default']; + const data = { + type: 'broadcast', + content: { + hash: obj.id, + markdown: true, + dismiss: () => { + let $notif = $(`.cp-notification[data-hash^="${obj.id}"]`); + if ($notif.length) { $notif.remove(); } + if (!dismissed.includes(obj.id)) { + dismissed.push(obj.id); + } + Common.setAttribute(['broadcast', 'viewed'], + dismissed); + return true; + }, + msg: { + type: 'BROADCAST_CUSTOM', + content: { + content: obj.msg + } + } + } + }; + mailbox.onMessage(data, () => {}); + }); + + metadataMgr.off('change', customBcast); + }; + metadataMgr.onChange(customBcast); + } + + + var onViewed = function (data) { // data = { type: 'type', hash: 'hash' } onViewedHandlers.forEach(function (f) {