Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging
commit
b8343b5483
|
@ -5,6 +5,7 @@ var map = {
|
|||
'es': 'Español',
|
||||
'el': 'Ελληνικά',
|
||||
'fr': 'Français',
|
||||
'nb': 'Norwegian Bokmål',
|
||||
'pl': 'Polski',
|
||||
'pt-br': 'Português do Brasil',
|
||||
'ro': 'Română',
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* You can override the translation text using this file.
|
||||
* The recommended method is to make a copy of this file (/customize.dist/translations/messages.{LANG}.js)
|
||||
in a 'customize' directory (/customize/translations/messages.{LANG}.js).
|
||||
* If you want to check all the existing translation keys, you can open the internal language file
|
||||
but you should not change it directly (/common/translations/messages.{LANG}.js)
|
||||
*/
|
||||
define(['/common/translations/messages.nb.js'], function (Messages) {
|
||||
// Replace the existing keys in your copied file here:
|
||||
// Messages.button_newpad = "New Rich Text Document";
|
||||
|
||||
return Messages;
|
||||
});
|
||||
|
|
@ -58147,37 +58147,6 @@ function Log(level) {
|
|||
this.warn = function () {};
|
||||
this.error = function () {};
|
||||
this.log = function () {};
|
||||
return;
|
||||
this.log = function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var level = args.shift();
|
||||
var logLevel = this.level;
|
||||
if (typeof logLevel === 'undefined') {
|
||||
logLevel = defaultLevel;
|
||||
}
|
||||
if (logLevel <= level) {
|
||||
if (typeof console !== 'undefined') {
|
||||
//eslint-disable-line no-console
|
||||
if (typeof console.log !== 'undefined') {
|
||||
//eslint-disable-line no-console
|
||||
//return console.log('[' + formatTime(new Date()) + '] ' , str); //eslint-disable-line no-console
|
||||
args.unshift('[' + formatTime(new Date()) + '] ');
|
||||
console.log.apply(console, args.map(function (a) {
|
||||
if (typeof a === "object") {
|
||||
return a.toString() + JSON.stringify(a, null, 2);
|
||||
}
|
||||
return a;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.trace = window.console.debug.bind(window.console, format('TRACE', name), 'color:grey;', 'color: grey;');
|
||||
this.debug = window.console.debug.bind(window.console, format('DEBUG', name), 'color:grey;', 'color: green;');
|
||||
this.info = window.console.debug.bind(window.console, format('INFO', name), 'color:grey;', 'color: blue;');
|
||||
this.warn = window.console.debug.bind(window.console, format('WARN', name), 'color:grey;', 'color: orange;');
|
||||
this.error = window.console.debug.bind(window.console, format('ERROR', name), 'color:grey;', 'color: red;');
|
||||
}
|
||||
|
||||
exports.Log = Log;
|
||||
|
|
|
@ -965,6 +965,7 @@ define([
|
|||
if (channel.padChan !== padChan) { return; }
|
||||
if (channel.wc) { channel.wc.leave(); }
|
||||
channel.stopped = true;
|
||||
delete channels[chatChan];
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1058,14 +1058,12 @@ define([
|
|||
};
|
||||
|
||||
var timeout = false;
|
||||
common.onTimeoutEvent = Util.mkEvent();
|
||||
var onTimeout = function () {
|
||||
return;
|
||||
/*
|
||||
timeout = true;
|
||||
common.onNetworkDisconnect.fire();
|
||||
// FIXME: no UI in outer...
|
||||
window.alert("Timeout error, please reload this tab");
|
||||
*/
|
||||
common.padRpc.onDisconnectEvent.fire();
|
||||
common.onTimeoutEvent.fire();
|
||||
};
|
||||
|
||||
var queries = {
|
||||
|
|
|
@ -18,6 +18,25 @@ define(['json.sortify'], function (Sortify) {
|
|||
var lazyChangeHandlers = [];
|
||||
var titleChangeHandlers = [];
|
||||
|
||||
// When someone leaves the document, their metadata is removed from our metadataObj
|
||||
// but it is not removed instantly from the chainpad document metadata. This is
|
||||
// the result of the lazy object: if we had to remove the metadata instantly, all
|
||||
// the remaining members would try to push a patch to do it, and it could create
|
||||
// conflicts. Their metadata is instead removed from the chainpad doc only when
|
||||
// someone calls onLocal to make another change.
|
||||
// The leaving user is not visible in the userlist UI because we filter it using
|
||||
// the list of "members" (netflux ID currently online).
|
||||
// Our Problem:
|
||||
// With the addition of shared workers, a user can leave and join back with the same
|
||||
// netflux ID (just reload the pad). If nobody has made any change in the mean time,
|
||||
// their metadata will still be in the document, but they won't be in our metadataObj.
|
||||
// This causes the presence of a "viewer" instead of an editor, because they don't
|
||||
// have user data.
|
||||
// To fix this problem, the metadata manager can request "syncs" from a chainpad app,
|
||||
// and the app should trigger a "metadataMgr.updateMetadata(data)" in the handler.
|
||||
// See "metadataMgr.onRequestSync" in sframe-app-framework for an example.
|
||||
var syncHandlers = [];
|
||||
|
||||
var rememberedTitle;
|
||||
|
||||
var checkUpdate = function (lazy) {
|
||||
|
@ -41,26 +60,25 @@ define(['json.sortify'], function (Sortify) {
|
|||
|
||||
var mdo = {};
|
||||
// We don't want to add our user data to the object multiple times.
|
||||
//var containsYou = false;
|
||||
//console.log(metadataObj);
|
||||
Object.keys(metadataObj.users).forEach(function (x) {
|
||||
if (members.indexOf(x) === -1) { return; }
|
||||
mdo[x] = metadataObj.users[x];
|
||||
/*if (metadataObj.users[x].uid === meta.user.uid) {
|
||||
//console.log('document already contains you');
|
||||
containsYou = true;
|
||||
}*/
|
||||
});
|
||||
//if (!containsYou) { mdo[meta.user.netfluxId] = meta.user; }
|
||||
if (!priv.readOnly) {
|
||||
mdo[meta.user.netfluxId] = meta.user;
|
||||
}
|
||||
metadataObj.users = mdo;
|
||||
|
||||
// Always update the userlist in the lazy object, otherwise it may be outdated
|
||||
// and metadataMgr.updateMetadata() won't do anything, and so we won't push events
|
||||
// to the userlist UI ==> phantom viewers
|
||||
var lazyUserStr = Sortify(metadataLazyObj.users[meta.user.netfluxId]);
|
||||
dirty = false;
|
||||
if (lazy || lazyUserStr !== Sortify(meta.user)) {
|
||||
metadataLazyObj = JSON.parse(JSON.stringify(metadataObj));
|
||||
lazyChangeHandlers.forEach(function (f) { f(); });
|
||||
} else {
|
||||
metadataLazyObj.users = JSON.parse(JSON.stringify(mdo));
|
||||
}
|
||||
|
||||
if (metadataObj.title !== rememberedTitle) {
|
||||
|
@ -127,6 +145,7 @@ define(['json.sortify'], function (Sortify) {
|
|||
members.push(ev);
|
||||
if (!meta.user) { return; }
|
||||
change(false);
|
||||
syncHandlers.forEach(function (f) { f(); });
|
||||
});
|
||||
sframeChan.on('EV_RT_LEAVE', function (ev) {
|
||||
var idx = members.indexOf(ev);
|
||||
|
@ -171,13 +190,14 @@ define(['json.sortify'], function (Sortify) {
|
|||
onTitleChange: function (f) { titleChangeHandlers.push(f); },
|
||||
onChange: function (f) { changeHandlers.push(f); },
|
||||
onChangeLazy: function (f) { lazyChangeHandlers.push(f); },
|
||||
onRequestSync: function (f) { syncHandlers.push(f); },
|
||||
isConnected : function () {
|
||||
return members.indexOf(meta.user.netfluxId) !== -1;
|
||||
},
|
||||
getViewers : function () {
|
||||
checkUpdate(false);
|
||||
var list = members.slice().filter(function (m) { return m.length === 32; });
|
||||
return list.length - Object.keys(metadataObj.users).length;
|
||||
return list.length - Object.keys(metadataLazyObj.users).length;
|
||||
},
|
||||
getChannelMembers: function () { return members.slice(); },
|
||||
getPrivateData : function () {
|
||||
|
|
|
@ -1262,9 +1262,15 @@ define([
|
|||
var messengerEventClients = [];
|
||||
|
||||
var dropChannel = function (chanId) {
|
||||
store.messenger.leavePad(chanId);
|
||||
store.cursor.leavePad(chanId);
|
||||
store.onlyoffice.leavePad(chanId);
|
||||
try {
|
||||
store.messenger.leavePad(chanId);
|
||||
} catch (e) { console.error(e); }
|
||||
try {
|
||||
store.cursor.leavePad(chanId);
|
||||
} catch (e) { console.error(e); }
|
||||
try {
|
||||
store.onlyoffice.leavePad(chanId);
|
||||
} catch (e) { console.error(e); }
|
||||
|
||||
if (!Store.channels[chanId]) { return; }
|
||||
|
||||
|
@ -1283,8 +1289,12 @@ define([
|
|||
if (messengerIdx !== -1) {
|
||||
messengerEventClients.splice(messengerIdx, 1);
|
||||
}
|
||||
store.cursor.removeClient(clientId);
|
||||
store.onlyoffice.removeClient(clientId);
|
||||
try {
|
||||
store.cursor.removeClient(clientId);
|
||||
} catch (e) { console.error(e); }
|
||||
try {
|
||||
store.onlyoffice.removeClient(clientId);
|
||||
} catch (e) { console.error(e); }
|
||||
|
||||
Object.keys(Store.channels).forEach(function (chanId) {
|
||||
var chanIdx = Store.channels[chanId].clients.indexOf(clientId);
|
||||
|
@ -1602,12 +1612,11 @@ define([
|
|||
broadcast([], 'NETWORK_RECONNECT', {myId: info.myId});
|
||||
});
|
||||
|
||||
/*
|
||||
// Ping clients regularly to make sure one tab was not closed without sending a removeClient()
|
||||
// command. This allow us to avoid phantom viewers in pads.
|
||||
var PING_INTERVAL = 30000;
|
||||
var MAX_PING = 1000;
|
||||
var MAX_FAILED_PING = 5;
|
||||
var MAX_PING = 5000;
|
||||
var MAX_FAILED_PING = 2;
|
||||
|
||||
setInterval(function () {
|
||||
var clients = [];
|
||||
|
@ -1635,7 +1644,6 @@ define([
|
|||
ping();
|
||||
});
|
||||
}, PING_INTERVAL);
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -533,6 +533,12 @@ define([
|
|||
}
|
||||
};
|
||||
cpNfInner.metadataMgr.onChange(checkReady);
|
||||
cpNfInner.metadataMgr.onRequestSync(function () {
|
||||
var newContentStr = cpNfInner.chainpad.getUserDoc();
|
||||
var newContent = JSON.parse(newContentStr);
|
||||
var meta = extractMetadata(newContent);
|
||||
cpNfInner.metadataMgr.updateMetadata(meta);
|
||||
});
|
||||
checkReady();
|
||||
|
||||
var infiniteSpinnerModal = false;
|
||||
|
|
|
@ -269,6 +269,9 @@ define([
|
|||
sessionStorage[Utils.Constants.displayPadCreationScreen];
|
||||
delete sessionStorage[Utils.Constants.displayPadCreationScreen];
|
||||
var updateMeta = function () {
|
||||
// TODO availableHashes in privateData may need updates once we have
|
||||
// a better privileges workflow
|
||||
|
||||
//console.log('EV_METADATA_UPDATE');
|
||||
var metaObj, isTemplate;
|
||||
nThen(function (waitFor) {
|
||||
|
@ -874,6 +877,10 @@ define([
|
|||
Cryptpad.cursor.execCommand(data, cb);
|
||||
});
|
||||
|
||||
Cryptpad.onTimeoutEvent.reg(function () {
|
||||
sframeChan.event('EV_WORKER_TIMEOUT');
|
||||
});
|
||||
|
||||
if (cfg.messaging) {
|
||||
Notifier.getPermission();
|
||||
|
||||
|
|
|
@ -51,14 +51,16 @@ define([
|
|||
metadataMgr.onChange(function () {
|
||||
var md = metadataMgr.getMetadata();
|
||||
if ($title) {
|
||||
$title.find('span.cp-toolbar-title-value').text(md.title || md.defaultTitle);
|
||||
$title.find('input').val(md.title || md.defaultTitle);
|
||||
$title.find('input').prop('placeholder', md.defaultTitle);
|
||||
}
|
||||
exp.defaultTitle = md.defaultTitle;
|
||||
exp.title = md.title;
|
||||
});
|
||||
metadataMgr.onTitleChange(function (title, defaultTitle) {
|
||||
if ($title) {
|
||||
$title.find('span.cp-toolbar-title-value').text(title || defaultTitle);
|
||||
$title.find('input').val(title || defaultTitle);
|
||||
}
|
||||
exp.title = title;
|
||||
sframeChan.query('Q_SET_PAD_TITLE_IN_DRIVE', {
|
||||
title: title,
|
||||
defaultTitle: defaultTitle
|
||||
|
|
|
@ -613,6 +613,10 @@ define([
|
|||
});
|
||||
});
|
||||
|
||||
ctx.sframeChan.on('EV_WORKER_TIMEOUT', function () {
|
||||
UI.errorLoadingScreen(Messages.timeoutError);
|
||||
});
|
||||
|
||||
ctx.sframeChan.on('EV_CHROME_68', function () {
|
||||
UI.alert(Messages.chrome68);
|
||||
});
|
||||
|
|
|
@ -475,11 +475,11 @@ MessengerUI, Messages) {
|
|||
};
|
||||
$closeIcon.click(function () {
|
||||
Common.setAttribute(['toolbar', 'chat-drawer'], false);
|
||||
hide();
|
||||
hide(true);
|
||||
});
|
||||
$button.click(function () {
|
||||
var visible = $content.is(':visible');
|
||||
if (visible) { hide(); }
|
||||
if (visible) { hide(true); }
|
||||
else { show(); }
|
||||
visible = !visible;
|
||||
Common.setAttribute(['toolbar', 'chat-drawer'], visible);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
|
@ -143,7 +143,7 @@
|
|||
"tags_notShared": "Ваши теги не разделяются с другими пользователями",
|
||||
"button_newsheet": "Новый Лист",
|
||||
"newButtonTitle": "Создать новый блокнот",
|
||||
"useTemplateCancel": "Начать без образца (Esc)",
|
||||
"useTemplateCancel": "Начать заново (Esc)",
|
||||
"previewButtonTitle": "Отобразить или скрыть режим предпросмотра разметки",
|
||||
"printOptions": "Опции расположения",
|
||||
"printBackgroundValue": "<b>Текущий фон:</b> <em>{0}</em>",
|
||||
|
@ -163,7 +163,7 @@
|
|||
"editOpen": "Открыть редактируемую ссылку в новой вкладке",
|
||||
"editOpenTitle": "Открыть блокнот в режиме редактирования в новой вкладке",
|
||||
"viewShare": "Ссылка только для чтения",
|
||||
"viewShareTitle": "Копировать ссылку для чтения",
|
||||
"viewShareTitle": "Скопировать ссылку для чтения в буфер обмена",
|
||||
"viewOpen": "Открыть ссылку в режиме чтения в новой вкладке",
|
||||
"viewOpenTitle": "Открыть блокнот в режиме чтения в новой вкладке",
|
||||
"fileShare": "Скопировать ссылку",
|
||||
|
@ -204,10 +204,10 @@
|
|||
"kanban_working": "В процессе",
|
||||
"kanban_deleteBoard": "Вы уверены, что хотите удалить эту доску?",
|
||||
"kanban_addBoard": "Добавить доску",
|
||||
"kanban_removeItem": "",
|
||||
"poll_p_save": "Ваши настройки применяются мгновенно, так что вам не нужно их сохранять",
|
||||
"kanban_removeItem": "Удалить этот элемент",
|
||||
"poll_p_save": "Ваши настройки применяются мгновенно, так что вам не нужно их сохранять.",
|
||||
"wizardTitle": "Используйте помощник, чтобы создать опрос",
|
||||
"wizardConfirm": "Вы хотите добавить эти варианты в опрос?",
|
||||
"wizardConfirm": "Вы действительно хотите добавить эти варианты в ваш опрос?",
|
||||
"poll_publish_button": "Опубликовать",
|
||||
"poll_admin_button": "Админ",
|
||||
"poll_create_user": "Добавить нового пользователя",
|
||||
|
@ -305,5 +305,17 @@
|
|||
"crowdfunding_popup_no": "Не сейчас",
|
||||
"crowdfunding_popup_never": "Не спрашивать меня снова",
|
||||
"markdown_toc": "Содержимое",
|
||||
"fm_expirablePad": "Этот блокнот удалится через {0}"
|
||||
"fm_expirablePad": "Этот блокнот удалится через {0}",
|
||||
"fileEmbedTitle": "Вставить файл во внешнюю страницу",
|
||||
"kanban_removeItemConfirm": "Вы уверенны, что хотите удалить этот пункт?",
|
||||
"settings_backup2": "Скачать мой CryptDrive",
|
||||
"settings_backup2Confirm": "Это позволит скачать все пэды и файлы с вашего CryptDrive. Если вы хотите продолжить, выберите имя и нажмите OK",
|
||||
"settings_exportTitle": "Экспортировать Ваш CryptDrive",
|
||||
"fileEmbedScript": "Чтобы вставить этот файл, включите этот скрипт один раз на своей странице, чтобы загрузить медиатег:",
|
||||
"fileEmbedTag": "Затем поместите медиатег в любое место на странице, куда вы хотите его вставить:",
|
||||
"pad_mediatagRatio": "Оставить соотношение",
|
||||
"kanban_item": "Элемент {0}",
|
||||
"poll_p_encryption": "Все ваши данные зашифрованы, доступ к ним имеют только пользователи, имеющие доступ к этой ссылке. Даже сервер не видит, что вы меняете.",
|
||||
"wizardLog": "Нажмите кнопку в левом верхнем углу, чтобы вернуться к опросу",
|
||||
"poll_bookmark_col": "Добавить этот столбец в закладку, чтобы он всегда был разблокирован и отображался для вас в начале"
|
||||
}
|
||||
|
|
|
@ -1158,6 +1158,10 @@ define([
|
|||
var md = copyObject(metadataMgr.getMetadata());
|
||||
APP.proxy.metadata = md;
|
||||
});
|
||||
metadataMgr.onRequestSync(function () {
|
||||
var meta = JSON.parse(JSON.stringify(APP.proxy.metadata));
|
||||
metadataMgr.updateMetadata(meta);
|
||||
});
|
||||
|
||||
/* add a forget button */
|
||||
var forgetCb = function (err) {
|
||||
|
|
Loading…
Reference in New Issue