mirror of https://github.com/xwiki-labs/cryptpad
Instance notification prototype
This commit is contained in:
parent
7ab529d4e9
commit
fee8a88169
|
@ -8,7 +8,7 @@
|
|||
& {
|
||||
@alertify_padding-base: @variables_padding;
|
||||
|
||||
input:not(.form-control):not([type="checkbox"]), textarea, div.cp-textarea {
|
||||
input:not(.numInput):not(.form-control):not([type="checkbox"]), textarea, div.cp-textarea {
|
||||
// background-color: @alertify-input-fg;
|
||||
color: @cp_forms-fg;
|
||||
background-color: @cp_forms-bg;
|
||||
|
|
|
@ -254,6 +254,11 @@ Channel.writePrivateMessage = function (Env, args, _cb, Server, netfluxId) {
|
|||
var session = HK.getNetfluxSession(Env, netfluxId);
|
||||
var allowed = HK.listAllowedUsers(metadata);
|
||||
|
||||
// Special broadcast channel
|
||||
if (channelId === '00000000000000000000000000000000') {
|
||||
allowed = Env.admins;
|
||||
}
|
||||
|
||||
if (HK.isUserSessionAllowed(allowed, session)) { return; }
|
||||
|
||||
w.abort();
|
||||
|
|
|
@ -883,6 +883,10 @@ HK.onChannelMessage = function (Env, Server, channel, msgStruct, cb) {
|
|||
// don't store messages if the channel id indicates that it's an ephemeral message
|
||||
if (!channel.id || channel.id.length === EPHEMERAL_CHANNEL_LENGTH) { return void cb(); }
|
||||
|
||||
if (channel.id === '00000000000000000000000000000000' && msgStruct[1] !== null) {
|
||||
return void cb('ERESTRICTED_ADMIN');
|
||||
}
|
||||
|
||||
const isCp = /^cp\|/.test(msgStruct[4]);
|
||||
let id;
|
||||
if (isCp) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
display: flex;
|
||||
flex-flow: column;
|
||||
|
||||
.cp-admin-setlimit-form {
|
||||
.cp-admin-setlimit-form, .cp-admin-broadcast-form {
|
||||
label {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
@ -199,5 +199,30 @@
|
|||
}
|
||||
}
|
||||
|
||||
.cp-admin-broadcast-form {
|
||||
margin-top: 30px;
|
||||
& > button:last-child {
|
||||
margin-top: 30px !important;
|
||||
}
|
||||
.cp-broadcast-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
.cp-broadcast-lang {
|
||||
margin: 30px;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: baseline;
|
||||
.cp-checkmark {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
div.cp-broadcast-languages {
|
||||
& > label.cp-checkmark:not(:last-child) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ define([
|
|||
'/common/common-signing-keys.js',
|
||||
'/support/ui.js',
|
||||
|
||||
'/lib/datepicker/flatpickr.js',
|
||||
|
||||
'css!/lib/datepicker/flatpickr.min.css',
|
||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||
'less!/admin/app-admin.less',
|
||||
|
@ -31,7 +34,8 @@ define([
|
|||
Util,
|
||||
Hash,
|
||||
Keys,
|
||||
Support
|
||||
Support,
|
||||
Flatpickr
|
||||
)
|
||||
{
|
||||
var APP = {
|
||||
|
@ -67,6 +71,9 @@ define([
|
|||
'cp-admin-support-list',
|
||||
'cp-admin-support-init'
|
||||
],
|
||||
'broadcast': [ // Msg.admin_cat_support
|
||||
'cp-admin-broadcast'
|
||||
],
|
||||
'performance': [ // Msg.admin_cat_performance
|
||||
'cp-admin-refresh-performance',
|
||||
'cp-admin-performance-profiling',
|
||||
|
@ -930,6 +937,279 @@ define([
|
|||
return;
|
||||
};
|
||||
|
||||
// Messages.admin_cat_broadcast // XXX
|
||||
// Messages.admin_broadcastHint // XXX
|
||||
// Messages.admin_broadcastTitle // XXX
|
||||
Messages.broadcast_maintenance = 'maintenance';// XXX
|
||||
Messages.broadcast_survey = 'survey'; // XXX
|
||||
Messages.broadcast_version = 'version'; // XXX
|
||||
Messages.broadcast_custom = 'custom'; // XXX
|
||||
Messages.broadcast_newVersionReload = 'Force a worker reload on all clients'; // XXX
|
||||
Messages.broadcast_surveyURL = 'Survey URL';
|
||||
Messages.broadcast_translations = 'Translations';
|
||||
Messages.broadcast_defaultLanguage = 'Default language';
|
||||
Messages.broadcast_start = 'Start time';
|
||||
Messages.broadcast_end = 'End time';
|
||||
|
||||
var getBroadcastForm = function ($form, key) {
|
||||
$form.empty();
|
||||
|
||||
var getData = function () {
|
||||
return false;
|
||||
};
|
||||
var reset = function () {};
|
||||
|
||||
var button = h('button.btn.btn-primary', Messages.support_formButton);
|
||||
var $button = $(button);
|
||||
|
||||
var send = function () {
|
||||
var data = getData();
|
||||
if (data === false) { return void UI.warn(Messages.error); }
|
||||
$button.prop('disabled', 'disabled');
|
||||
common.mailbox.sendTo('BROADCAST_'+key.toUpperCase(), data, {}, function (err) {
|
||||
$button.prop('disabled', '');
|
||||
if (err) { return UI.warn(Messages.error); }
|
||||
reset();
|
||||
UI.log(Messages.saved);
|
||||
});
|
||||
};
|
||||
$button.click(function () {
|
||||
send();
|
||||
});
|
||||
|
||||
if (key === 'custom') {
|
||||
(function () {
|
||||
var container = h('div.cp-broadcast-container');
|
||||
var $container = $(container);
|
||||
var languages = Messages._languages;
|
||||
var keys = Object.keys(languages).sort();
|
||||
|
||||
var onPreview = function (l) {
|
||||
// XXX
|
||||
};
|
||||
|
||||
var reorder = function () {
|
||||
$container.find('.cp-broadcast-lang').each(function (i, el) {
|
||||
var $el = $(el);
|
||||
var l = $el.attr('data-lang');
|
||||
$el.css('order', keys.indexOf(l));
|
||||
});
|
||||
};
|
||||
var removeLang = function (l) {
|
||||
$container.find('.cp-broadcast-lang[data-lang="'+l+'"]').remove();
|
||||
};
|
||||
var addLang = function (l) {
|
||||
if ($container.find('.cp-broadcast-lang[data-lang="'+l+'"]').length) { return; }
|
||||
var preview = h('button.btn.btn-secondary', Messages.share_linkOpen);
|
||||
$(preview).click(function () {
|
||||
onPreview(l);
|
||||
});
|
||||
var bcastDefault = Messages.broadcast_defaultLanguage;
|
||||
$container.append(h('div.cp-broadcast-lang', { 'data-lang': l }, [
|
||||
h('h4', languages[l]),
|
||||
h('label', Messages.kanban_body),
|
||||
h('textarea'),
|
||||
UI.createRadio('broadcastDefault', null, bcastDefault, false, {
|
||||
'data-lang': l,
|
||||
label: {class: 'noTitle'}
|
||||
}),
|
||||
preview
|
||||
]));
|
||||
reorder();
|
||||
};
|
||||
|
||||
|
||||
var boxes = keys.map(function (l) {
|
||||
var $cbox = $(UI.createCheckbox('cp-broadcast-custom-lang-'+l,
|
||||
languages[l], false, { label: { class: 'noTitle' } }));
|
||||
var $check = $cbox.find('input').on('change', function () {
|
||||
var c = $check.is(':checked');
|
||||
if (c) { return void addLang(l); }
|
||||
removeLang(l);
|
||||
});
|
||||
if (l === 'en') {
|
||||
setTimeout(function () {
|
||||
$check.click();
|
||||
});
|
||||
}
|
||||
return $cbox[0];
|
||||
});
|
||||
|
||||
getData = function () {
|
||||
var map = {};
|
||||
var defaultLanguage;
|
||||
var error = false;
|
||||
$container.find('.cp-broadcast-lang').each(function (i, el) {
|
||||
var $el = $(el);
|
||||
var l = $el.attr('data-lang');
|
||||
if (!l) { error = true; return; }
|
||||
var text = $el.find('textarea').val();
|
||||
if (!text.trim()) { error = true; return; }
|
||||
if ($el.find('.cp-checkmark input').is(':checked')) {
|
||||
defaultLanguage = l;
|
||||
}
|
||||
map[l] = text;
|
||||
});
|
||||
if (!Object.keys(map).length) {
|
||||
console.error('You must select at least one language');
|
||||
return false;
|
||||
}
|
||||
if (error) {
|
||||
console.error('One of the selected languages has no data');
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
defaultLanguage: defaultLanguage,
|
||||
content: map
|
||||
};
|
||||
};
|
||||
reset = function () {
|
||||
$container.find('.cp-broadcast-lang textarea').each(function (i, el) {
|
||||
$(el).val('');
|
||||
});
|
||||
};
|
||||
$form.append([
|
||||
h('label', Messages.broadcast_translations),
|
||||
h('div.cp-broadcast-languages', boxes),
|
||||
container,
|
||||
button
|
||||
]);
|
||||
})();
|
||||
return;
|
||||
}
|
||||
if (key === 'maintenance') {
|
||||
(function () {
|
||||
var start = h('input');
|
||||
var end = h('input');
|
||||
var $start = $(start);
|
||||
var $end = $(end);
|
||||
|
||||
var endPickr = Flatpickr(end, {
|
||||
enableTime: true,
|
||||
minDate: new Date()
|
||||
});
|
||||
Flatpickr(start, {
|
||||
enableTime: true,
|
||||
minDate: new Date(),
|
||||
onChange: function () {
|
||||
endPickr.set('minDate', new Date($start.val()));
|
||||
}
|
||||
});
|
||||
getData = function () {
|
||||
var start = +new Date($start.val());
|
||||
var end = +new Date($start.val());
|
||||
if (isNaN(start) || isNaN(end)) {
|
||||
console.error('Invalid dates');
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
start: start,
|
||||
end: end
|
||||
};
|
||||
};
|
||||
reset = function () {
|
||||
$start.val('');
|
||||
$end.val('');
|
||||
};
|
||||
$form.append([
|
||||
h('label', Messages.broadcast_start),
|
||||
start,
|
||||
h('label', Messages.broadcast_end),
|
||||
end,
|
||||
h('br'),
|
||||
button
|
||||
]);
|
||||
})();
|
||||
return;
|
||||
}
|
||||
if (key === 'version') {
|
||||
(function () {
|
||||
var $cbox = $(UI.createCheckbox('cp-admin-version-reload',
|
||||
Messages.broadcast_newVersionReload,
|
||||
false, { label: { class: 'noTitle' } }));
|
||||
var $checkbox = $cbox.find('input');
|
||||
getData = function () {
|
||||
return {
|
||||
reload: $checkbox.is(':checked')
|
||||
};
|
||||
};
|
||||
reset = function () {
|
||||
$checkbox[0].checked = false;
|
||||
};
|
||||
$form.append([
|
||||
$cbox[0],
|
||||
h('br'),
|
||||
button
|
||||
]);
|
||||
})();
|
||||
return;
|
||||
}
|
||||
if (key === 'survey') {
|
||||
(function () {
|
||||
var label = h('label', Messages.broadcast_surveyURL);
|
||||
var input = h('input');
|
||||
var $input = $(input);
|
||||
getData = function () {
|
||||
var url = $input.val();
|
||||
if (!Util.isValidURL(url)) {
|
||||
console.error('Invalid URL');
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
url: url
|
||||
};
|
||||
};
|
||||
reset = function () {
|
||||
$input.val('');
|
||||
};
|
||||
$form.append([
|
||||
label,
|
||||
input,
|
||||
h('br'),
|
||||
button
|
||||
]);
|
||||
})();
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
create['broadcast'] = function () {
|
||||
var key = 'broadcast';
|
||||
var $div = makeBlock(key);
|
||||
|
||||
var form = h('div.cp-admin-broadcast-form')
|
||||
var $select = $(h('div.cp-dropdown-container')).appendTo($div);
|
||||
var $form = $(form).appendTo($div);
|
||||
|
||||
var categories = [
|
||||
'maintenance',
|
||||
'survey',
|
||||
'version',
|
||||
'custom'
|
||||
];
|
||||
categories = categories.map(function (key) {
|
||||
return {
|
||||
tag: 'a',
|
||||
content: h('span', Messages['broadcast_'+key]),
|
||||
action: function () {
|
||||
getBroadcastForm($form, key);
|
||||
}
|
||||
};
|
||||
});
|
||||
var dropdownCfg = {
|
||||
text: Messages.support_category,
|
||||
angleDown: 1,
|
||||
options: categories,
|
||||
container: $select,
|
||||
isSelect: true
|
||||
};
|
||||
UIElements.createDropdown(dropdownCfg);
|
||||
|
||||
|
||||
return $div;
|
||||
};
|
||||
|
||||
|
||||
var onRefreshPerformance = Util.mkEvent();
|
||||
|
||||
create['refresh-performance'] = function () {
|
||||
|
@ -1010,6 +1290,7 @@ define([
|
|||
stats: 'fa fa-line-chart',
|
||||
quota: 'fa fa-hdd-o',
|
||||
support: 'fa fa-life-ring',
|
||||
broadcast: 'fa fa-bullhorn',
|
||||
performance: 'fa fa-heartbeat',
|
||||
};
|
||||
|
||||
|
|
|
@ -554,6 +554,16 @@
|
|||
return false;
|
||||
};
|
||||
|
||||
Util.isValidURL = function (str) {
|
||||
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
|
||||
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
|
||||
return !!pattern.test(str);
|
||||
};
|
||||
|
||||
var emoji_patt = /([\uD800-\uDBFF][\uDC00-\uDFFF])/;
|
||||
var isEmoji = function (str) {
|
||||
return emoji_patt.test(str);
|
||||
|
|
|
@ -406,6 +406,87 @@ define([
|
|||
}
|
||||
};
|
||||
|
||||
Messages.broadcast_newSurvey = "A new survey is available."; // XXX
|
||||
handlers['BROADCAST_SURVEY'] = function (common, data) {
|
||||
var content = data.content;
|
||||
var msg = content.msg.content;
|
||||
content.getFormatText = function () {
|
||||
return Messages.broadcast_newSurvey;
|
||||
};
|
||||
content.handler = function () {
|
||||
common.openUnsafeURL(msg.url);
|
||||
// XXX dismiss on click?
|
||||
};
|
||||
if (!content.archived) {
|
||||
content.dismissHandler = defaultDismiss(common, data);
|
||||
}
|
||||
};
|
||||
|
||||
Messages.broadcast_newMaintenance = "A maintenance is planned between <b>{0}</b> and <b>{1}</b>"; // XXX
|
||||
handlers['BROADCAST_MAINTENANCE'] = function (common, data) {
|
||||
var content = data.content;
|
||||
var msg = content.msg.content;
|
||||
content.getFormatText = function () {
|
||||
return Messages._getKey('broadcast_newMaintenance', [
|
||||
new Date(msg.start).toLocaleString(),
|
||||
new Date(msg.end).toLocaleString(),
|
||||
]);
|
||||
};
|
||||
if (!content.archived) {
|
||||
content.dismissHandler = defaultDismiss(common, data);
|
||||
}
|
||||
};
|
||||
|
||||
Messages.broadcast_newVersion = "A new version is available. Reload the page to discover the new features!"; // XXX
|
||||
handlers['BROADCAST_VERSION'] = function (common, data) {
|
||||
var content = data.content;
|
||||
content.getFormatText = function () {
|
||||
return Messages.broadcast_newVersion;
|
||||
};
|
||||
if (!content.archived) {
|
||||
content.dismissHandler = defaultDismiss(common, data);
|
||||
}
|
||||
};
|
||||
|
||||
Messages.broadcast_newCustom = "Message from the administrators"; // XXX
|
||||
handlers['BROADCAST_CUSTOM'] = function (common, data) {
|
||||
var content = data.content;
|
||||
var msg = content.msg.content;
|
||||
var text = msg.content;
|
||||
var defaultL = msg.defaultLanguage;
|
||||
// Check if our language is available
|
||||
var toShow = text[Messages._languageUsed];
|
||||
// Otherwise, fallback to the default language if it exists
|
||||
if (!toShow && defaultL) { toShow = text[defaultL]; }
|
||||
// No translation available, dismiss
|
||||
if (!toShow) { defaultDismiss(common, data)(); }
|
||||
|
||||
var slice = toShow.length > 500;
|
||||
toShow = Util.fixHTML(toShow);
|
||||
|
||||
content.getFormatText = function () {
|
||||
// XXX Add a title to custom messages? Or use a generic key in the notification and only display the text in the alert?
|
||||
if (slice) {
|
||||
return toShow.slice(0, 500) + '...';
|
||||
}
|
||||
return toShow;
|
||||
};
|
||||
if (slice) {
|
||||
content.handler = function () {
|
||||
// XXX Allow markdown (sanitized)?
|
||||
var content = h('div', [
|
||||
h('h4', Messages.broadcast_newCustom),
|
||||
h('div', toShow)
|
||||
]);
|
||||
UI.alert(content);
|
||||
// XXX Dismiss on click?
|
||||
};
|
||||
}
|
||||
if (!content.archived) {
|
||||
content.dismissHandler = defaultDismiss(common, data);
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
define([
|
||||
'/api/config',
|
||||
'/common/common-util.js',
|
||||
'/common/common-hash.js',
|
||||
'/common/common-realtime.js',
|
||||
|
@ -7,17 +8,20 @@ define([
|
|||
'/common/outer/mailbox-handlers.js',
|
||||
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
||||
'/bower_components/chainpad-crypto/crypto.js',
|
||||
], function (Util, Hash, Realtime, Messaging, Notify, Handlers, CpNetflux, Crypto) {
|
||||
], function (Config, Util, Hash, Realtime, Messaging, Notify, Handlers, CpNetflux, Crypto) {
|
||||
var Mailbox = {};
|
||||
|
||||
var TYPES = [
|
||||
'notifications',
|
||||
'supportadmin',
|
||||
'support'
|
||||
'support',
|
||||
'broadcast'
|
||||
];
|
||||
var BLOCKING_TYPES = [
|
||||
];
|
||||
|
||||
var BROADCAST_CHAN = '00000000000000000000000000000000';
|
||||
|
||||
var initializeMailboxes = function (ctx, mailboxes) {
|
||||
if (!mailboxes['notifications']) {
|
||||
mailboxes.notifications = {
|
||||
|
@ -39,6 +43,16 @@ define([
|
|||
if (res.error) { console.error(res); }
|
||||
});
|
||||
}
|
||||
if (!mailboxes['broadcast']) {
|
||||
mailboxes.broadcast = {
|
||||
channel: BROADCAST_CHAN,
|
||||
lastKnownHash: '', // XXX load /api/brooadcast to set this hash
|
||||
decrypted: true,
|
||||
viewed: []
|
||||
};
|
||||
} else {
|
||||
// XXX update lastKnownHash from /api/broadcast
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -80,33 +94,49 @@ proxy.mailboxes = {
|
|||
|
||||
// Send a message to someone else
|
||||
var sendTo = Mailbox.sendTo = function (ctx, type, msg, user, _cb) {
|
||||
user = user || {};
|
||||
var cb = _cb || function (obj) {
|
||||
if (obj && obj.error) {
|
||||
console.error(obj.error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!Crypto.Mailbox) {
|
||||
return void cb({error: "chainpad-crypto is outdated and doesn't support mailboxes."});
|
||||
}
|
||||
var keys = getMyKeys(ctx);
|
||||
if (!keys) { return void cb({error: "missing asymmetric encryption keys"}); }
|
||||
if (!user || !user.channel || !user.curvePublic) { return void cb({error: "no notification channel"}); }
|
||||
|
||||
var anonRpc = Util.find(ctx, [ 'store', 'anon_rpc', ]);
|
||||
if (!anonRpc) { return void cb({error: "anonymous rpc session not ready"}); }
|
||||
|
||||
var crypto = Crypto.Mailbox.createEncryptor(keys);
|
||||
|
||||
// Always send your data
|
||||
if (typeof(msg) === "object" && !msg.user) {
|
||||
var myData = Messaging.createData(ctx.store.proxy, false);
|
||||
msg.user = myData;
|
||||
}
|
||||
|
||||
var text = JSON.stringify({
|
||||
// Broadcast mailbox doesn't use encryption. Sending messages there is restricted
|
||||
// to admins in the server directly
|
||||
var crypto = { encrypt: function (x) { return x; } };
|
||||
var channel = BROADCAST_CHAN;
|
||||
var obj = {
|
||||
uid: Util.uid(), // add uid at the beginning to have a unique server hash
|
||||
type: type,
|
||||
content: msg
|
||||
});
|
||||
};
|
||||
|
||||
if (!/^BROADCAST/.test(type)) {
|
||||
var keys = getMyKeys(ctx);
|
||||
if (!keys) { return void cb({error: "missing asymmetric encryption keys"}); }
|
||||
if (!user || !user.channel || !user.curvePublic) { return void cb({error: "no notification channel"}); }
|
||||
channel = user.channel;
|
||||
crypto = Crypto.Mailbox.createEncryptor(keys);
|
||||
|
||||
// Always send your data
|
||||
if (typeof(msg) === "object" && !msg.user) {
|
||||
var myData = Messaging.createData(ctx.store.proxy, false);
|
||||
msg.user = myData;
|
||||
}
|
||||
obj = {
|
||||
type: type,
|
||||
content: msg
|
||||
};
|
||||
}
|
||||
|
||||
var text = JSON.stringify(obj);
|
||||
var ciphertext = crypto.encrypt(text, user.curvePublic);
|
||||
|
||||
// If we've sent this message to one of our teams' mailbox, we may want to "dismiss" it
|
||||
|
@ -121,7 +151,7 @@ proxy.mailboxes = {
|
|||
}
|
||||
|
||||
anonRpc.send("WRITE_PRIVATE_MESSAGE", [
|
||||
user.channel,
|
||||
channel,
|
||||
ciphertext
|
||||
], function (err /*, response */) {
|
||||
if (err) {
|
||||
|
@ -239,8 +269,11 @@ proxy.mailboxes = {
|
|||
return void console.error("chainpad-crypto is outdated and doesn't support mailboxes.");
|
||||
}
|
||||
var keys = m.keys || getMyKeys(ctx);
|
||||
if (!keys) { return void console.error("missing asymmetric encryption keys"); }
|
||||
var crypto = Crypto.Mailbox.createEncryptor(keys);
|
||||
if (!keys && !m.decrypted) { return void console.error("missing asymmetric encryption keys"); }
|
||||
var crypto = m.decrypted ? {
|
||||
encrypt: function (x) { return x; },
|
||||
decrypt: function (x) { return x; }
|
||||
} : Crypto.Mailbox.createEncryptor(keys);
|
||||
box.encryptor = crypto;
|
||||
var cfg = {
|
||||
network: ctx.store.network,
|
||||
|
|
|
@ -106,7 +106,7 @@ define([
|
|||
|
||||
// Call the onMessage handlers
|
||||
var isNotification = function (type) {
|
||||
return type === "notifications" || /^team-/.test(type);
|
||||
return type === "notifications" || /^team-/.test(type) || type === "broadcast";
|
||||
};
|
||||
var pushMessage = function (data, handler) {
|
||||
var todo = function (f) {
|
||||
|
|
|
@ -1081,7 +1081,7 @@ MessengerUI, Messages) {
|
|||
$button.addClass('fa-bell');
|
||||
};
|
||||
|
||||
Common.mailbox.subscribe(['notifications', 'team'], {
|
||||
Common.mailbox.subscribe(['notifications', 'team', 'broadcast'], {
|
||||
onMessage: function (data, el) {
|
||||
if (el) {
|
||||
$(div).prepend(el);
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -445,6 +445,9 @@ define([
|
|||
};
|
||||
ctx.FM = common.createFileManager(fmConfig);
|
||||
|
||||
ui.send = function (id, type, data, dest) {
|
||||
return send(ctx, id, type, data, dest);
|
||||
};
|
||||
ui.sendForm = function (id, form, dest) {
|
||||
return sendForm(ctx, id, form, dest);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue