resolve merge conflicts
This commit is contained in:
40
check-accounts.js
Normal file
40
check-accounts.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* globals Buffer */
|
||||||
|
var Https = require('https');
|
||||||
|
var Config = require("./config.js");
|
||||||
|
var Package = require("./package.json");
|
||||||
|
|
||||||
|
var body = JSON.stringify({
|
||||||
|
domain: Config.myDomain,
|
||||||
|
adminEmail: Config.adminEmail,
|
||||||
|
version: Package.version,
|
||||||
|
});
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
host: 'accounts.cryptpad.fr',
|
||||||
|
path: '/api/getauthorized',
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Content-Length': Buffer.byteLength(body)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Https.request(options, function (response) {
|
||||||
|
if (!('' + response.statusCode).match(/^2\d\d$/)) {
|
||||||
|
throw new Error('SERVER ERROR ' + response.statusCode);
|
||||||
|
}
|
||||||
|
var str = '';
|
||||||
|
response.on('data', function (chunk) {
|
||||||
|
str += chunk;
|
||||||
|
});
|
||||||
|
response.on('end', function () {
|
||||||
|
try {
|
||||||
|
var json = JSON.parse(str);
|
||||||
|
console.log(json);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).on('error', function (e) {
|
||||||
|
console.error(e);
|
||||||
|
}).end(body);
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/customize/application_config.js',
|
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/api/config',
|
|
||||||
], function ($, Config, Cryptpad, ApiConfig) {
|
|
||||||
|
|
||||||
window.APP = {
|
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
};
|
|
||||||
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
// Language selector
|
|
||||||
var $sel = $('#language-selector');
|
|
||||||
Cryptpad.createLanguageSelector(undefined, $sel);
|
|
||||||
$sel.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
$sel.show();
|
|
||||||
|
|
||||||
var $upgrade = $('#upgrade');
|
|
||||||
|
|
||||||
var showUpgrade = function (text, feedback, url) {
|
|
||||||
if (ApiConfig.removeDonateButton) { return; }
|
|
||||||
if (localStorage.plan) { return; }
|
|
||||||
if (!text) { return; }
|
|
||||||
$upgrade.text(text).show();
|
|
||||||
$upgrade.click(function () {
|
|
||||||
Cryptpad.feedback(feedback);
|
|
||||||
window.open(url,'_blank');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// User admin menu
|
|
||||||
var $userMenu = $('#user-menu');
|
|
||||||
var userMenuCfg = {
|
|
||||||
$initBlock: $userMenu,
|
|
||||||
'static': true
|
|
||||||
};
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
$userAdmin.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Cryptpad.isLoggedIn() && ApiConfig.allowSubscriptions) {
|
|
||||||
showUpgrade(Messages.upgradeAccount, "HOME_UPGRADE_ACCOUNT", Cryptpad.upgradeURL);
|
|
||||||
} else {
|
|
||||||
showUpgrade(Messages.supportCryptpad, "HOME_SUPPORT_CRYPTPAD", Cryptpad.donateURL);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
@@ -2,15 +2,16 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/customize/header.js',
|
'/common/common-interface.js',
|
||||||
], function ($, Config, Cryptpad) {
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
], function ($, Config, Cryptpad, UI, Realtime, Constants, Messages) {
|
||||||
|
|
||||||
window.APP = {
|
window.APP = {
|
||||||
Cryptpad: Cryptpad,
|
Cryptpad: Cryptpad,
|
||||||
};
|
};
|
||||||
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
var $main = $('#mainBlock');
|
var $main = $('#mainBlock');
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ define([
|
|||||||
$main.find('a[href="/drive/"] div.pad-button-text h4')
|
$main.find('a[href="/drive/"] div.pad-button-text h4')
|
||||||
.text(Messages.main_yourCryptDrive);
|
.text(Messages.main_yourCryptDrive);
|
||||||
|
|
||||||
var name = localStorage[Cryptpad.userNameKey] || sessionStorage[Cryptpad.userNameKey];
|
var name = localStorage[Constants.userNameKey] || sessionStorage[Constants.userNameKey];
|
||||||
var $loggedInBlock = $main.find('#loggedIn');
|
var $loggedInBlock = $main.find('#loggedIn');
|
||||||
var $hello = $loggedInBlock.find('#loggedInHello');
|
var $hello = $loggedInBlock.find('#loggedInHello');
|
||||||
var $logout = $loggedInBlock.find('#loggedInLogOut');
|
var $logout = $loggedInBlock.find('#loggedInLogOut');
|
||||||
@@ -58,34 +59,6 @@ define([
|
|||||||
$('#name').focus();
|
$('#name').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
var displayCreateButtons = function () {
|
|
||||||
var $parent = $('#buttons');
|
|
||||||
var options = [];
|
|
||||||
var $container = $('<div>', {'class': 'cp-dropdown-container'}).appendTo($parent);
|
|
||||||
Config.availablePadTypes.forEach(function (el) {
|
|
||||||
if (el === 'drive') { return; }
|
|
||||||
if (!Cryptpad.isLoggedIn() && Config.registeredOnlyTypes &&
|
|
||||||
Config.registeredOnlyTypes.indexOf(el) !== -1) { return; }
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {
|
|
||||||
'class': 'newdoc',
|
|
||||||
'href': '/' + el + '/',
|
|
||||||
'target': '_blank'
|
|
||||||
},
|
|
||||||
content: Messages['button_new' + el] // Pretty name of the language value
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var dropdownConfig = {
|
|
||||||
text: Messages.login_makeAPad, // Button initial text
|
|
||||||
options: options, // Entries displayed in the menu
|
|
||||||
container: $container
|
|
||||||
};
|
|
||||||
var $block = Cryptpad.createDropdown(dropdownConfig);
|
|
||||||
$block.find('button').addClass('btn').addClass('btn-primary');
|
|
||||||
$block.appendTo($parent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Log in UI */
|
/* Log in UI */
|
||||||
var Login;
|
var Login;
|
||||||
// deferred execution to avoid unnecessary asset loading
|
// deferred execution to avoid unnecessary asset loading
|
||||||
@@ -116,7 +89,7 @@ define([
|
|||||||
$('button.login').click(function () {
|
$('button.login').click(function () {
|
||||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
Cryptpad.addLoadingScreen({loadingText: Messages.login_hashing});
|
UI.addLoadingScreen({loadingText: Messages.login_hashing});
|
||||||
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed after hashing the password
|
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed after hashing the password
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
loginReady(function () {
|
loginReady(function () {
|
||||||
@@ -135,7 +108,7 @@ define([
|
|||||||
proxy.edPrivate = result.edPrivate;
|
proxy.edPrivate = result.edPrivate;
|
||||||
proxy.edPublic = result.edPublic;
|
proxy.edPublic = result.edPublic;
|
||||||
|
|
||||||
Cryptpad.whenRealtimeSyncs(result.realtime, function () {
|
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
||||||
Cryptpad.login(result.userHash, result.userName, function () {
|
Cryptpad.login(result.userHash, result.userName, function () {
|
||||||
document.location.href = '/drive/';
|
document.location.href = '/drive/';
|
||||||
});
|
});
|
||||||
@@ -144,22 +117,22 @@ define([
|
|||||||
}
|
}
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'NO_SUCH_USER':
|
case 'NO_SUCH_USER':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_noSuchUser);
|
UI.alert(Messages.login_noSuchUser);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'INVAL_USER':
|
case 'INVAL_USER':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_invalUser);
|
UI.alert(Messages.login_invalUser);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'INVAL_PASS':
|
case 'INVAL_PASS':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_invalPass);
|
UI.alert(Messages.login_invalPass);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default: // UNHANDLED ERROR
|
default: // UNHANDLED ERROR
|
||||||
Cryptpad.errorLoadingScreen(Messages.login_unhandledError);
|
UI.errorLoadingScreen(Messages.login_unhandledError);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -167,27 +140,6 @@ define([
|
|||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
/* End Log in UI */
|
/* End Log in UI */
|
||||||
|
|
||||||
var addButtonHandlers = function () {
|
|
||||||
$('button.register').click(function () {
|
|
||||||
var username = $('#name').val();
|
|
||||||
var passwd = $('#password').val();
|
|
||||||
sessionStorage.login_user = username;
|
|
||||||
sessionStorage.login_pass = passwd;
|
|
||||||
document.location.href = '/register/';
|
|
||||||
});
|
|
||||||
$('button.gotodrive').click(function () {
|
|
||||||
document.location.href = '/drive/';
|
|
||||||
});
|
|
||||||
|
|
||||||
$('button#loggedInLogout').click(function () {
|
|
||||||
$('#user-menu .logout').click();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
displayCreateButtons();
|
|
||||||
|
|
||||||
addButtonHandlers();
|
|
||||||
console.log("ready");
|
console.log("ready");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ if (language && map[language]) { req.push('/customize/translations/messages.' +
|
|||||||
define(req, function($, Default, Language) {
|
define(req, function($, Default, Language) {
|
||||||
map.en = 'English';
|
map.en = 'English';
|
||||||
var defaultLanguage = 'en';
|
var defaultLanguage = 'en';
|
||||||
console.log(messages);
|
|
||||||
|
|
||||||
if (!Language || language === defaultLanguage || !map[language]) {
|
if (!Language || language === defaultLanguage || !map[language]) {
|
||||||
messages = $.extend(true, messages, Default);
|
messages = $.extend(true, messages, Default);
|
||||||
@@ -39,7 +38,6 @@ console.log(messages);
|
|||||||
// Add the translated keys to the returned object
|
// Add the translated keys to the returned object
|
||||||
messages = $.extend(true, messages, Default, Language);
|
messages = $.extend(true, messages, Default, Language);
|
||||||
}
|
}
|
||||||
console.log(messages);
|
|
||||||
|
|
||||||
messages._languages = map;
|
messages._languages = map;
|
||||||
messages._languageUsed = language;
|
messages._languageUsed = language;
|
||||||
@@ -49,11 +47,13 @@ console.log(messages);
|
|||||||
var missing = [];
|
var missing = [];
|
||||||
var reqs = [];
|
var reqs = [];
|
||||||
Object.keys(map).forEach(function (code) {
|
Object.keys(map).forEach(function (code) {
|
||||||
|
if (code === defaultLanguage) { return; }
|
||||||
reqs.push('/customize/translations/messages.' + code + '.js');
|
reqs.push('/customize/translations/messages.' + code + '.js');
|
||||||
});
|
});
|
||||||
require(reqs, function () {
|
require(reqs, function () {
|
||||||
var langs = arguments;
|
var langs = arguments;
|
||||||
Object.keys(map).forEach(function (code, i) {
|
Object.keys(map).forEach(function (code, i) {
|
||||||
|
if (code === defaultLanguage) { return; }
|
||||||
var translation = langs[i];
|
var translation = langs[i];
|
||||||
var updated = {};
|
var updated = {};
|
||||||
Object.keys(Default).forEach(function (k) {
|
Object.keys(Default).forEach(function (k) {
|
||||||
|
|||||||
@@ -49,11 +49,6 @@ define([
|
|||||||
h('p', Msg.main_footerText)
|
h('p', Msg.main_footerText)
|
||||||
])
|
])
|
||||||
], ''),
|
], ''),
|
||||||
/* footerCol(null, [
|
|
||||||
footLink('/about.html', 'about'),
|
|
||||||
footLink('/terms.html', 'terms'),
|
|
||||||
footLink('/privacy.html', 'privacy'),
|
|
||||||
], 'CryptPad'),*/
|
|
||||||
footerCol('footer_applications', [
|
footerCol('footer_applications', [
|
||||||
footLink('/drive/', 'main_drive'),
|
footLink('/drive/', 'main_drive'),
|
||||||
footLink('/pad/', 'main_richText'),
|
footLink('/pad/', 'main_richText'),
|
||||||
@@ -76,7 +71,7 @@ define([
|
|||||||
])
|
])
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
h('div.cp-version-footer', "CryptPad v1.19.0 (Tarasque)")
|
h('div.cp-version-footer', "CryptPad v1.21.0 (Vampire)")
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -690,45 +685,5 @@ define([
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
Pages['/drive/'] = Pages['/drive/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/file/'] = Pages['/file/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/contacts/'] = Pages['/contacts/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/pad/'] = Pages['/pad/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/code/'] = Pages['/code/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/slide/'] = Pages['/slide/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/invite/'] = Pages['/invite/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/settings/'] = Pages['/settings/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/profile/'] = Pages['/profile/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
Pages['/todo/'] = Pages['/todo/index.html'] = function () {
|
|
||||||
return loadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
return Pages;
|
return Pages;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
& > a, & > span {
|
||||||
color: @colortheme_dropdown-color;
|
color: @colortheme_dropdown-color;
|
||||||
padding: 5px 16px;
|
padding: 5px 16px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -75,6 +75,31 @@
|
|||||||
color: @colortheme_dropdown-color;
|
color: @colortheme_dropdown-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&> span {
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
.cp-dropdown-content {
|
||||||
|
margin-top: 26px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding: 0;
|
||||||
|
text-align: left;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
line-height: 1em;
|
||||||
|
.cp-toolbar-drawer-element {
|
||||||
|
margin-left: 10px;
|
||||||
|
display: inline;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: 5px 0px;
|
margin: 5px 0px;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
.cp-toolbar-history {
|
.cp-toolbar-history {
|
||||||
display: none;
|
display: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
* {
|
* {
|
||||||
font: @colortheme_app-font;
|
font: @colortheme_app-font;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cp-toolbar-userlist-drawer {
|
.cp-toolbar-userlist-drawer {
|
||||||
|
background-color: @colortheme_default-bg;
|
||||||
font: @colortheme_app-font-size @colortheme_font;
|
font: @colortheme_app-font-size @colortheme_font;
|
||||||
min-width: 175px;
|
min-width: 175px;
|
||||||
width: 175px;
|
width: 175px;
|
||||||
@@ -102,6 +103,32 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.cp-toolbar-userlist-name-input {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.cp-toolbar-userlist-name-value {
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.cp-toolbar-userlist-name-edit {
|
||||||
|
width: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
height: 20px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.cp-toolbar-userlist-friend {
|
.cp-toolbar-userlist-friend {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -115,7 +142,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.addToolbarColors (@color, @bg-color) {
|
.addToolbarColors (@color, @bg-color, @barWidth: 600px) {
|
||||||
.cp-toolbar-userlist-drawer {
|
.cp-toolbar-userlist-drawer {
|
||||||
background-color: @bgcolor;
|
background-color: @bgcolor;
|
||||||
color: @color;
|
color: @color;
|
||||||
@@ -126,6 +153,19 @@
|
|||||||
background-color: darken(@bgcolor, 10%);
|
background-color: darken(@bgcolor, 10%);
|
||||||
color: @color;
|
color: @color;
|
||||||
}
|
}
|
||||||
|
.cp-toolbar-userlist-name-input {
|
||||||
|
background-color: darken(@bg-color, 10%);
|
||||||
|
color: @color;
|
||||||
|
}
|
||||||
|
.cp-toolbar-userlist-name-edit {
|
||||||
|
color: contrast(@color,
|
||||||
|
lighten(@color, 20%),
|
||||||
|
darken(@color, 20%));
|
||||||
|
background: transparent;
|
||||||
|
&:hover {
|
||||||
|
color: @color;
|
||||||
|
}
|
||||||
|
}
|
||||||
.cp-toolbar-userlist-friend {
|
.cp-toolbar-userlist-friend {
|
||||||
&:hover {
|
&:hover {
|
||||||
color: darken(@color, 15%);
|
color: darken(@color, 15%);
|
||||||
@@ -148,6 +188,13 @@
|
|||||||
background-color: @bgcolor;
|
background-color: @bgcolor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.cp-toolbar-rightside {
|
||||||
|
@media screen and (max-width: @barWidth) { // 450px
|
||||||
|
flex-wrap: wrap;
|
||||||
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
.cp-toolbar-title-hoverable:hover {
|
.cp-toolbar-title-hoverable:hover {
|
||||||
.cp-toolbar-title-editable, .cp-toolbar-title-edit {
|
.cp-toolbar-title-editable, .cp-toolbar-title-edit {
|
||||||
cursor: text;
|
cursor: text;
|
||||||
@@ -192,7 +239,7 @@
|
|||||||
&.cp-app-slide {
|
&.cp-app-slide {
|
||||||
@bgcolor: @colortheme_slide-bg;
|
@bgcolor: @colortheme_slide-bg;
|
||||||
@color: @colortheme_slide-color;
|
@color: @colortheme_slide-color;
|
||||||
.addToolbarColors(@color, @bgcolor);
|
.addToolbarColors(@color, @bgcolor, 700px);
|
||||||
}
|
}
|
||||||
&.cp-app-poll {
|
&.cp-app-poll {
|
||||||
@bgcolor: @colortheme_poll-bg;
|
@bgcolor: @colortheme_poll-bg;
|
||||||
@@ -236,33 +283,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: move to the slide LESS page */
|
|
||||||
.cp-app-slide {
|
|
||||||
@media screen and (max-width: @browser_media-medium-screen) {
|
|
||||||
.cp-toolbar-leftside {
|
|
||||||
flex-flow: row wrap;
|
|
||||||
width: 175px;
|
|
||||||
height: auto;
|
|
||||||
.cp-toolbar-spinner { order: 0; }
|
|
||||||
}
|
|
||||||
.cp-toolbar-rightside {
|
|
||||||
height: 2*@toolbar_line-height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media screen and (max-width: 320px) {
|
|
||||||
.cp-toolbar-leftside {
|
|
||||||
flex-flow: row wrap;
|
|
||||||
width: 175px;
|
|
||||||
height: auto;
|
|
||||||
padding-top: @toolbar_line-height;
|
|
||||||
.cp-toolbar-spinner { order: 0; }
|
|
||||||
}
|
|
||||||
.cp-toolbar-rightside {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cp-toolbar {
|
.cp-toolbar {
|
||||||
* {
|
* {
|
||||||
outline-width: 0;
|
outline-width: 0;
|
||||||
@@ -275,6 +295,9 @@
|
|||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
//background-color: #BBBBFF;
|
//background-color: #BBBBFF;
|
||||||
background-color: @colortheme_default-bg;
|
background-color: @colortheme_default-bg;
|
||||||
@@ -437,8 +460,9 @@
|
|||||||
flex-flow: row;
|
flex-flow: row;
|
||||||
height: @toolbar_top-height;
|
height: @toolbar_top-height;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
.cp-toolbar-top-filler {
|
.cp-toolbar-top-filler {
|
||||||
height: 100%;
|
height: @toolbar_top-height;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
order: 4;
|
order: 4;
|
||||||
//flex: 1;
|
//flex: 1;
|
||||||
@@ -600,7 +624,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cp-toolbar-user {
|
.cp-toolbar-user {
|
||||||
height: 100%;
|
height: @toolbar_top-height;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
order: 5;
|
order: 5;
|
||||||
line-height: @toolbar_top-height;
|
line-height: @toolbar_top-height;
|
||||||
@@ -628,8 +652,9 @@
|
|||||||
}
|
}
|
||||||
.cp-dropdown-content {
|
.cp-dropdown-content {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
button {
|
& > button {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -675,9 +700,10 @@
|
|||||||
&:empty {
|
&:empty {
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
float: left;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
max-width: 100%;
|
||||||
|
flex: 1;
|
||||||
//margin-bottom: -1px;
|
//margin-bottom: -1px;
|
||||||
.cp-toolbar-users {
|
.cp-toolbar-users {
|
||||||
pre {
|
pre {
|
||||||
@@ -720,12 +746,6 @@
|
|||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
text-align: right;
|
text-align: right;
|
||||||
/*&> button {
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
padding: 0 10px;
|
|
||||||
}*/
|
|
||||||
.cp-toolbar-drawer-content:empty ~ .cp-toolbar-drawer-button {
|
.cp-toolbar-drawer-content:empty ~ .cp-toolbar-drawer-button {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -773,6 +793,11 @@
|
|||||||
.cp-toolbar-spinner {
|
.cp-toolbar-spinner {
|
||||||
line-height: @toolbar_line-height;
|
line-height: @toolbar_line-height;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 200px;
|
||||||
|
box-sizing: border-box;
|
||||||
&> span.fa {
|
&> span.fa {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
|||||||
@@ -36,4 +36,5 @@ body.cp-app-whiteboard { @import "../../../whiteboard/app-whiteboard.less"; }
|
|||||||
body.cp-app-todo { @import "../../../todo/app-todo.less"; }
|
body.cp-app-todo { @import "../../../todo/app-todo.less"; }
|
||||||
body.cp-app-profile { @import "../../../profile/app-profile.less"; }
|
body.cp-app-profile { @import "../../../profile/app-profile.less"; }
|
||||||
body.cp-app-settings { @import "../../../settings/app-settings.less"; }
|
body.cp-app-settings { @import "../../../settings/app-settings.less"; }
|
||||||
|
body.cp-app-debug { @import "../../../debug/app-debug.less"; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/hyperscript.js',
|
'/common/hyperscript.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/customize/pages.js',
|
'/customize/pages.js',
|
||||||
|
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
], function ($, h, Cryptpad, Pages) {
|
], function ($, h, Pages) {
|
||||||
$(function () {
|
$(function () {
|
||||||
var $body = $('body');
|
var $body = $('body');
|
||||||
var isMainApp = function () {
|
var isMainApp = function () {
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ define(function () {
|
|||||||
|
|
||||||
out.cancel = "Annuler";
|
out.cancel = "Annuler";
|
||||||
out.cancelButton = 'Annuler (Échap)';
|
out.cancelButton = 'Annuler (Échap)';
|
||||||
|
out.doNotAskAgain = "Ne plus demander (Échap)";
|
||||||
|
|
||||||
out.historyText = "Historique";
|
out.historyText = "Historique";
|
||||||
out.historyButton = "Afficher l'historique du document";
|
out.historyButton = "Afficher l'historique du document";
|
||||||
@@ -440,7 +441,7 @@ define(function () {
|
|||||||
out.login_invalPass = 'Mot de passe requis';
|
out.login_invalPass = 'Mot de passe requis';
|
||||||
out.login_unhandledError = "Une erreur inattendue s'est produite :(";
|
out.login_unhandledError = "Une erreur inattendue s'est produite :(";
|
||||||
|
|
||||||
out.register_importRecent = "Importer l'historique (Recommendé)";
|
out.register_importRecent = "Importer l'historique (Recommandé)";
|
||||||
out.register_acceptTerms = "J'accepte <a href='/terms.html' tabindex='-1'>les conditions d'utilisation</a>";
|
out.register_acceptTerms = "J'accepte <a href='/terms.html' tabindex='-1'>les conditions d'utilisation</a>";
|
||||||
out.register_passwordsDontMatch = "Les mots de passe doivent être identiques!";
|
out.register_passwordsDontMatch = "Les mots de passe doivent être identiques!";
|
||||||
out.register_passwordTooShort = "Les mots de passe doivent contenir au moins {0} caractères.";
|
out.register_passwordTooShort = "Les mots de passe doivent contenir au moins {0} caractères.";
|
||||||
@@ -488,12 +489,12 @@ define(function () {
|
|||||||
out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive";
|
out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive";
|
||||||
out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles.";
|
out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles.";
|
||||||
|
|
||||||
out.settings_thumbnails = "Vignettes";
|
out.settings_thumbnails = "Miniatures";
|
||||||
out.settings_disableThumbnailsAction = "Désactiver la création de vignettes dans CryptDrive";
|
out.settings_disableThumbnailsAction = "Désactiver la création de miniatures dans CryptDrive";
|
||||||
out.settings_disableThumbnailsDescription = "Des vignettes de vos pads sont automatiquement créées et stockées dans votre navigateur. Vous pouvez désactiver cette fonctionnalité.";
|
out.settings_disableThumbnailsDescription = "Des miniatures de vos pads sont automatiquement créées et stockées dans votre navigateur. Vous pouvez désactiver cette fonctionnalité.";
|
||||||
out.settings_resetThumbnailsAction = "Nettoyer";
|
out.settings_resetThumbnailsAction = "Nettoyer";
|
||||||
out.settings_resetThumbnailsDescription = "Nettoyer toutes les vignettes stockées dans votre navigateur.";
|
out.settings_resetThumbnailsDescription = "Nettoyer toutes les miniatures stockées dans votre navigateur.";
|
||||||
out.settings_resetThumbnailsDone = "Toutes les vignettes ont été effacées.";
|
out.settings_resetThumbnailsDone = "Toutes les miniatures ont été effacées.";
|
||||||
|
|
||||||
out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive";
|
out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive";
|
||||||
out.settings_import = "Importer";
|
out.settings_import = "Importer";
|
||||||
@@ -523,6 +524,9 @@ define(function () {
|
|||||||
out.settings_codeUseTabs = "Utiliser des tabulations au lieu d'espaces";
|
out.settings_codeUseTabs = "Utiliser des tabulations au lieu d'espaces";
|
||||||
|
|
||||||
out.upload_title = "Hébergement de fichiers";
|
out.upload_title = "Hébergement de fichiers";
|
||||||
|
out.upload_rename = "Souhaitez-vous renommer <b>{0}</b> avant son stockage en ligne ?<br>" +
|
||||||
|
"<em>L'extension du fichier ({1}) sera ajoutée automatiquement. "+
|
||||||
|
"Ce nom sera permanent et visible par les autres utilisateurs</em>.";
|
||||||
out.upload_serverError = "Erreur interne: impossible d'importer le fichier pour l'instant.";
|
out.upload_serverError = "Erreur interne: impossible d'importer le fichier pour l'instant.";
|
||||||
out.upload_uploadPending = "Vous avez déjà un fichier en cours d'importation. Souhaitez-vous l'annuler et importer ce nouveau fichier ?";
|
out.upload_uploadPending = "Vous avez déjà un fichier en cours d'importation. Souhaitez-vous l'annuler et importer ce nouveau fichier ?";
|
||||||
out.upload_success = "Votre fichier ({0}) a été importé avec succès et ajouté à votre CryptDrive.";
|
out.upload_success = "Votre fichier ({0}) a été importé avec succès et ajouté à votre CryptDrive.";
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ define(function () {
|
|||||||
|
|
||||||
out.cancel = "Cancel";
|
out.cancel = "Cancel";
|
||||||
out.cancelButton = 'Cancel (esc)';
|
out.cancelButton = 'Cancel (esc)';
|
||||||
|
out.doNotAskAgain = "Don't ask me again (Esc)";
|
||||||
|
|
||||||
out.historyText = "History";
|
out.historyText = "History";
|
||||||
out.historyButton = "Display the document history";
|
out.historyButton = "Display the document history";
|
||||||
@@ -528,6 +529,9 @@ define(function () {
|
|||||||
out.settings_codeUseTabs = "Indent using tabs (instead of spaces)";
|
out.settings_codeUseTabs = "Indent using tabs (instead of spaces)";
|
||||||
|
|
||||||
out.upload_title = "File upload";
|
out.upload_title = "File upload";
|
||||||
|
out.upload_rename = "Do you want to rename <b>{0}</b> before uploading it to the server?<br>" +
|
||||||
|
"<em>The file extension ({1}) will be added automatically. "+
|
||||||
|
"This name will be permanent and visible to other users.</em>";
|
||||||
out.upload_serverError = "Server Error: unable to upload your file at this time.";
|
out.upload_serverError = "Server Error: unable to upload your file at this time.";
|
||||||
out.upload_uploadPending = "You already have an upload in progress. Cancel it and upload your new file?";
|
out.upload_uploadPending = "You already have an upload in progress. Cancel it and upload your new file?";
|
||||||
out.upload_success = "Your file ({0}) has been successfully uploaded and added to your drive.";
|
out.upload_success = "Your file ({0}) has been successfully uploaded and added to your drive.";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cryptpad",
|
"name": "cryptpad",
|
||||||
"description": "realtime collaborative visual editor with zero knowlege server",
|
"description": "realtime collaborative visual editor with zero knowlege server",
|
||||||
"version": "1.19.0",
|
"version": "1.21.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chainpad-server": "^1.0.1",
|
"chainpad-server": "^1.0.1",
|
||||||
"express": "~4.10.1",
|
"express": "~4.10.1",
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ define([
|
|||||||
'/bower_components/hyperjson/hyperjson.js',
|
'/bower_components/hyperjson/hyperjson.js',
|
||||||
'/bower_components/textpatcher/TextPatcher.amd.js',
|
'/bower_components/textpatcher/TextPatcher.amd.js',
|
||||||
'json.sortify',
|
'json.sortify',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/drive/tests.js',
|
'/drive/tests.js',
|
||||||
'/common/test.js',
|
'/common/test.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
'/common/common-thumbnail.js',
|
'/common/common-thumbnail.js',
|
||||||
'/common/flat-dom.js',
|
'/common/flat-dom.js',
|
||||||
], function ($, Hyperjson, TextPatcher, Sortify, Cryptpad, Drive, Test, Thumb, Flat) {
|
], function ($, Hyperjson, TextPatcher, Sortify, Drive, Test, Hash, Thumb, Flat) {
|
||||||
window.Hyperjson = Hyperjson;
|
window.Hyperjson = Hyperjson;
|
||||||
window.TextPatcher = TextPatcher;
|
window.TextPatcher = TextPatcher;
|
||||||
window.Sortify = Sortify;
|
window.Sortify = Sortify;
|
||||||
@@ -158,7 +158,7 @@ define([
|
|||||||
|
|
||||||
// check that old hashes parse correctly
|
// check that old hashes parse correctly
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy');
|
var secret = Hash.parsePadUrl('/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy');
|
||||||
return cb(secret.hashData.channel === "67b8385b07352be53e40746d2be6ccd7" &&
|
return cb(secret.hashData.channel === "67b8385b07352be53e40746d2be6ccd7" &&
|
||||||
secret.hashData.key === "XAYSuJYYqa9NfmInyHci7LNy" &&
|
secret.hashData.key === "XAYSuJYYqa9NfmInyHci7LNy" &&
|
||||||
secret.hashData.version === 0);
|
secret.hashData.version === 0);
|
||||||
@@ -166,7 +166,7 @@ define([
|
|||||||
|
|
||||||
// make sure version 1 hashes parse correctly
|
// make sure version 1 hashes parse correctly
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI');
|
||||||
return cb(secret.hashData.version === 1 &&
|
return cb(secret.hashData.version === 1 &&
|
||||||
secret.hashData.mode === "edit" &&
|
secret.hashData.mode === "edit" &&
|
||||||
secret.hashData.channel === "3Ujt4F2Sjnjbis6CoYWpoQ" &&
|
secret.hashData.channel === "3Ujt4F2Sjnjbis6CoYWpoQ" &&
|
||||||
@@ -176,7 +176,7 @@ define([
|
|||||||
|
|
||||||
// test support for present mode in hashes
|
// test support for present mode in hashes
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit/CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G/present');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit/CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G/present');
|
||||||
return cb(secret.hashData.version === 1
|
return cb(secret.hashData.version === 1
|
||||||
&& secret.hashData.mode === "edit"
|
&& secret.hashData.mode === "edit"
|
||||||
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
||||||
@@ -186,7 +186,7 @@ define([
|
|||||||
|
|
||||||
// test support for present mode in hashes
|
// test support for present mode in hashes
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G//present');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G//present');
|
||||||
return cb(secret.hashData.version === 1
|
return cb(secret.hashData.version === 1
|
||||||
&& secret.hashData.mode === "edit"
|
&& secret.hashData.mode === "edit"
|
||||||
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
||||||
@@ -196,7 +196,7 @@ define([
|
|||||||
|
|
||||||
// test support for present & embed mode in hashes
|
// test support for present & embed mode in hashes
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G/embed/present/');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G/embed/present/');
|
||||||
return cb(secret.hashData.version === 1
|
return cb(secret.hashData.version === 1
|
||||||
&& secret.hashData.mode === "edit"
|
&& secret.hashData.mode === "edit"
|
||||||
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
||||||
@@ -207,7 +207,7 @@ define([
|
|||||||
|
|
||||||
// test support for present & embed mode in hashes
|
// test support for present & embed mode in hashes
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G/present/embed');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G/present/embed');
|
||||||
return cb(secret.hashData.version === 1
|
return cb(secret.hashData.version === 1
|
||||||
&& secret.hashData.mode === "edit"
|
&& secret.hashData.mode === "edit"
|
||||||
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
||||||
@@ -218,7 +218,7 @@ define([
|
|||||||
|
|
||||||
// test support for embed mode in hashes
|
// test support for embed mode in hashes
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G///embed//');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit//CmN5+YJkrHFS3NSBg-P7Sg/DNZ2wcG683GscU4fyOyqA87G///embed//');
|
||||||
return cb(secret.hashData.version === 1
|
return cb(secret.hashData.version === 1
|
||||||
&& secret.hashData.mode === "edit"
|
&& secret.hashData.mode === "edit"
|
||||||
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
&& secret.hashData.channel === "CmN5+YJkrHFS3NSBg-P7Sg"
|
||||||
@@ -229,7 +229,7 @@ define([
|
|||||||
|
|
||||||
// test support for trailing slash
|
// test support for trailing slash
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/pad/#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI/');
|
var secret = Hash.parsePadUrl('/pad/#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI/');
|
||||||
return cb(secret.hashData.version === 1 &&
|
return cb(secret.hashData.version === 1 &&
|
||||||
secret.hashData.mode === "edit" &&
|
secret.hashData.mode === "edit" &&
|
||||||
secret.hashData.channel === "3Ujt4F2Sjnjbis6CoYWpoQ" &&
|
secret.hashData.channel === "3Ujt4F2Sjnjbis6CoYWpoQ" &&
|
||||||
@@ -238,13 +238,24 @@ define([
|
|||||||
}, "test support for trailing slashes in version 1 hash failed to parse");
|
}, "test support for trailing slashes in version 1 hash failed to parse");
|
||||||
|
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var secret = Cryptpad.parsePadUrl('/invite/#/1/ilrOtygzDVoUSRpOOJrUuQ/e8jvf36S3chzkkcaMrLSW7PPrz7VDp85lIFNI26dTmr=/');
|
var secret = Hash.parsePadUrl('/invite/#/1/ilrOtygzDVoUSRpOOJrUuQ/e8jvf36S3chzkkcaMrLSW7PPrz7VDp85lIFNI26dTmr=/');
|
||||||
var hd = secret.hashData;
|
var hd = secret.hashData;
|
||||||
cb(hd.channel === "ilrOtygzDVoUSRpOOJrUuQ" &&
|
cb(hd.channel === "ilrOtygzDVoUSRpOOJrUuQ" &&
|
||||||
hd.pubkey === "e8jvf36S3chzkkcaMrLSW7PPrz7VDp85lIFNI26dTmr=" &&
|
hd.pubkey === "e8jvf36S3chzkkcaMrLSW7PPrz7VDp85lIFNI26dTmr=" &&
|
||||||
hd.type === 'invite');
|
hd.type === 'invite');
|
||||||
}, "test support for invite urls");
|
}, "test support for invite urls");
|
||||||
|
|
||||||
|
assert(function (cb) {
|
||||||
|
var url = '/pad/?utm_campaign=new_comment&utm_medium=email&utm_source=thread_mailer#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI/';
|
||||||
|
var secret = Hash.parsePadUrl(url);
|
||||||
|
|
||||||
|
return cb(secret.hashData.version === 1 &&
|
||||||
|
secret.hashData.mode === "edit" &&
|
||||||
|
secret.hashData.channel === "3Ujt4F2Sjnjbis6CoYWpoQ" &&
|
||||||
|
secret.hashData.key === "usn4+9CqVja8Q7RZOGTfRgqI" &&
|
||||||
|
!secret.hashData.present);
|
||||||
|
}, "test support for ugly tracking query paramaters in url");
|
||||||
|
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
// TODO
|
// TODO
|
||||||
return cb(true);
|
return cb(true);
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/diffMarked.js',
|
'/common/diffMarked.js',
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/common/sframe-app-framework.js',
|
'/common/sframe-app-framework.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
'/common/modes.js',
|
'/common/modes.js',
|
||||||
|
'/customize/messages.js',
|
||||||
'cm/lib/codemirror',
|
'cm/lib/codemirror',
|
||||||
|
|
||||||
'css!cm/lib/codemirror.css',
|
'css!cm/lib/codemirror.css',
|
||||||
@@ -37,17 +38,17 @@ define([
|
|||||||
|
|
||||||
], function (
|
], function (
|
||||||
$,
|
$,
|
||||||
Cryptpad,
|
|
||||||
DiffMd,
|
DiffMd,
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
Framework,
|
Framework,
|
||||||
Util,
|
Util,
|
||||||
|
Hash,
|
||||||
Modes,
|
Modes,
|
||||||
|
Messages,
|
||||||
CMeditor)
|
CMeditor)
|
||||||
{
|
{
|
||||||
window.CodeMirror = CMeditor;
|
window.CodeMirror = CMeditor;
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var MEDIA_TAG_MODES = Object.freeze([
|
var MEDIA_TAG_MODES = Object.freeze([
|
||||||
'markdown',
|
'markdown',
|
||||||
@@ -80,7 +81,11 @@ define([
|
|||||||
}, 150);
|
}, 150);
|
||||||
|
|
||||||
$previewButton.removeClass('fa-question').addClass('fa-eye');
|
$previewButton.removeClass('fa-question').addClass('fa-eye');
|
||||||
|
window.setTimeout(function () {
|
||||||
|
// setTimeout needed for tippy (tooltip), otherwise we have the browser's default
|
||||||
|
// tooltips
|
||||||
$previewButton.attr('title', Messages.previewButtonTitle);
|
$previewButton.attr('title', Messages.previewButtonTitle);
|
||||||
|
});
|
||||||
var previewTo;
|
var previewTo;
|
||||||
$previewButton.click(function () {
|
$previewButton.click(function () {
|
||||||
clearTimeout(previewTo);
|
clearTimeout(previewTo);
|
||||||
@@ -291,8 +296,8 @@ define([
|
|||||||
//var cursor = editor.getCursor();
|
//var cursor = editor.getCursor();
|
||||||
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
||||||
//var text = '';
|
//var text = '';
|
||||||
var parsed = Cryptpad.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '"></media-tag>';
|
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '"></media-tag>';
|
||||||
editor.replaceSelection(mt);
|
editor.replaceSelection(mt);
|
||||||
@@ -352,6 +357,7 @@ define([
|
|||||||
}
|
}
|
||||||
$(el).parents().css('overflow', '');
|
$(el).parents().css('overflow', '');
|
||||||
$(el).css('max-height', '');
|
$(el).css('max-height', '');
|
||||||
|
editor.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, waitFor(function (fw) { framework = fw; }));
|
}, waitFor(function (fw) { framework = fw; }));
|
||||||
|
|||||||
14
www/common/common-constants.js
Normal file
14
www/common/common-constants.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
define(function () {
|
||||||
|
return {
|
||||||
|
// localStorage
|
||||||
|
userHashKey: 'User_hash',
|
||||||
|
userNameKey: 'User_name',
|
||||||
|
fileHashKey: 'FS_hash',
|
||||||
|
// sessionStorage
|
||||||
|
newPadPathKey: "newPadPath",
|
||||||
|
// Store
|
||||||
|
displayNameKey: 'cryptpad.username',
|
||||||
|
oldStorageKey: 'CryptPad_RECENTPADS',
|
||||||
|
storageKey: 'filesData',
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -1,366 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/file/file-crypto.js',
|
|
||||||
'/common/common-thumbnail.js',
|
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
|
||||||
], function ($, FileCrypto, Thumb) {
|
|
||||||
var Nacl = window.nacl;
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
var blobToArrayBuffer = module.blobToArrayBuffer = function (blob, cb) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onloadend = function () {
|
|
||||||
cb(void 0, this.result);
|
|
||||||
};
|
|
||||||
reader.readAsArrayBuffer(blob);
|
|
||||||
};
|
|
||||||
|
|
||||||
var arrayBufferToString = function (AB) {
|
|
||||||
try {
|
|
||||||
return Nacl.util.encodeBase64(new Uint8Array(AB));
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) {
|
|
||||||
var u8 = file.blob; // This is not a blob but a uint8array
|
|
||||||
var metadata = file.metadata;
|
|
||||||
|
|
||||||
// if it exists, path contains the new pad location in the drive
|
|
||||||
var path = file.path;
|
|
||||||
|
|
||||||
var key = Nacl.randomBytes(32);
|
|
||||||
var next = FileCrypto.encrypt(u8, metadata, key);
|
|
||||||
|
|
||||||
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
|
|
||||||
|
|
||||||
var sendChunk = function (box, cb) {
|
|
||||||
var enc = Nacl.util.encodeBase64(box);
|
|
||||||
common.rpc.send.unauthenticated('UPLOAD', enc, function (e, msg) {
|
|
||||||
cb(e, msg);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var actual = 0;
|
|
||||||
var again = function (err, box) {
|
|
||||||
if (err) { throw new Error(err); }
|
|
||||||
if (box) {
|
|
||||||
actual += box.length;
|
|
||||||
var progressValue = (actual / estimate * 100);
|
|
||||||
updateProgress(progressValue);
|
|
||||||
|
|
||||||
return void sendChunk(box, function (e) {
|
|
||||||
if (e) { return console.error(e); }
|
|
||||||
next(again);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actual !== estimate) {
|
|
||||||
console.error('Estimated size does not match actual size');
|
|
||||||
}
|
|
||||||
|
|
||||||
// if not box then done
|
|
||||||
common.uploadComplete(function (e, id) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
var uri = ['', 'blob', id.slice(0,2), id].join('/');
|
|
||||||
console.log("encrypted blob is now available as %s", uri);
|
|
||||||
|
|
||||||
var b64Key = Nacl.util.encodeBase64(key);
|
|
||||||
|
|
||||||
var hash = common.getFileHashFromKeys(id, b64Key);
|
|
||||||
var href = '/file/#' + hash;
|
|
||||||
|
|
||||||
var title = metadata.name;
|
|
||||||
|
|
||||||
if (noStore) { return void onComplete(href); }
|
|
||||||
|
|
||||||
common.initialPath = path;
|
|
||||||
common.renamePad(title || "", href, function (err) {
|
|
||||||
if (err) { return void console.error(err); }
|
|
||||||
onComplete(href);
|
|
||||||
common.setPadAttribute('fileType', metadata.type, null, href);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
common.uploadStatus(estimate, function (e, pending) {
|
|
||||||
if (e) {
|
|
||||||
console.error(e);
|
|
||||||
onError(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pending) {
|
|
||||||
return void onPending(function () {
|
|
||||||
// if the user wants to cancel the pending upload to execute that one
|
|
||||||
common.uploadCancel(function (e, res) {
|
|
||||||
if (e) {
|
|
||||||
return void console.error(e);
|
|
||||||
}
|
|
||||||
console.log(res);
|
|
||||||
next(again);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
next(again);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.create = function (common, config) {
|
|
||||||
var File = {};
|
|
||||||
|
|
||||||
var Messages = common.Messages;
|
|
||||||
|
|
||||||
var queue = File.queue = {
|
|
||||||
queue: [],
|
|
||||||
inProgress: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var uid = function () {
|
|
||||||
return 'file-' + String(Math.random()).substring(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
var $table = File.$table = $('<table>', { id: 'uploadStatus' });
|
|
||||||
var $thead = $('<tr>').appendTo($table);
|
|
||||||
$('<td>').text(Messages.upload_name).appendTo($thead);
|
|
||||||
$('<td>').text(Messages.upload_size).appendTo($thead);
|
|
||||||
$('<td>').text(Messages.upload_progress).appendTo($thead);
|
|
||||||
$('<td>').text(Messages.cancel).appendTo($thead);
|
|
||||||
|
|
||||||
var createTableContainer = function ($body) {
|
|
||||||
File.$container = $('<div>', { id: 'uploadStatusContainer' }).append($table).appendTo($body);
|
|
||||||
return File.$container;
|
|
||||||
};
|
|
||||||
|
|
||||||
var getData = function (file, href) {
|
|
||||||
var data = {};
|
|
||||||
|
|
||||||
data.name = file.metadata.name;
|
|
||||||
data.url = href;
|
|
||||||
if (file.metadata.type.slice(0,6) === 'image/') {
|
|
||||||
data.mediatag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
var upload = function (file) {
|
|
||||||
var blob = file.blob; // This is not a blob but an array buffer
|
|
||||||
var u8 = new Uint8Array(blob);
|
|
||||||
var metadata = file.metadata;
|
|
||||||
var id = file.id;
|
|
||||||
if (queue.inProgress) { return; }
|
|
||||||
queue.inProgress = true;
|
|
||||||
|
|
||||||
var $row = $table.find('tr[id="'+id+'"]');
|
|
||||||
|
|
||||||
$row.find('.upCancel').html('-');
|
|
||||||
var $pv = $row.find('.progressValue');
|
|
||||||
var $pb = $row.find('.progressContainer');
|
|
||||||
var $pc = $row.find('.upProgress');
|
|
||||||
var $link = $row.find('.upLink');
|
|
||||||
|
|
||||||
var updateProgress = function (progressValue) {
|
|
||||||
$pv.text(Math.round(progressValue*100)/100 + '%');
|
|
||||||
$pb.css({
|
|
||||||
width: (progressValue/100)*$pc.width()+'px'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var onComplete = function (href) {
|
|
||||||
$link.attr('href', href)
|
|
||||||
.click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
window.open($link.attr('href'), '_blank');
|
|
||||||
});
|
|
||||||
var title = metadata.name;
|
|
||||||
common.log(Messages._getKey('upload_success', [title]));
|
|
||||||
common.prepareFeedback('upload')();
|
|
||||||
|
|
||||||
if (config.onUploaded) {
|
|
||||||
var data = getData(file, href);
|
|
||||||
config.onUploaded(file.dropEvent, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.inProgress = false;
|
|
||||||
queue.next();
|
|
||||||
};
|
|
||||||
|
|
||||||
var onError = function (e) {
|
|
||||||
queue.inProgress = false;
|
|
||||||
queue.next();
|
|
||||||
if (e === 'TOO_LARGE') {
|
|
||||||
// TODO update table to say too big?
|
|
||||||
return void common.alert(Messages.upload_tooLarge);
|
|
||||||
}
|
|
||||||
if (e === 'NOT_ENOUGH_SPACE') {
|
|
||||||
// TODO update table to say not enough space?
|
|
||||||
return void common.alert(Messages.upload_notEnoughSpace);
|
|
||||||
}
|
|
||||||
console.error(e);
|
|
||||||
return void common.alert(Messages.upload_serverError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onPending = function (cb) {
|
|
||||||
common.confirm(Messages.upload_uploadPending, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
file.blob = u8;
|
|
||||||
module.upload(file, config.noStore, common, updateProgress, onComplete, onError, onPending);
|
|
||||||
};
|
|
||||||
|
|
||||||
var prettySize = function (bytes) {
|
|
||||||
var kB = common.bytesToKilobytes(bytes);
|
|
||||||
if (kB < 1024) { return kB + Messages.KB; }
|
|
||||||
var mB = common.bytesToMegabytes(bytes);
|
|
||||||
return mB + Messages.MB;
|
|
||||||
};
|
|
||||||
|
|
||||||
queue.next = function () {
|
|
||||||
if (queue.queue.length === 0) {
|
|
||||||
queue.to = window.setTimeout(function () {
|
|
||||||
if (config.keepTable) { return; }
|
|
||||||
File.$container.fadeOut();
|
|
||||||
}, 3000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (queue.inProgress) { return; }
|
|
||||||
File.$container.show();
|
|
||||||
var file = queue.queue.shift();
|
|
||||||
upload(file);
|
|
||||||
};
|
|
||||||
queue.push = function (obj) {
|
|
||||||
var id = uid();
|
|
||||||
obj.id = id;
|
|
||||||
queue.queue.push(obj);
|
|
||||||
|
|
||||||
$table.show();
|
|
||||||
var estimate = FileCrypto.computeEncryptedSize(obj.blob.byteLength, obj.metadata);
|
|
||||||
|
|
||||||
var $progressBar = $('<div>', {'class':'progressContainer'});
|
|
||||||
var $progressValue = $('<span>', {'class':'progressValue'}).text(Messages.upload_pending);
|
|
||||||
|
|
||||||
var $tr = $('<tr>', {id: id}).appendTo($table);
|
|
||||||
|
|
||||||
var $cancel = $('<span>', {'class': 'cancel fa fa-times'}).click(function () {
|
|
||||||
queue.queue = queue.queue.filter(function (el) { return el.id !== id; });
|
|
||||||
$cancel.remove();
|
|
||||||
$tr.find('.upCancel').text('-');
|
|
||||||
$tr.find('.progressValue').text(Messages.upload_cancelled);
|
|
||||||
});
|
|
||||||
|
|
||||||
var $link = $('<a>', {
|
|
||||||
'class': 'upLink',
|
|
||||||
'rel': 'noopener noreferrer'
|
|
||||||
}).text(obj.metadata.name);
|
|
||||||
|
|
||||||
$('<td>').append($link).appendTo($tr);
|
|
||||||
$('<td>').text(prettySize(estimate)).appendTo($tr);
|
|
||||||
$('<td>', {'class': 'upProgress'}).append($progressBar).append($progressValue).appendTo($tr);
|
|
||||||
$('<td>', {'class': 'upCancel'}).append($cancel).appendTo($tr);
|
|
||||||
|
|
||||||
queue.next();
|
|
||||||
};
|
|
||||||
|
|
||||||
var handleFile = File.handleFile = function (file, e, thumbnail) {
|
|
||||||
var thumb;
|
|
||||||
var file_arraybuffer;
|
|
||||||
var finish = function () {
|
|
||||||
var metadata = {
|
|
||||||
name: file.name,
|
|
||||||
type: file.type,
|
|
||||||
};
|
|
||||||
if (thumb) { metadata.thumbnail = thumb; }
|
|
||||||
queue.push({
|
|
||||||
blob: file_arraybuffer,
|
|
||||||
metadata: metadata,
|
|
||||||
dropEvent: e
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
blobToArrayBuffer(file, function (e, buffer) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
file_arraybuffer = buffer;
|
|
||||||
if (thumbnail) { // there is already a thumbnail
|
|
||||||
return blobToArrayBuffer(thumbnail, function (e, buffer) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
thumb = arrayBufferToString(buffer);
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Thumb.isSupportedType(file.type)) { return finish(); }
|
|
||||||
// make a resized thumbnail from the image..
|
|
||||||
Thumb.fromBlob(file, function (e, thumb64) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
if (!thumb64) { return finish(); }
|
|
||||||
thumb = thumb64;
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var onFileDrop = File.onFileDrop = function (file, e) {
|
|
||||||
if (!common.isLoggedIn()) {
|
|
||||||
return common.alert(common.Messages.upload_mustLogin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array.prototype.slice.call(file).forEach(function (d) {
|
|
||||||
handleFile(d, e);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var createAreaHandlers = File.createDropArea = function ($area, $hoverArea) {
|
|
||||||
var counter = 0;
|
|
||||||
if (!$hoverArea) { $hoverArea = $area; }
|
|
||||||
if (!$area) { return; }
|
|
||||||
$hoverArea
|
|
||||||
.on('dragenter', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
counter++;
|
|
||||||
$hoverArea.addClass('hovering');
|
|
||||||
})
|
|
||||||
.on('dragleave', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
counter--;
|
|
||||||
if (counter <= 0) {
|
|
||||||
$hoverArea.removeClass('hovering');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$area
|
|
||||||
.on('drag dragstart dragend dragover drop dragenter dragleave', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
})
|
|
||||||
.on('drop', function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
var dropped = e.originalEvent.dataTransfer.files;
|
|
||||||
counter = 0;
|
|
||||||
$hoverArea.removeClass('hovering');
|
|
||||||
onFileDrop(dropped, e);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUploader = function ($area, $hover, $body) {
|
|
||||||
if (!config.noHandlers) {
|
|
||||||
createAreaHandlers($area, null);
|
|
||||||
}
|
|
||||||
createTableContainer($body);
|
|
||||||
};
|
|
||||||
|
|
||||||
createUploader(config.dropArea, config.hoverArea, config.body);
|
|
||||||
|
|
||||||
return File;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
define([
|
define([
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
'/common/common-interface.js',
|
'/customize/messages.js',
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js'
|
'/bower_components/tweetnacl/nacl-fast.min.js'
|
||||||
], function (Util, UI, Crypto) {
|
], function (Util, Messages, Crypto) {
|
||||||
var Nacl = window.nacl;
|
var Nacl = window.nacl;
|
||||||
|
|
||||||
var Hash = {};
|
var Hash = {};
|
||||||
@@ -35,8 +35,8 @@ define([
|
|||||||
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
||||||
return '/1/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
return '/1/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
||||||
};
|
};
|
||||||
Hash.getUserHrefFromKeys = function (username, pubkey) {
|
Hash.getUserHrefFromKeys = function (origin, username, pubkey) {
|
||||||
return window.location.origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
|
return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
|
||||||
};
|
};
|
||||||
|
|
||||||
var fixDuplicateSlashes = function (s) {
|
var fixDuplicateSlashes = function (s) {
|
||||||
@@ -114,6 +114,7 @@ Version 1
|
|||||||
|
|
||||||
if (!href) { return ret; }
|
if (!href) { return ret; }
|
||||||
if (href.slice(-1) !== '/') { href += '/'; }
|
if (href.slice(-1) !== '/') { href += '/'; }
|
||||||
|
href = href.replace(/\/\?[^#]+#/, '/#');
|
||||||
|
|
||||||
var idx;
|
var idx;
|
||||||
|
|
||||||
@@ -211,14 +212,12 @@ Version 1
|
|||||||
secret.keys = Crypto.createEditCryptor(parsed.key);
|
secret.keys = Crypto.createEditCryptor(parsed.key);
|
||||||
secret.key = secret.keys.editKeyStr;
|
secret.key = secret.keys.editKeyStr;
|
||||||
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
||||||
UI.alert("The channel key and/or the encryption key is invalid");
|
|
||||||
throw new Error("The channel key and/or the encryption key is invalid");
|
throw new Error("The channel key and/or the encryption key is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (parsed.mode === 'view') {
|
else if (parsed.mode === 'view') {
|
||||||
secret.keys = Crypto.createViewCryptor(parsed.key);
|
secret.keys = Crypto.createViewCryptor(parsed.key);
|
||||||
if (secret.channel.length !== 32) {
|
if (secret.channel.length !== 32) {
|
||||||
UI.alert("The channel key is invalid");
|
|
||||||
throw new Error("The channel key is invalid");
|
throw new Error("The channel key is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,5 +362,19 @@ Version 1
|
|||||||
'/' + curvePublic.replace(/\//g, '-') + '/';
|
'/' + curvePublic.replace(/\//g, '-') + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create untitled documents when no name is given
|
||||||
|
var getLocaleDate = function () {
|
||||||
|
if (window.Intl && window.Intl.DateTimeFormat) {
|
||||||
|
var options = {weekday: "short", year: "numeric", month: "long", day: "numeric"};
|
||||||
|
return new window.Intl.DateTimeFormat(undefined, options).format(new Date());
|
||||||
|
}
|
||||||
|
return new Date().toString().split(' ').slice(0,4).join(' ');
|
||||||
|
};
|
||||||
|
Hash.getDefaultName = function (parsed) {
|
||||||
|
var type = parsed.type;
|
||||||
|
var name = (Messages.type)[type] + ' - ' + getLocaleDate();
|
||||||
|
return name;
|
||||||
|
};
|
||||||
|
|
||||||
return Hash;
|
return Hash;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,266 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
|
||||||
], function ($, Crypto, ChainPad) {
|
|
||||||
var History = {};
|
|
||||||
|
|
||||||
var getStates = function (rt) {
|
|
||||||
var states = [];
|
|
||||||
var b = rt.getAuthBlock();
|
|
||||||
if (b) { states.unshift(b); }
|
|
||||||
while (b.getParent()) {
|
|
||||||
b = b.getParent();
|
|
||||||
states.unshift(b);
|
|
||||||
}
|
|
||||||
return states;
|
|
||||||
};
|
|
||||||
|
|
||||||
var loadHistory = function (config, common, cb) {
|
|
||||||
var network = common.getNetwork();
|
|
||||||
var hkn = network.historyKeeper;
|
|
||||||
|
|
||||||
var wcId = common.hrefToHexChannelId(config.href || window.location.href);
|
|
||||||
|
|
||||||
var createRealtime = function () {
|
|
||||||
return ChainPad.create({
|
|
||||||
userName: 'history',
|
|
||||||
initialState: '',
|
|
||||||
patchTransformer: ChainPad.NaiveJSONStransformer,
|
|
||||||
logLevel: 0,
|
|
||||||
noPrune: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var realtime = createRealtime();
|
|
||||||
|
|
||||||
var parsed = config.href ? common.parsePadUrl(config.href) : {};
|
|
||||||
var secret = common.getSecrets(parsed.type, parsed.hash);
|
|
||||||
|
|
||||||
History.readOnly = 0;
|
|
||||||
if (!secret.keys) {
|
|
||||||
secret.keys = secret.key;
|
|
||||||
History.readOnly = 0;
|
|
||||||
}
|
|
||||||
else if (!secret.keys.validateKey) {
|
|
||||||
History.readOnly = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var crypto = Crypto.createEncryptor(secret.keys);
|
|
||||||
|
|
||||||
var to = window.setTimeout(function () {
|
|
||||||
cb('[GET_FULL_HISTORY_TIMEOUT]');
|
|
||||||
}, 30000);
|
|
||||||
|
|
||||||
var parse = function (msg) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(msg);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var onMsg = function (msg) {
|
|
||||||
var parsed = parse(msg);
|
|
||||||
if (parsed[0] === 'FULL_HISTORY_END') {
|
|
||||||
console.log('END');
|
|
||||||
window.clearTimeout(to);
|
|
||||||
cb(null, realtime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parsed[0] !== 'FULL_HISTORY') { return; }
|
|
||||||
if (parsed[1] && parsed[1].validateKey) { // First message
|
|
||||||
secret.keys.validateKey = parsed[1].validateKey;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
msg = parsed[1][4];
|
|
||||||
if (msg) {
|
|
||||||
msg = msg.replace(/^cp\|/, '');
|
|
||||||
var decryptedMsg = crypto.decrypt(msg, secret.keys.validateKey);
|
|
||||||
realtime.message(decryptedMsg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
network.on('message', function (msg) {
|
|
||||||
onMsg(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
network.sendto(hkn, JSON.stringify(['GET_FULL_HISTORY', wcId, secret.keys.validateKey]));
|
|
||||||
};
|
|
||||||
|
|
||||||
History.create = function (common, config) {
|
|
||||||
if (!config.$toolbar) { return void console.error("config.$toolbar is undefined");}
|
|
||||||
if (History.loading) { return void console.error("History is already being loaded..."); }
|
|
||||||
History.loading = true;
|
|
||||||
var $toolbar = config.$toolbar;
|
|
||||||
|
|
||||||
if (!config.applyVal || !config.setHistory || !config.onLocal || !config.onRemote) {
|
|
||||||
throw new Error("Missing config element: applyVal, onLocal, onRemote, setHistory");
|
|
||||||
}
|
|
||||||
|
|
||||||
// config.setHistory(bool, bool)
|
|
||||||
// - bool1: history value
|
|
||||||
// - bool2: reset old content?
|
|
||||||
var render = function (val) {
|
|
||||||
if (typeof val === "undefined") { return; }
|
|
||||||
try {
|
|
||||||
config.applyVal(val);
|
|
||||||
} catch (e) {
|
|
||||||
// Probably a parse error
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var onClose = function () { config.setHistory(false, true); };
|
|
||||||
var onRevert = function () {
|
|
||||||
config.setHistory(false, false);
|
|
||||||
config.onLocal();
|
|
||||||
config.onRemote();
|
|
||||||
};
|
|
||||||
var onReady = function () {
|
|
||||||
config.setHistory(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
var Messages = common.Messages;
|
|
||||||
|
|
||||||
var realtime;
|
|
||||||
|
|
||||||
var states = [];
|
|
||||||
var c = states.length - 1;
|
|
||||||
|
|
||||||
var $hist = $toolbar.find('.cryptpad-toolbar-history');
|
|
||||||
var $left = $toolbar.find('.cryptpad-toolbar-leftside');
|
|
||||||
var $right = $toolbar.find('.cryptpad-toolbar-rightside');
|
|
||||||
var $cke = $toolbar.find('.cke_toolbox_main');
|
|
||||||
|
|
||||||
$hist.html('').show();
|
|
||||||
$left.hide();
|
|
||||||
$right.hide();
|
|
||||||
$cke.hide();
|
|
||||||
|
|
||||||
common.spinner($hist).get().show();
|
|
||||||
|
|
||||||
var onUpdate;
|
|
||||||
|
|
||||||
var update = function () {
|
|
||||||
if (!realtime) { return []; }
|
|
||||||
states = getStates(realtime);
|
|
||||||
if (typeof onUpdate === "function") { onUpdate(); }
|
|
||||||
return states;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the content of the selected version, and change the version number
|
|
||||||
var get = function (i) {
|
|
||||||
i = parseInt(i);
|
|
||||||
if (isNaN(i)) { return; }
|
|
||||||
if (i < 0) { i = 0; }
|
|
||||||
if (i > states.length - 1) { i = states.length - 1; }
|
|
||||||
var val = states[i].getContent().doc;
|
|
||||||
c = i;
|
|
||||||
if (typeof onUpdate === "function") { onUpdate(); }
|
|
||||||
$hist.find('.next, .previous').css('visibility', '');
|
|
||||||
if (c === states.length - 1) { $hist.find('.next').css('visibility', 'hidden'); }
|
|
||||||
if (c === 0) { $hist.find('.previous').css('visibility', 'hidden'); }
|
|
||||||
return val || '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var getNext = function (step) {
|
|
||||||
return typeof step === "number" ? get(c + step) : get(c + 1);
|
|
||||||
};
|
|
||||||
var getPrevious = function (step) {
|
|
||||||
return typeof step === "number" ? get(c - step) : get(c - 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the history toolbar
|
|
||||||
var display = function () {
|
|
||||||
$hist.html('');
|
|
||||||
var $prev =$('<button>', {
|
|
||||||
'class': 'previous fa fa-step-backward buttonPrimary',
|
|
||||||
title: Messages.history_prev
|
|
||||||
}).appendTo($hist);
|
|
||||||
var $nav = $('<div>', {'class': 'goto'}).appendTo($hist);
|
|
||||||
var $next = $('<button>', {
|
|
||||||
'class': 'next fa fa-step-forward buttonPrimary',
|
|
||||||
title: Messages.history_next
|
|
||||||
}).appendTo($hist);
|
|
||||||
|
|
||||||
$('<label>').text(Messages.history_version).appendTo($nav);
|
|
||||||
var $cur = $('<input>', {
|
|
||||||
'class' : 'gotoInput',
|
|
||||||
'type' : 'number',
|
|
||||||
'min' : '1',
|
|
||||||
'max' : states.length
|
|
||||||
}).val(c + 1).appendTo($nav).mousedown(function (e) {
|
|
||||||
// stopPropagation because the event would be cancelled by the dropdown menus
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
var $label2 = $('<label>').text(' / '+ states.length).appendTo($nav);
|
|
||||||
$('<br>').appendTo($nav);
|
|
||||||
var $close = $('<button>', {
|
|
||||||
'class':'closeHistory',
|
|
||||||
title: Messages.history_closeTitle
|
|
||||||
}).text(Messages.history_closeTitle).appendTo($nav);
|
|
||||||
var $rev = $('<button>', {
|
|
||||||
'class':'revertHistory buttonSuccess',
|
|
||||||
title: Messages.history_restoreTitle
|
|
||||||
}).text(Messages.history_restore).appendTo($nav);
|
|
||||||
if (History.readOnly) { $rev.hide(); }
|
|
||||||
|
|
||||||
onUpdate = function () {
|
|
||||||
$cur.attr('max', states.length);
|
|
||||||
$cur.val(c+1);
|
|
||||||
$label2.text(' / ' + states.length);
|
|
||||||
};
|
|
||||||
|
|
||||||
var close = function () {
|
|
||||||
$hist.hide();
|
|
||||||
$left.show();
|
|
||||||
$right.show();
|
|
||||||
$cke.show();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Buttons actions
|
|
||||||
$prev.click(function () { render(getPrevious()); });
|
|
||||||
$next.click(function () { render(getNext()); });
|
|
||||||
$cur.keydown(function (e) {
|
|
||||||
var p = function () { e.preventDefault(); };
|
|
||||||
if (e.which === 13) { p(); return render( get($cur.val() - 1) ); } // Enter
|
|
||||||
if ([37, 40].indexOf(e.which) >= 0) { p(); return render(getPrevious()); } // Left
|
|
||||||
if ([38, 39].indexOf(e.which) >= 0) { p(); return render(getNext()); } // Right
|
|
||||||
if (e.which === 33) { p(); return render(getNext(10)); } // PageUp
|
|
||||||
if (e.which === 34) { p(); return render(getPrevious(10)); } // PageUp
|
|
||||||
if (e.which === 27) { p(); $close.click(); }
|
|
||||||
}).keyup(function (e) { e.stopPropagation(); }).focus();
|
|
||||||
$cur.on('change', function () {
|
|
||||||
render( get($cur.val() - 1) );
|
|
||||||
});
|
|
||||||
$close.click(function () {
|
|
||||||
states = [];
|
|
||||||
close();
|
|
||||||
onClose();
|
|
||||||
});
|
|
||||||
$rev.click(function () {
|
|
||||||
common.confirm(Messages.history_restorePrompt, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
close();
|
|
||||||
onRevert();
|
|
||||||
common.log(Messages.history_restoreDone);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Display the latest content
|
|
||||||
render(get(c));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load all the history messages into a new chainpad object
|
|
||||||
loadHistory(config, common, function (err, newRt) {
|
|
||||||
History.loading = false;
|
|
||||||
if (err) { throw new Error(err); }
|
|
||||||
realtime = newRt;
|
|
||||||
update();
|
|
||||||
c = states.length - 1;
|
|
||||||
display();
|
|
||||||
onReady();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return History;
|
|
||||||
});
|
|
||||||
|
|
||||||
@@ -2,16 +2,17 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-notifier.js',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/bower_components/alertifyjs/dist/js/alertify.js',
|
'/bower_components/alertifyjs/dist/js/alertify.js',
|
||||||
'/common/notify.js',
|
|
||||||
'/common/visible.js',
|
|
||||||
'/common/tippy.min.js',
|
'/common/tippy.min.js',
|
||||||
'/customize/pages.js',
|
'/customize/pages.js',
|
||||||
'/common/hyperscript.js',
|
'/common/hyperscript.js',
|
||||||
'/bower_components/bootstrap-tokenfield/dist/bootstrap-tokenfield.js',
|
'/bower_components/bootstrap-tokenfield/dist/bootstrap-tokenfield.js',
|
||||||
'css!/common/tippy.css',
|
'css!/common/tippy.css',
|
||||||
], function ($, Messages, Util, AppConfig, Alertify, Notify, Visible, Tippy, Pages, h) {
|
], function ($, Messages, Util, Hash, Notifier, AppConfig,
|
||||||
|
Alertify, Tippy, Pages, h) {
|
||||||
var UI = {};
|
var UI = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -270,7 +271,7 @@ define([
|
|||||||
document.body.appendChild(frame);
|
document.body.appendChild(frame);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
$ok.focus();
|
$ok.focus();
|
||||||
UI.notify();
|
Notifier.notify();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -318,7 +319,7 @@ define([
|
|||||||
document.body.appendChild(frame);
|
document.body.appendChild(frame);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
$(input).select().focus();
|
$(input).select().focus();
|
||||||
UI.notify();
|
Notifier.notify();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -365,7 +366,7 @@ define([
|
|||||||
|
|
||||||
document.body.appendChild(frame);
|
document.body.appendChild(frame);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
UI.notify();
|
Notifier.notify();
|
||||||
$(frame).find('.ok').focus();
|
$(frame).find('.ok').focus();
|
||||||
if (typeof(opt.done) === 'function') {
|
if (typeof(opt.done) === 'function') {
|
||||||
opt.done($ok.closest('.dialog'));
|
opt.done($ok.closest('.dialog'));
|
||||||
@@ -468,44 +469,6 @@ define([
|
|||||||
$('#' + LOADING).find('p').html(error || Messages.error);
|
$('#' + LOADING).find('p').html(error || Messages.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Notify
|
|
||||||
var notify = {};
|
|
||||||
UI.unnotify = function () {
|
|
||||||
if (notify.tabNotification &&
|
|
||||||
typeof(notify.tabNotification.cancel) === 'function') {
|
|
||||||
notify.tabNotification.cancel();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
UI.notify = function () {
|
|
||||||
if (Visible.isSupported() && !Visible.currently()) {
|
|
||||||
UI.unnotify();
|
|
||||||
notify.tabNotification = Notify.tab(1000, 10);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Visible.isSupported()) {
|
|
||||||
Visible.onChange(function (yes) {
|
|
||||||
if (yes) { UI.unnotify(); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
UI.importContent = function (type, f, cfg) {
|
|
||||||
return function () {
|
|
||||||
var $files = $('<input>', {type:"file"});
|
|
||||||
if (cfg && cfg.accept) {
|
|
||||||
$files.attr('accept', cfg.accept);
|
|
||||||
}
|
|
||||||
$files.click();
|
|
||||||
$files.on('change', function (e) {
|
|
||||||
var file = e.target.files[0];
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onload = function (e) { f(e.target.result, file); };
|
|
||||||
reader.readAsText(file, type);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var $defaultIcon = $('<span>', {"class": "fa fa-file-text-o"});
|
var $defaultIcon = $('<span>', {"class": "fa fa-file-text-o"});
|
||||||
UI.getIcon = function (type) {
|
UI.getIcon = function (type) {
|
||||||
var $icon = $defaultIcon.clone();
|
var $icon = $defaultIcon.clone();
|
||||||
@@ -517,6 +480,17 @@ define([
|
|||||||
|
|
||||||
return $icon;
|
return $icon;
|
||||||
};
|
};
|
||||||
|
UI.getFileIcon = function (data) {
|
||||||
|
var $icon = UI.getIcon();
|
||||||
|
if (!data) { return $icon; }
|
||||||
|
var href = data.href;
|
||||||
|
if (!href) { return $icon; }
|
||||||
|
|
||||||
|
var type = Hash.parsePadUrl(href).type;
|
||||||
|
$icon = UI.getIcon(type);
|
||||||
|
|
||||||
|
return $icon;
|
||||||
|
};
|
||||||
|
|
||||||
// Tooltips
|
// Tooltips
|
||||||
|
|
||||||
@@ -524,11 +498,8 @@ define([
|
|||||||
// If an element is removed from the UI while a tooltip is applied on that element, the tooltip will get hung
|
// If an element is removed from the UI while a tooltip is applied on that element, the tooltip will get hung
|
||||||
// forever, this is a solution which just searches for tooltips which have no corrisponding element and removes
|
// forever, this is a solution which just searches for tooltips which have no corrisponding element and removes
|
||||||
// them.
|
// them.
|
||||||
var win;
|
|
||||||
$('.tippy-popper').each(function (i, el) {
|
$('.tippy-popper').each(function (i, el) {
|
||||||
win = win || $('#pad-iframe').length? $('#pad-iframe')[0].contentWindow: undefined;
|
if ($('[aria-describedby=' + el.getAttribute('id') + ']').length === 0) {
|
||||||
if (!win) { return; }
|
|
||||||
if (win.$('[aria-describedby=' + el.getAttribute('id') + ']').length === 0) {
|
|
||||||
el.remove();
|
el.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -536,52 +507,54 @@ define([
|
|||||||
|
|
||||||
UI.addTooltips = function () {
|
UI.addTooltips = function () {
|
||||||
var MutationObserver = window.MutationObserver;
|
var MutationObserver = window.MutationObserver;
|
||||||
var addTippy = function (el) {
|
|
||||||
if (el.nodeName === 'IFRAME') { return; }
|
|
||||||
var delay = typeof(AppConfig.tooltipDelay) === "number" ? AppConfig.tooltipDelay : 500;
|
var delay = typeof(AppConfig.tooltipDelay) === "number" ? AppConfig.tooltipDelay : 500;
|
||||||
|
var addTippy = function (i, el) {
|
||||||
|
if (el.nodeName === 'IFRAME') { return; }
|
||||||
Tippy(el, {
|
Tippy(el, {
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
distance: 0,
|
distance: 0,
|
||||||
performance: true,
|
performance: true,
|
||||||
dynamicTitle: true,
|
dynamicTitle: true,
|
||||||
delay: [delay, 0]
|
delay: [delay, 0],
|
||||||
|
sticky: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var $body = $('body');
|
// This is the robust solution to remove dangling tooltips
|
||||||
var $padIframe = $('#pad-iframe').contents().find('body');
|
// The mutation observer does not always find removed nodes.
|
||||||
$('[title]').each(function (i, el) {
|
setInterval(UI.clearTooltips, delay);
|
||||||
addTippy(el);
|
var checkRemoved = function (x) {
|
||||||
});
|
var out = false;
|
||||||
$('#pad-iframe').contents().find('[title]').each(function (i, el) {
|
$(x).find('[aria-describedby]').each(function (i, el) {
|
||||||
addTippy(el);
|
var id = el.getAttribute('aria-describedby');
|
||||||
|
if (id.indexOf('tippy-tooltip-') !== 0) { return; }
|
||||||
|
out = true;
|
||||||
});
|
});
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
$('[title]').each(addTippy);
|
||||||
var observer = new MutationObserver(function(mutations) {
|
var observer = new MutationObserver(function(mutations) {
|
||||||
|
var removed = false;
|
||||||
mutations.forEach(function(mutation) {
|
mutations.forEach(function(mutation) {
|
||||||
if (mutation.type === 'childList' && mutation.addedNodes.length) {
|
if (mutation.type === "childList") {
|
||||||
$body.find('[title]').each(function (i, el) {
|
for (var i = 0; i < mutation.addedNodes.length; i++) {
|
||||||
addTippy(el);
|
$(mutation.addedNodes[i]).find('[title]').each(addTippy);
|
||||||
});
|
}
|
||||||
if (!$padIframe.length) { return; }
|
for (var j = 0; j < mutation.removedNodes.length; j++) {
|
||||||
$padIframe.find('[title]').each(function (i, el) {
|
removed |= checkRemoved(mutation.removedNodes[j]);
|
||||||
addTippy(el);
|
}
|
||||||
});
|
}
|
||||||
|
if (mutation.type === "attributes" && mutation.attributeName === "title") {
|
||||||
|
addTippy(0, mutation.target);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (removed) { UI.clearTooltips(); }
|
||||||
});
|
});
|
||||||
observer.observe($('body')[0], {
|
observer.observe($('body')[0], {
|
||||||
attributes: false,
|
attributes: true,
|
||||||
childList: true,
|
childList: true,
|
||||||
characterData: false,
|
characterData: false,
|
||||||
subtree: true
|
subtree: true
|
||||||
});
|
});
|
||||||
if ($('#pad-iframe').length) {
|
|
||||||
observer.observe($('#pad-iframe').contents().find('body')[0], {
|
|
||||||
attributes: false,
|
|
||||||
childList: true,
|
|
||||||
characterData: false,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return UI;
|
return UI;
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ define([
|
|||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/curve.js',
|
'/common/curve.js',
|
||||||
'/common/common-hash.js',
|
'/common/common-hash.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'/bower_components/marked/marked.min.js',
|
'/bower_components/marked/marked.min.js',
|
||||||
'/common/common-realtime.js',
|
'/common/common-realtime.js',
|
||||||
], function ($, Crypto, Curve, Hash, Marked, Realtime) {
|
], function ($, Crypto, Curve, Hash, Util, Constants, Messages, Marked, Realtime) {
|
||||||
var Msg = {
|
var Msg = {
|
||||||
inputs: [],
|
inputs: [],
|
||||||
};
|
};
|
||||||
@@ -80,13 +83,13 @@ define([
|
|||||||
|
|
||||||
friends[pubKey] = data;
|
friends[pubKey] = data;
|
||||||
|
|
||||||
Realtime.whenRealtimeSyncs(common, common.getRealtime(), function () {
|
Realtime.whenRealtimeSyncs(common.getRealtime(), function () {
|
||||||
cb();
|
cb();
|
||||||
common.pinPads([data.channel], function (e) {
|
common.pinPads([data.channel], function (e) {
|
||||||
if (e) { console.error(e); }
|
if (e) { console.error(e); }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
common.changeDisplayName(proxy[common.displayNameKey]);
|
common.changeDisplayName(proxy[Constants.displayNameKey]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Used to accept friend requests within apps other than /contacts/ */
|
/* Used to accept friend requests within apps other than /contacts/ */
|
||||||
@@ -98,7 +101,7 @@ define([
|
|||||||
var msg;
|
var msg;
|
||||||
if (sender === network.historyKeeper) { return; }
|
if (sender === network.historyKeeper) { return; }
|
||||||
try {
|
try {
|
||||||
var parsed = common.parsePadUrl(window.location.href);
|
var parsed = Hash.parsePadUrl(window.location.href);
|
||||||
if (!parsed.hashData) { return; }
|
if (!parsed.hashData) { return; }
|
||||||
var chan = parsed.hashData.channel;
|
var chan = parsed.hashData.channel;
|
||||||
// Decrypt
|
// Decrypt
|
||||||
@@ -132,11 +135,11 @@ define([
|
|||||||
todo(true);
|
todo(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var confirmMsg = common.Messages._getKey('contacts_request', [
|
var confirmMsg = Messages._getKey('contacts_request', [
|
||||||
common.fixHTML(msgData.displayName)
|
Util.fixHTML(msgData.displayName)
|
||||||
]);
|
]);
|
||||||
common.onFriendRequest(confirmMsg, todo);
|
common.onFriendRequest(confirmMsg, todo);
|
||||||
//common.confirm(confirmMsg, todo, null, true);
|
//UI.confirm(confirmMsg, todo, null, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg[0] === "FRIEND_REQ_OK") {
|
if (msg[0] === "FRIEND_REQ_OK") {
|
||||||
@@ -147,12 +150,12 @@ define([
|
|||||||
addToFriendList(common, msgData, function (err) {
|
addToFriendList(common, msgData, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return void common.onFriendComplete({
|
return void common.onFriendComplete({
|
||||||
logText: common.Messages.contacts_addError,
|
logText: Messages.contacts_addError,
|
||||||
netfluxId: sender
|
netfluxId: sender
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
common.onFriendComplete({
|
common.onFriendComplete({
|
||||||
logText: common.Messages.contacts_added,
|
logText: Messages.contacts_added,
|
||||||
netfluxId: sender
|
netfluxId: sender
|
||||||
});
|
});
|
||||||
var msg = ["FRIEND_REQ_ACK", chan];
|
var msg = ["FRIEND_REQ_ACK", chan];
|
||||||
@@ -165,10 +168,10 @@ define([
|
|||||||
var i = pendingRequests.indexOf(sender);
|
var i = pendingRequests.indexOf(sender);
|
||||||
if (i !== -1) { pendingRequests.splice(i, 1); }
|
if (i !== -1) { pendingRequests.splice(i, 1); }
|
||||||
common.onFriendComplete({
|
common.onFriendComplete({
|
||||||
logText: common.Messages.contacts_rejected,
|
logText: Messages.contacts_rejected,
|
||||||
netfluxId: sender
|
netfluxId: sender
|
||||||
});
|
});
|
||||||
common.changeDisplayName(proxy[common.displayNameKey]);
|
common.changeDisplayName(proxy[Constants.displayNameKey]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg[0] === "FRIEND_REQ_ACK") {
|
if (msg[0] === "FRIEND_REQ_ACK") {
|
||||||
@@ -177,12 +180,12 @@ define([
|
|||||||
addToFriendList(common, data, function (err) {
|
addToFriendList(common, data, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return void common.onFriendComplete({
|
return void common.onFriendComplete({
|
||||||
logText: common.Messages.contacts_addError,
|
logText: Messages.contacts_addError,
|
||||||
netfluxId: sender
|
netfluxId: sender
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
common.onFriendComplete({
|
common.onFriendComplete({
|
||||||
logText: common.Messages.contacts_added,
|
logText: Messages.contacts_added,
|
||||||
netfluxId: sender
|
netfluxId: sender
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -201,7 +204,7 @@ define([
|
|||||||
|
|
||||||
Msg.inviteFromUserlist = function (common, netfluxId) {
|
Msg.inviteFromUserlist = function (common, netfluxId) {
|
||||||
var network = common.getNetwork();
|
var network = common.getNetwork();
|
||||||
var parsed = common.parsePadUrl(window.location.href);
|
var parsed = Hash.parsePadUrl(window.location.href);
|
||||||
if (!parsed.hashData) { return; }
|
if (!parsed.hashData) { return; }
|
||||||
// Message
|
// Message
|
||||||
var chan = parsed.hashData.channel;
|
var chan = parsed.hashData.channel;
|
||||||
@@ -218,7 +221,7 @@ define([
|
|||||||
var proxy = common.getProxy();
|
var proxy = common.getProxy();
|
||||||
// this redraws the userlist after a change has occurred
|
// this redraws the userlist after a change has occurred
|
||||||
// TODO rename this function to reflect its purpose
|
// TODO rename this function to reflect its purpose
|
||||||
common.changeDisplayName(proxy[common.displayNameKey]);
|
common.changeDisplayName(proxy[Constants.displayNameKey]);
|
||||||
}
|
}
|
||||||
network.sendto(netfluxId, msgStr);
|
network.sendto(netfluxId, msgStr);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ define([
|
|||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/curve.js',
|
'/common/curve.js',
|
||||||
'/common/common-hash.js',
|
'/common/common-hash.js',
|
||||||
], function ($, Crypto, Curve, Hash) {
|
'/common/common-util.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
], function ($, Crypto, Curve, Hash, Util, Realtime) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var Msg = {
|
var Msg = {
|
||||||
inputs: [],
|
inputs: [],
|
||||||
@@ -48,21 +50,6 @@ define([
|
|||||||
return proxy.friends;
|
return proxy.friends;
|
||||||
};
|
};
|
||||||
|
|
||||||
var eachFriend = function (friends, cb) {
|
|
||||||
Object.keys(friends).forEach(function (id) {
|
|
||||||
if (id === 'me') { return; }
|
|
||||||
cb(friends[id], id, friends);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Msg.getFriendChannelsList = function (proxy) {
|
|
||||||
var list = [];
|
|
||||||
eachFriend(proxy, function (friend) {
|
|
||||||
list.push(friend.channel);
|
|
||||||
});
|
|
||||||
return list;
|
|
||||||
};
|
|
||||||
|
|
||||||
var msgAlreadyKnown = function (channel, sig) {
|
var msgAlreadyKnown = function (channel, sig) {
|
||||||
return channel.messages.some(function (message) {
|
return channel.messages.some(function (message) {
|
||||||
return message[0] === sig;
|
return message[0] === sig;
|
||||||
@@ -149,7 +136,7 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var txid = common.uid();
|
var txid = Util.uid();
|
||||||
initRangeRequest(txid, curvePublic, hash, cb);
|
initRangeRequest(txid, curvePublic, hash, cb);
|
||||||
var msg = [ 'GET_HISTORY_RANGE', chan.id, {
|
var msg = [ 'GET_HISTORY_RANGE', chan.id, {
|
||||||
from: hash,
|
from: hash,
|
||||||
@@ -245,7 +232,7 @@ define([
|
|||||||
if (!proxy.friends) { return; }
|
if (!proxy.friends) { return; }
|
||||||
var friends = proxy.friends;
|
var friends = proxy.friends;
|
||||||
delete friends[curvePublic];
|
delete friends[curvePublic];
|
||||||
common.whenRealtimeSyncs(realtime, cb);
|
Realtime.whenRealtimeSyncs(realtime, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
var pushMsg = function (channel, cryptMsg) {
|
var pushMsg = function (channel, cryptMsg) {
|
||||||
@@ -352,7 +339,7 @@ define([
|
|||||||
return cb();
|
return cb();
|
||||||
};
|
};
|
||||||
|
|
||||||
var onDirectMessage = function (common, msg, sender) {
|
var onDirectMessage = function (msg, sender) {
|
||||||
if (sender !== Msg.hk) { return void onIdMessage(msg, sender); }
|
if (sender !== Msg.hk) { return void onIdMessage(msg, sender); }
|
||||||
var parsed = JSON.parse(msg);
|
var parsed = JSON.parse(msg);
|
||||||
|
|
||||||
@@ -443,7 +430,7 @@ define([
|
|||||||
|
|
||||||
// listen for messages...
|
// listen for messages...
|
||||||
network.on('message', function(msg, sender) {
|
network.on('message', function(msg, sender) {
|
||||||
onDirectMessage(common, msg, sender);
|
onDirectMessage(msg, sender);
|
||||||
});
|
});
|
||||||
|
|
||||||
messenger.removeFriend = function (curvePublic, cb) {
|
messenger.removeFriend = function (curvePublic, cb) {
|
||||||
@@ -476,7 +463,7 @@ define([
|
|||||||
channel.wc.bcast(cryptMsg).then(function () {
|
channel.wc.bcast(cryptMsg).then(function () {
|
||||||
delete friends[curvePublic];
|
delete friends[curvePublic];
|
||||||
delete channels[curvePublic];
|
delete channels[curvePublic];
|
||||||
common.whenRealtimeSyncs(realtime, function () {
|
Realtime.whenRealtimeSyncs(realtime, function () {
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
@@ -646,6 +633,13 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
messenger.clearOwnedChannel = function (channel, cb) {
|
||||||
|
common.clearOwnedChannel(channel, function (e) {
|
||||||
|
if (e) { return void cb(e); }
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// TODO listen for changes to your friend list
|
// TODO listen for changes to your friend list
|
||||||
// emit 'update' events for clients
|
// emit 'update' events for clients
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
define(function () {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (UserList, Title, cfg, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
exp.update = function (shjson) {
|
|
||||||
// Extract the user list (metadata) from the hyperjson
|
|
||||||
var json = (!shjson || typeof shjson !== "string") ? "" : JSON.parse(shjson);
|
|
||||||
var titleUpdated = false;
|
|
||||||
var metadata;
|
|
||||||
if (Array.isArray(json)) {
|
|
||||||
metadata = json[3] && json[3].metadata;
|
|
||||||
} else {
|
|
||||||
metadata = json.metadata;
|
|
||||||
}
|
|
||||||
if (typeof metadata === "object") {
|
|
||||||
if (Cryptpad) {
|
|
||||||
if (typeof(metadata.type) === 'undefined') {
|
|
||||||
// initialize pad type by location.pathname
|
|
||||||
metadata.type = Cryptpad.getAppType();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log("Cryptpad should exist but it does not");
|
|
||||||
}
|
|
||||||
if (metadata.users) {
|
|
||||||
var userData = metadata.users;
|
|
||||||
// Update the local user data
|
|
||||||
UserList.addToUserData(userData);
|
|
||||||
}
|
|
||||||
if (metadata.defaultTitle) {
|
|
||||||
Title.updateDefaultTitle(metadata.defaultTitle);
|
|
||||||
}
|
|
||||||
if (typeof metadata.title !== "undefined") {
|
|
||||||
Title.updateTitle(metadata.title || Title.defaultTitle);
|
|
||||||
titleUpdated = true;
|
|
||||||
}
|
|
||||||
if (metadata.slideOptions && cfg.slideOptions) {
|
|
||||||
cfg.slideOptions(metadata.slideOptions);
|
|
||||||
}
|
|
||||||
if (metadata.color && cfg.slideColors) {
|
|
||||||
cfg.slideColors(metadata.color, metadata.backColor);
|
|
||||||
}
|
|
||||||
if (typeof(metadata.palette) !== 'undefined' && cfg.updatePalette) {
|
|
||||||
cfg.updatePalette(metadata.palette);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!titleUpdated) {
|
|
||||||
Title.updateTitle(Title.defaultTitle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
29
www/common/common-notifier.js
Normal file
29
www/common/common-notifier.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
define([
|
||||||
|
'/common/visible.js',
|
||||||
|
'/common/notify.js'
|
||||||
|
], function (Visible, Notify) {
|
||||||
|
var Notifier = {};
|
||||||
|
|
||||||
|
var notify = {};
|
||||||
|
Notifier.unnotify = function () {
|
||||||
|
if (notify.tabNotification &&
|
||||||
|
typeof(notify.tabNotification.cancel) === 'function') {
|
||||||
|
notify.tabNotification.cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Notifier.notify = function () {
|
||||||
|
if (Visible.isSupported() && !Visible.currently()) {
|
||||||
|
Notifier.unnotify();
|
||||||
|
notify.tabNotification = Notify.tab(1000, 10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Visible.isSupported()) {
|
||||||
|
Visible.onChange(function (yes) {
|
||||||
|
if (yes) { Notifier.unnotify(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Notifier;
|
||||||
|
});
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
define([
|
define([
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
], function (AppConfig, Messages) {
|
'/common/common-interface.js',
|
||||||
|
], function (AppConfig, Messages, UI) {
|
||||||
var common = {};
|
var common = {};
|
||||||
|
|
||||||
common.infiniteSpinnerDetected = false;
|
common.infiniteSpinnerDetected = false;
|
||||||
@@ -15,7 +16,7 @@ define([
|
|||||||
/*
|
/*
|
||||||
TODO make this not blow up when disconnected or lagging...
|
TODO make this not blow up when disconnected or lagging...
|
||||||
*/
|
*/
|
||||||
common.whenRealtimeSyncs = function (Cryptpad, realtime, cb) {
|
common.whenRealtimeSyncs = function (realtime, cb) {
|
||||||
if (typeof(realtime.getAuthDoc) !== 'function') {
|
if (typeof(realtime.getAuthDoc) !== 'function') {
|
||||||
return void console.error('improper use of this function');
|
return void console.error('improper use of this function');
|
||||||
}
|
}
|
||||||
@@ -28,7 +29,7 @@ define([
|
|||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
common.beginDetectingInfiniteSpinner = function (Cryptpad, realtime) {
|
common.beginDetectingInfiniteSpinner = function (realtime) {
|
||||||
if (intr) { return; }
|
if (intr) { return; }
|
||||||
intr = window.setInterval(function () {
|
intr = window.setInterval(function () {
|
||||||
var l;
|
var l;
|
||||||
@@ -44,7 +45,7 @@ define([
|
|||||||
infiniteSpinnerHandlers.forEach(function (ish) { ish(); });
|
infiniteSpinnerHandlers.forEach(function (ish) { ish(); });
|
||||||
|
|
||||||
// inform the user their session is in a bad state
|
// inform the user their session is in a bad state
|
||||||
Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
window.parent.location.reload();
|
window.parent.location.reload();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ define([
|
|||||||
|
|
||||||
var ctx = c2.getContext('2d');
|
var ctx = c2.getContext('2d');
|
||||||
ctx.drawImage(canvas, D.x, D.y, D.w, D.h);
|
ctx.drawImage(canvas, D.x, D.y, D.w, D.h);
|
||||||
|
|
||||||
cb(void 0, c2.toDataURL());
|
cb(void 0, c2.toDataURL());
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,19 +125,15 @@ define([
|
|||||||
Thumb.fromVideoBlob = function (blob, cb) {
|
Thumb.fromVideoBlob = function (blob, cb) {
|
||||||
var url = URL.createObjectURL(blob);
|
var url = URL.createObjectURL(blob);
|
||||||
var video = document.createElement("VIDEO");
|
var video = document.createElement("VIDEO");
|
||||||
|
|
||||||
video.src = url;
|
|
||||||
video.addEventListener('loadedmetadata', function() {
|
|
||||||
video.currentTime = Number(Math.floor(Math.min(video.duration/10, 5)));
|
|
||||||
video.addEventListener('loadeddata', function() {
|
video.addEventListener('loadeddata', function() {
|
||||||
var D = getResizedDimensions(video, 'video');
|
var D = getResizedDimensions(video, 'video');
|
||||||
Thumb.fromCanvas(video, D, cb);
|
Thumb.fromCanvas(video, D, cb);
|
||||||
});
|
}, false);
|
||||||
});
|
|
||||||
video.addEventListener('error', function (e) {
|
video.addEventListener('error', function (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
cb('ERROR');
|
cb('ERROR');
|
||||||
});
|
});
|
||||||
|
video.src = url;
|
||||||
};
|
};
|
||||||
Thumb.fromPdfBlob = function (blob, cb) {
|
Thumb.fromPdfBlob = function (blob, cb) {
|
||||||
require.config({paths: {'pdfjs-dist': '/common/pdfjs'}});
|
require.config({paths: {'pdfjs-dist': '/common/pdfjs'}});
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
define(['jquery'], function ($) {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (cfg, onLocal, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
var parsed = exp.parsedHref = Cryptpad.parsePadUrl(window.location.href);
|
|
||||||
exp.defaultTitle = Cryptpad.getDefaultName(parsed);
|
|
||||||
|
|
||||||
exp.title = document.title; // TOOD slides
|
|
||||||
|
|
||||||
cfg = cfg || {};
|
|
||||||
|
|
||||||
var getHeadingText = cfg.getHeadingText || function () { return; };
|
|
||||||
var updateLocalTitle = function (newTitle) {
|
|
||||||
exp.title = newTitle;
|
|
||||||
onLocal();
|
|
||||||
if (typeof cfg.updateLocalTitle === "function") {
|
|
||||||
cfg.updateLocalTitle(newTitle);
|
|
||||||
} else {
|
|
||||||
document.title = newTitle;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var $title;
|
|
||||||
exp.setToolbar = function (toolbar) {
|
|
||||||
$title = toolbar && toolbar.title;
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getTitle = function () { return exp.title; };
|
|
||||||
var isDefaultTitle = exp.isDefaultTitle = function (){return exp.title === exp.defaultTitle;};
|
|
||||||
|
|
||||||
var suggestTitle = exp.suggestTitle = function (fallback) {
|
|
||||||
if (isDefaultTitle()) {
|
|
||||||
return getHeadingText() || fallback || "";
|
|
||||||
} else {
|
|
||||||
return exp.title || getHeadingText() || exp.defaultTitle;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var renameCb = function (err, newTitle) {
|
|
||||||
if (err) { return; }
|
|
||||||
updateLocalTitle(newTitle);
|
|
||||||
onLocal();
|
|
||||||
};
|
|
||||||
|
|
||||||
// update title: href is optional; if not specified, we use window.location.href
|
|
||||||
exp.updateTitle = function (newTitle, href, cb) {
|
|
||||||
cb = cb || $.noop;
|
|
||||||
if (newTitle === exp.title) { return; }
|
|
||||||
// Change the title now, and set it back to the old value if there is an error
|
|
||||||
var oldTitle = exp.title;
|
|
||||||
Cryptpad.renamePad(newTitle, href, function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set pad title");
|
|
||||||
console.error(err);
|
|
||||||
updateLocalTitle(oldTitle);
|
|
||||||
return void cb(err);
|
|
||||||
}
|
|
||||||
updateLocalTitle(data);
|
|
||||||
cb(null, data);
|
|
||||||
if (!$title) { return; }
|
|
||||||
$title.find('span.title').text(data);
|
|
||||||
$title.find('input').val(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.updateDefaultTitle = function (newDefaultTitle) {
|
|
||||||
exp.defaultTitle = newDefaultTitle;
|
|
||||||
if (!$title) { return; }
|
|
||||||
$title.find('input').attr("placeholder", exp.defaultTitle);
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getTitleConfig = function () {
|
|
||||||
return {
|
|
||||||
onRename: renameCb,
|
|
||||||
suggestName: suggestTitle,
|
|
||||||
defaultName: exp.defaultTitle
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
|
|
||||||
@@ -3,42 +3,26 @@ define([
|
|||||||
'/api/config',
|
'/api/config',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
'/common/common-language.js',
|
'/common/common-language.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
'/common/media-tag.js',
|
'/common/media-tag.js',
|
||||||
'/common/tippy.min.js',
|
|
||||||
'/customize/application_config.js',
|
|
||||||
|
|
||||||
'css!/common/tippy.css',
|
'css!/common/tippy.css',
|
||||||
], function ($, Config, Cryptpad, Util, Language, MediaTag, Tippy, AppConfig) {
|
], function ($, Config, Cryptpad, Util, Hash, Language, UI, MediaTag) {
|
||||||
var UI = {};
|
var UIElements = {};
|
||||||
var Messages = Cryptpad.Messages;
|
var Messages = Cryptpad.Messages;
|
||||||
|
|
||||||
/**
|
UIElements.updateTags = function (common, href) {
|
||||||
* Requirements from cryptpad-common.js
|
|
||||||
* getFileSize
|
|
||||||
* - hrefToHexChannelId
|
|
||||||
* displayAvatar
|
|
||||||
* - getFirstEmojiOrCharacter
|
|
||||||
* - parsePadUrl
|
|
||||||
* - getSecrets
|
|
||||||
* - base64ToHex
|
|
||||||
* - getBlobPathFromHex
|
|
||||||
* - bytesToMegabytes
|
|
||||||
* createUserAdminMenu
|
|
||||||
* - fixHTML
|
|
||||||
* - createDropdown
|
|
||||||
*/
|
|
||||||
|
|
||||||
UI.updateTags = function (common, href) {
|
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
sframeChan.query('Q_TAGS_GET', href || null, function (err, res) {
|
sframeChan.query('Q_TAGS_GET', href || null, function (err, res) {
|
||||||
if (err || res.error) {
|
if (err || res.error) {
|
||||||
if (res.error === 'NO_ENTRY') {
|
if (res.error === 'NO_ENTRY') {
|
||||||
Cryptpad.alert(Messages.tags_noentry);
|
UI.alert(Messages.tags_noentry);
|
||||||
}
|
}
|
||||||
return void console.error(err || res.error);
|
return void console.error(err || res.error);
|
||||||
}
|
}
|
||||||
Cryptpad.dialog.tagPrompt(res.data, function (tags) {
|
UI.dialog.tagPrompt(res.data, function (tags) {
|
||||||
if (!Array.isArray(tags)) { return; }
|
if (!Array.isArray(tags)) { return; }
|
||||||
sframeChan.event('EV_TAGS_SET', {
|
sframeChan.event('EV_TAGS_SET', {
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@@ -48,7 +32,23 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.createButton = function (common, type, rightside, data, callback) {
|
var importContent = function (type, f, cfg) {
|
||||||
|
return function () {
|
||||||
|
var $files = $('<input>', {type:"file"});
|
||||||
|
if (cfg && cfg.accept) {
|
||||||
|
$files.attr('accept', cfg.accept);
|
||||||
|
}
|
||||||
|
$files.click();
|
||||||
|
$files.on('change', function (e) {
|
||||||
|
var file = e.target.files[0];
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function (e) { f(e.target.result, file); };
|
||||||
|
reader.readAsText(file, type);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
UIElements.createButton = function (common, type, rightside, data, callback) {
|
||||||
var AppConfig = common.getAppConfig();
|
var AppConfig = common.getAppConfig();
|
||||||
var button;
|
var button;
|
||||||
var size = "17px";
|
var size = "17px";
|
||||||
@@ -73,7 +73,7 @@ define([
|
|||||||
if (callback) {
|
if (callback) {
|
||||||
button
|
button
|
||||||
.click(common.prepareFeedback(type))
|
.click(common.prepareFeedback(type))
|
||||||
.click(Cryptpad.importContent('text/plain', function (content, file) {
|
.click(importContent('text/plain', function (content, file) {
|
||||||
callback(content, file);
|
callback(content, file);
|
||||||
}, {accept: data ? data.accept : undefined}));
|
}, {accept: data ? data.accept : undefined}));
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ define([
|
|||||||
target: data.target
|
target: data.target
|
||||||
};
|
};
|
||||||
if (data.filter && !data.filter(file)) {
|
if (data.filter && !data.filter(file)) {
|
||||||
Cryptpad.log('Invalid avatar (type or size)');
|
UI.log('Invalid avatar (type or size)');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data.FM.handleFile(file, ev);
|
data.FM.handleFile(file, ev);
|
||||||
@@ -142,11 +142,11 @@ define([
|
|||||||
title: title,
|
title: title,
|
||||||
toSave: toSave
|
toSave: toSave
|
||||||
}, function () {
|
}, function () {
|
||||||
Cryptpad.alert(Messages.templateSaved);
|
UI.alert(Messages.templateSaved);
|
||||||
common.feedback('TEMPLATE_CREATED');
|
common.feedback('TEMPLATE_CREATED');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Cryptpad.prompt(Messages.saveTemplatePrompt, title, todo);
|
UI.prompt(Messages.saveTemplatePrompt, title, todo);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -162,12 +162,12 @@ define([
|
|||||||
.click(common.prepareFeedback(type))
|
.click(common.prepareFeedback(type))
|
||||||
.click(function() {
|
.click(function() {
|
||||||
var msg = common.isLoggedIn() ? Messages.forgetPrompt : Messages.fm_removePermanentlyDialog;
|
var msg = common.isLoggedIn() ? Messages.forgetPrompt : Messages.fm_removePermanentlyDialog;
|
||||||
Cryptpad.confirm(msg, function (yes) {
|
UI.confirm(msg, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
sframeChan.query('Q_MOVE_TO_TRASH', null, function (err) {
|
sframeChan.query('Q_MOVE_TO_TRASH', null, function (err) {
|
||||||
if (err) { return void callback(err); }
|
if (err) { return void callback(err); }
|
||||||
var cMsg = common.isLoggedIn() ? Messages.movedToTrash : Messages.deleted;
|
var cMsg = common.isLoggedIn() ? Messages.movedToTrash : Messages.deleted;
|
||||||
Cryptpad.alert(cMsg, undefined, true);
|
UI.alert(cMsg, undefined, true);
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
@@ -220,7 +220,7 @@ define([
|
|||||||
title: Messages.tags_title,
|
title: Messages.tags_title,
|
||||||
})
|
})
|
||||||
.click(common.prepareFeedback(type))
|
.click(common.prepareFeedback(type))
|
||||||
.click(function () { UI.updateTags(common, null); });
|
.click(function () { UIElements.updateTags(common, null); });
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
button = $('<button>', {
|
button = $('<button>', {
|
||||||
@@ -236,7 +236,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Avatars
|
// Avatars
|
||||||
UI.displayMediatagImage = function (Common, $tag, cb) {
|
UIElements.displayMediatagImage = function (Common, $tag, cb) {
|
||||||
if (!$tag.length || !$tag.is('media-tag')) { return void cb('NOT_MEDIATAG'); }
|
if (!$tag.length || !$tag.is('media-tag')) { return void cb('NOT_MEDIATAG'); }
|
||||||
var observer = new MutationObserver(function(mutations) {
|
var observer = new MutationObserver(function(mutations) {
|
||||||
mutations.forEach(function(mutation) {
|
mutations.forEach(function(mutation) {
|
||||||
@@ -267,31 +267,52 @@ define([
|
|||||||
});
|
});
|
||||||
MediaTag($tag[0]);
|
MediaTag($tag[0]);
|
||||||
};
|
};
|
||||||
UI.displayAvatar = function (Common, $container, href, name, cb) {
|
|
||||||
|
var emoji_patt = /([\uD800-\uDBFF][\uDC00-\uDFFF])/;
|
||||||
|
var isEmoji = function (str) {
|
||||||
|
return emoji_patt.test(str);
|
||||||
|
};
|
||||||
|
var emojiStringToArray = function (str) {
|
||||||
|
var split = str.split(emoji_patt);
|
||||||
|
var arr = [];
|
||||||
|
for (var i=0; i<split.length; i++) {
|
||||||
|
var char = split[i];
|
||||||
|
if (char !== "") {
|
||||||
|
arr.push(char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
var getFirstEmojiOrCharacter = function (str) {
|
||||||
|
if (!str || !str.trim()) { return '?'; }
|
||||||
|
var emojis = emojiStringToArray(str);
|
||||||
|
return isEmoji(emojis[0])? emojis[0]: str[0];
|
||||||
|
};
|
||||||
|
UIElements.displayAvatar = function (Common, $container, href, name, cb) {
|
||||||
var displayDefault = function () {
|
var displayDefault = function () {
|
||||||
var text = Cryptpad.getFirstEmojiOrCharacter(name);
|
var text = getFirstEmojiOrCharacter(name);
|
||||||
var $avatar = $('<span>', {'class': 'cp-avatar-default'}).text(text);
|
var $avatar = $('<span>', {'class': 'cp-avatar-default'}).text(text);
|
||||||
$container.append($avatar);
|
$container.append($avatar);
|
||||||
if (cb) { cb(); }
|
if (cb) { cb(); }
|
||||||
};
|
};
|
||||||
if (!href) { return void displayDefault(); }
|
if (!href) { return void displayDefault(); }
|
||||||
var parsed = Cryptpad.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var secret = Cryptpad.getSecrets('file', parsed.hash);
|
var secret = Hash.getSecrets('file', parsed.hash);
|
||||||
if (secret.keys && secret.channel) {
|
if (secret.keys && secret.channel) {
|
||||||
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||||
var hexFileName = Cryptpad.base64ToHex(secret.channel);
|
var hexFileName = Util.base64ToHex(secret.channel);
|
||||||
var src = Cryptpad.getBlobPathFromHex(hexFileName);
|
var src = Hash.getBlobPathFromHex(hexFileName);
|
||||||
Common.getFileSize(href, function (e, data) {
|
Common.getFileSize(href, function (e, data) {
|
||||||
if (e) {
|
if (e) {
|
||||||
displayDefault();
|
displayDefault();
|
||||||
return void console.error(e);
|
return void console.error(e);
|
||||||
}
|
}
|
||||||
if (typeof data !== "number") { return void displayDefault(); }
|
if (typeof data !== "number") { return void displayDefault(); }
|
||||||
if (Cryptpad.bytesToMegabytes(data) > 0.5) { return void displayDefault(); }
|
if (Util.bytesToMegabytes(data) > 0.5) { return void displayDefault(); }
|
||||||
var $img = $('<media-tag>').appendTo($container);
|
var $img = $('<media-tag>').appendTo($container);
|
||||||
$img.attr('src', src);
|
$img.attr('src', src);
|
||||||
$img.attr('data-crypto-key', 'cryptpad:' + cryptKey);
|
$img.attr('data-crypto-key', 'cryptpad:' + cryptKey);
|
||||||
UI.displayMediatagImage(Common, $img, function (err, $image, img) {
|
UIElements.displayMediatagImage(Common, $img, function (err, $image, img) {
|
||||||
if (err) { return void console.error(err); }
|
if (err) { return void console.error(err); }
|
||||||
var w = img.width;
|
var w = img.width;
|
||||||
var h = img.height;
|
var h = img.height;
|
||||||
@@ -317,13 +338,13 @@ define([
|
|||||||
update.
|
update.
|
||||||
*/
|
*/
|
||||||
var LIMIT_REFRESH_RATE = 30000; // milliseconds
|
var LIMIT_REFRESH_RATE = 30000; // milliseconds
|
||||||
UI.createUsageBar = function (common, cb) {
|
UIElements.createUsageBar = function (common, cb) {
|
||||||
if (!common.isLoggedIn()) { return cb("NOT_LOGGED_IN"); }
|
if (!common.isLoggedIn()) { return cb("NOT_LOGGED_IN"); }
|
||||||
// getPinnedUsage updates common.account.usage, and other values
|
// getPinnedUsage updates common.account.usage, and other values
|
||||||
// so we can just use those and only check for errors
|
// so we can just use those and only check for errors
|
||||||
var $container = $('<span>', {'class':'cp-limit-container'});
|
var $container = $('<span>', {'class':'cp-limit-container'});
|
||||||
var todo;
|
var todo;
|
||||||
var updateUsage = Cryptpad.notAgainForAnother(function () {
|
var updateUsage = Util.notAgainForAnother(function () {
|
||||||
common.getPinUsage(todo);
|
common.getPinUsage(todo);
|
||||||
}, LIMIT_REFRESH_RATE);
|
}, LIMIT_REFRESH_RATE);
|
||||||
|
|
||||||
@@ -404,23 +425,174 @@ define([
|
|||||||
cb(null, $container);
|
cb(null, $container);
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.createUserAdminMenu = function (Common, config) {
|
// Create a button with a dropdown menu
|
||||||
|
// input is a config object with parameters:
|
||||||
|
// - container (optional): the dropdown container (span)
|
||||||
|
// - text (optional): the button text value
|
||||||
|
// - options: array of {tag: "", attributes: {}, content: "string"}
|
||||||
|
//
|
||||||
|
// allowed options tags: ['a', 'hr', 'p']
|
||||||
|
UIElements.createDropdown = function (config) {
|
||||||
|
if (typeof config !== "object" || !Array.isArray(config.options)) { return; }
|
||||||
|
|
||||||
|
var allowedTags = ['a', 'p', 'hr'];
|
||||||
|
var isValidOption = function (o) {
|
||||||
|
if (typeof o !== "object") { return false; }
|
||||||
|
if (!o.tag || allowedTags.indexOf(o.tag) === -1) { return false; }
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Container
|
||||||
|
var $container = $(config.container);
|
||||||
|
var containerConfig = {
|
||||||
|
'class': 'cp-dropdown-container'
|
||||||
|
};
|
||||||
|
if (config.buttonTitle) {
|
||||||
|
containerConfig.title = config.buttonTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.container) {
|
||||||
|
$container = $('<span>', containerConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button
|
||||||
|
var $button = $('<button>', {
|
||||||
|
'class': ''
|
||||||
|
}).append($('<span>', {'class': 'cp-dropdown-button-title'}).html(config.text || ""));
|
||||||
|
/*$('<span>', {
|
||||||
|
'class': 'fa fa-caret-down',
|
||||||
|
}).appendTo($button);*/
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
var $innerblock = $('<div>', {'class': 'cp-dropdown-content'});
|
||||||
|
if (config.left) { $innerblock.addClass('cp-dropdown-left'); }
|
||||||
|
|
||||||
|
config.options.forEach(function (o) {
|
||||||
|
if (!isValidOption(o)) { return; }
|
||||||
|
$('<' + o.tag + '>', o.attributes || {}).html(o.content || '').appendTo($innerblock);
|
||||||
|
});
|
||||||
|
|
||||||
|
$container.append($button).append($innerblock);
|
||||||
|
|
||||||
|
var value = config.initialValue || '';
|
||||||
|
|
||||||
|
var setActive = function ($el) {
|
||||||
|
if ($el.length !== 1) { return; }
|
||||||
|
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
|
||||||
|
$el.addClass('cp-dropdown-element-active');
|
||||||
|
var scroll = $el.position().top + $innerblock.scrollTop();
|
||||||
|
if (scroll < $innerblock.scrollTop()) {
|
||||||
|
$innerblock.scrollTop(scroll);
|
||||||
|
} else if (scroll > ($innerblock.scrollTop() + 280)) {
|
||||||
|
$innerblock.scrollTop(scroll-270);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var hide = function () {
|
||||||
|
window.setTimeout(function () { $innerblock.hide(); }, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
var show = function () {
|
||||||
|
$innerblock.show();
|
||||||
|
$innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active');
|
||||||
|
if (config.isSelect && value) {
|
||||||
|
var $val = $innerblock.find('[data-value="'+value+'"]');
|
||||||
|
setActive($val);
|
||||||
|
$innerblock.scrollTop($val.position().top + $innerblock.scrollTop());
|
||||||
|
}
|
||||||
|
if (config.feedback) { Cryptpad.feedback(config.feedback); }
|
||||||
|
};
|
||||||
|
|
||||||
|
$container.click(function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
var state = $innerblock.is(':visible');
|
||||||
|
$('.cp-dropdown-content').hide();
|
||||||
|
try {
|
||||||
|
$('iframe').each(function (idx, ifrw) {
|
||||||
|
$(ifrw).contents().find('.cp-dropdown-content').hide();
|
||||||
|
});
|
||||||
|
} catch (er) {
|
||||||
|
// empty try catch in case this iframe is problematic (cross-origin)
|
||||||
|
}
|
||||||
|
if (state) {
|
||||||
|
hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
show();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.isSelect) {
|
||||||
|
var pressed = '';
|
||||||
|
var to;
|
||||||
|
$container.keydown(function (e) {
|
||||||
|
var $value = $innerblock.find('[data-value].cp-dropdown-element-active');
|
||||||
|
if (e.which === 38) { // Up
|
||||||
|
if ($value.length) {
|
||||||
|
var $prev = $value.prev();
|
||||||
|
setActive($prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.which === 40) { // Down
|
||||||
|
if ($value.length) {
|
||||||
|
var $next = $value.next();
|
||||||
|
setActive($next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.which === 13) { //Enter
|
||||||
|
if ($value.length) {
|
||||||
|
$value.click();
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.which === 27) { // Esc
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$container.keypress(function (e) {
|
||||||
|
window.clearTimeout(to);
|
||||||
|
var c = String.fromCharCode(e.which);
|
||||||
|
pressed += c;
|
||||||
|
var $value = $innerblock.find('[data-value^="'+pressed+'"]:first');
|
||||||
|
if ($value.length) {
|
||||||
|
setActive($value);
|
||||||
|
$innerblock.scrollTop($value.position().top + $innerblock.scrollTop());
|
||||||
|
}
|
||||||
|
to = window.setTimeout(function () {
|
||||||
|
pressed = '';
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
$container.setValue = function (val, name) {
|
||||||
|
value = val;
|
||||||
|
var $val = $innerblock.find('[data-value="'+val+'"]');
|
||||||
|
var textValue = name || $val.html() || val;
|
||||||
|
$button.find('.cp-dropdown-button-title').html(textValue);
|
||||||
|
};
|
||||||
|
$container.getValue = function () {
|
||||||
|
return value || '';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return $container;
|
||||||
|
};
|
||||||
|
|
||||||
|
UIElements.createUserAdminMenu = function (Common, config) {
|
||||||
var metadataMgr = Common.getMetadataMgr();
|
var metadataMgr = Common.getMetadataMgr();
|
||||||
|
|
||||||
var displayNameCls = config.displayNameCls || 'displayName';
|
var displayNameCls = config.displayNameCls || 'cp-toolbar-user-name';
|
||||||
var $displayedName = $('<span>', {'class': displayNameCls});
|
var $displayedName = $('<span>', {'class': displayNameCls});
|
||||||
|
|
||||||
var accountName = metadataMgr.getPrivateData().accountName;
|
var accountName = metadataMgr.getPrivateData().accountName;
|
||||||
var origin = metadataMgr.getPrivateData().origin;
|
var origin = metadataMgr.getPrivateData().origin;
|
||||||
var padType = metadataMgr.getMetadata().type;
|
var padType = metadataMgr.getMetadata().type;
|
||||||
|
|
||||||
var $userName = $('<span>', {'class': 'userDisplayName'});
|
var $userName = $('<span>');
|
||||||
var options = [];
|
var options = [];
|
||||||
if (config.displayNameCls) {
|
if (config.displayNameCls) {
|
||||||
var $userAdminContent = $('<p>');
|
var $userAdminContent = $('<p>');
|
||||||
if (accountName) {
|
if (accountName) {
|
||||||
var $userAccount = $('<span>', {'class': 'userAccount'}).append(Messages.user_accountName + ': ' + Cryptpad.fixHTML(accountName));
|
var $userAccount = $('<span>').append(Messages.user_accountName + ': ');
|
||||||
$userAdminContent.append($userAccount);
|
$userAdminContent.append($userAccount).append(Util.fixHTML(accountName));
|
||||||
$userAdminContent.append($('<br>'));
|
$userAdminContent.append($('<br>'));
|
||||||
}
|
}
|
||||||
if (config.displayName) {
|
if (config.displayName) {
|
||||||
@@ -456,14 +628,14 @@ define([
|
|||||||
if (accountName) {
|
if (accountName) {
|
||||||
options.push({
|
options.push({
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
attributes: {'class': 'profile'},
|
attributes: {'class': 'cp-toolbar-menu-profile'},
|
||||||
content: Messages.profileButton
|
content: Messages.profileButton
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (padType !== 'settings') {
|
if (padType !== 'settings') {
|
||||||
options.push({
|
options.push({
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
attributes: {'class': 'settings'},
|
attributes: {'class': 'cp-toolbar-menu-settings'},
|
||||||
content: Messages.settingsButton
|
content: Messages.settingsButton
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -471,18 +643,18 @@ define([
|
|||||||
if (accountName) {
|
if (accountName) {
|
||||||
options.push({
|
options.push({
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
attributes: {'class': 'logout'},
|
attributes: {'class': 'cp-toolbar-menu-logout'},
|
||||||
content: Messages.logoutButton
|
content: Messages.logoutButton
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
options.push({
|
options.push({
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
attributes: {'class': 'login'},
|
attributes: {'class': 'cp-toolbar-menu-login'},
|
||||||
content: Messages.login_login
|
content: Messages.login_login
|
||||||
});
|
});
|
||||||
options.push({
|
options.push({
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
attributes: {'class': 'register'},
|
attributes: {'class': 'cp-toolbar-menu-register'},
|
||||||
content: Messages.login_register
|
content: Messages.login_register
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -505,11 +677,18 @@ define([
|
|||||||
container: config.$initBlock, // optional
|
container: config.$initBlock, // optional
|
||||||
feedback: "USER_ADMIN",
|
feedback: "USER_ADMIN",
|
||||||
};
|
};
|
||||||
var $userAdmin = Cryptpad.createDropdown(dropdownConfigUser);
|
var $userAdmin = UIElements.createDropdown(dropdownConfigUser);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Uncomment these lines to have a language selector in the admin menu
|
||||||
|
// FIXME clicking on the inner menu hides the outer one
|
||||||
|
var $lang = UIElements.createLanguageSelector(Common);
|
||||||
|
$userAdmin.find('.cp-dropdown-content').append($lang);
|
||||||
|
*/
|
||||||
|
|
||||||
var $displayName = $userAdmin.find('.'+displayNameCls);
|
var $displayName = $userAdmin.find('.'+displayNameCls);
|
||||||
|
|
||||||
var $avatar = $userAdmin.find('.cp-dropdown-button-title');
|
var $avatar = $userAdmin.find('> button .cp-dropdown-button-title');
|
||||||
var loadingAvatar;
|
var loadingAvatar;
|
||||||
var to;
|
var to;
|
||||||
var oldUrl = '';
|
var oldUrl = '';
|
||||||
@@ -528,10 +707,11 @@ define([
|
|||||||
$displayName.text(newName || Messages.anonymous);
|
$displayName.text(newName || Messages.anonymous);
|
||||||
if (accountName && oldUrl !== url) {
|
if (accountName && oldUrl !== url) {
|
||||||
$avatar.html('');
|
$avatar.html('');
|
||||||
UI.displayAvatar(Common, $avatar, url, newName || Messages.anonymous, function ($img) {
|
UIElements.displayAvatar(Common, $avatar, url,
|
||||||
|
newName || Messages.anonymous, function ($img) {
|
||||||
oldUrl = url;
|
oldUrl = url;
|
||||||
if ($img) {
|
if ($img) {
|
||||||
$userAdmin.find('button').addClass('cp-avatar');
|
$userAdmin.find('> button').addClass('cp-avatar');
|
||||||
}
|
}
|
||||||
loadingAvatar = false;
|
loadingAvatar = false;
|
||||||
});
|
});
|
||||||
@@ -542,31 +722,31 @@ define([
|
|||||||
metadataMgr.onChange(updateButton);
|
metadataMgr.onChange(updateButton);
|
||||||
updateButton();
|
updateButton();
|
||||||
|
|
||||||
$userAdmin.find('a.logout').click(function () {
|
$userAdmin.find('a.cp-toolbar-menu-logout').click(function () {
|
||||||
Common.logout(function () {
|
Common.logout(function () {
|
||||||
window.parent.location = origin+'/';
|
window.parent.location = origin+'/';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
$userAdmin.find('a.settings').click(function () {
|
$userAdmin.find('a.cp-toolbar-menu-settings').click(function () {
|
||||||
if (padType) {
|
if (padType) {
|
||||||
window.open(origin+'/settings/');
|
window.open(origin+'/settings/');
|
||||||
} else {
|
} else {
|
||||||
window.parent.location = origin+'/settings/';
|
window.parent.location = origin+'/settings/';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$userAdmin.find('a.profile').click(function () {
|
$userAdmin.find('a.cp-toolbar-menu-profile').click(function () {
|
||||||
if (padType) {
|
if (padType) {
|
||||||
window.open(origin+'/profile/');
|
window.open(origin+'/profile/');
|
||||||
} else {
|
} else {
|
||||||
window.parent.location = origin+'/profile/';
|
window.parent.location = origin+'/profile/';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$userAdmin.find('a.login').click(function () {
|
$userAdmin.find('a.cp-toolbar-menu-login').click(function () {
|
||||||
Common.setLoginRedirect(function () {
|
Common.setLoginRedirect(function () {
|
||||||
window.parent.location = origin+'/login/';
|
window.parent.location = origin+'/login/';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
$userAdmin.find('a.register').click(function () {
|
$userAdmin.find('a.cp-toolbar-menu-register').click(function () {
|
||||||
Common.setLoginRedirect(function () {
|
Common.setLoginRedirect(function () {
|
||||||
window.parent.location = origin+'/register/';
|
window.parent.location = origin+'/register/';
|
||||||
});
|
});
|
||||||
@@ -577,7 +757,7 @@ define([
|
|||||||
|
|
||||||
// Provide $container if you want to put the generated block in another element
|
// Provide $container if you want to put the generated block in another element
|
||||||
// Provide $initBlock if you already have the menu block and you want the content inserted in it
|
// Provide $initBlock if you already have the menu block and you want the content inserted in it
|
||||||
UI.createLanguageSelector = function (common, $container, $initBlock) {
|
UIElements.createLanguageSelector = function (common, $container, $initBlock) {
|
||||||
var options = [];
|
var options = [];
|
||||||
var languages = Messages._languages;
|
var languages = Messages._languages;
|
||||||
var keys = Object.keys(languages).sort();
|
var keys = Object.keys(languages).sort();
|
||||||
@@ -599,7 +779,7 @@ define([
|
|||||||
container: $initBlock, // optional
|
container: $initBlock, // optional
|
||||||
isSelect: true
|
isSelect: true
|
||||||
};
|
};
|
||||||
var $block = Cryptpad.createDropdown(dropdownConfig);
|
var $block = UIElements.createDropdown(dropdownConfig);
|
||||||
$block.attr('id', 'cp-language-selector');
|
$block.attr('id', 'cp-language-selector');
|
||||||
|
|
||||||
if ($container) {
|
if ($container) {
|
||||||
@@ -611,20 +791,51 @@ define([
|
|||||||
return $block;
|
return $block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UIElements.createModal = function (cfg) {
|
||||||
|
var $body = cfg.$body || $('body');
|
||||||
|
var $blockContainer = $body.find('#'+cfg.id);
|
||||||
|
if (!$blockContainer.length) {
|
||||||
|
$blockContainer = $('<div>', {
|
||||||
|
'class': 'cp-modal-container',
|
||||||
|
'id': cfg.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var hide = function () {
|
||||||
|
if (cfg.onClose) { return void cfg.onClose(); }
|
||||||
|
$blockContainer.hide();
|
||||||
|
};
|
||||||
|
$blockContainer.html('').appendTo($body);
|
||||||
|
var $block = $('<div>', {'class': 'cp-modal'}).appendTo($blockContainer);
|
||||||
|
$('<span>', {
|
||||||
|
'class': 'cp-modal-close fa fa-times',
|
||||||
|
'title': Messages.filePicker_close
|
||||||
|
}).click(hide).appendTo($block);
|
||||||
|
$body.click(hide);
|
||||||
|
$block.click(function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
$body.keydown(function (e) {
|
||||||
|
if (e.which === 27) {
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return $blockContainer;
|
||||||
|
};
|
||||||
|
|
||||||
UI.initFilePicker = function (common, cfg) {
|
|
||||||
|
UIElements.initFilePicker = function (common, cfg) {
|
||||||
var onSelect = cfg.onSelect || $.noop;
|
var onSelect = cfg.onSelect || $.noop;
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
sframeChan.on("EV_FILE_PICKED", function (data) {
|
sframeChan.on("EV_FILE_PICKED", function (data) {
|
||||||
onSelect(data);
|
onSelect(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
UI.openFilePicker = function (common, types) {
|
UIElements.openFilePicker = function (common, types) {
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
sframeChan.event("EV_FILE_PICKER_OPEN", types);
|
sframeChan.event("EV_FILE_PICKER_OPEN", types);
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.openTemplatePicker = function (common) {
|
UIElements.openTemplatePicker = function (common) {
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
var type = metadataMgr.getMetadataLazy().type;
|
var type = metadataMgr.getMetadataLazy().type;
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
@@ -646,10 +857,10 @@ define([
|
|||||||
var fileDialogCfg = {
|
var fileDialogCfg = {
|
||||||
onSelect: function (data) {
|
onSelect: function (data) {
|
||||||
if (data.type === type && first) {
|
if (data.type === type && first) {
|
||||||
Cryptpad.addLoadingScreen({hideTips: true});
|
UI.addLoadingScreen({hideTips: true});
|
||||||
sframeChan.query('Q_TEMPLATE_USE', data.href, function () {
|
sframeChan.query('Q_TEMPLATE_USE', data.href, function () {
|
||||||
first = false;
|
first = false;
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
common.feedback('TEMPLATE_USED');
|
common.feedback('TEMPLATE_USED');
|
||||||
});
|
});
|
||||||
if (focus) { focus.focus(); }
|
if (focus) { focus.focus(); }
|
||||||
@@ -664,7 +875,7 @@ define([
|
|||||||
if (data) {
|
if (data) {
|
||||||
common.openFilePicker(pickerCfg);
|
common.openFilePicker(pickerCfg);
|
||||||
focus = document.activeElement;
|
focus = document.activeElement;
|
||||||
Cryptpad.confirm(Messages.useTemplate, onConfirm, {
|
UI.confirm(Messages.useTemplate, onConfirm, {
|
||||||
ok: Messages.useTemplateOK,
|
ok: Messages.useTemplateOK,
|
||||||
cancel: Messages.useTemplateCancel,
|
cancel: Messages.useTemplateCancel,
|
||||||
});
|
});
|
||||||
@@ -672,58 +883,5 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.addTooltips = function () {
|
return UIElements;
|
||||||
var MutationObserver = window.MutationObserver;
|
|
||||||
var delay = typeof(AppConfig.tooltipDelay) === "number" ? AppConfig.tooltipDelay : 500;
|
|
||||||
var addTippy = function (i, el) {
|
|
||||||
if (el.nodeName === 'IFRAME') { return; }
|
|
||||||
Tippy(el, {
|
|
||||||
position: 'bottom',
|
|
||||||
distance: 0,
|
|
||||||
performance: true,
|
|
||||||
dynamicTitle: true,
|
|
||||||
delay: [delay, 0]
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var clearTooltips = function () {
|
|
||||||
$('.tippy-popper').each(function (i, el) {
|
|
||||||
if ($('[aria-describedby=' + el.getAttribute('id') + ']').length === 0) {
|
|
||||||
el.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// This is the robust solution to remove dangling tooltips
|
|
||||||
// The mutation observer does not always find removed nodes.
|
|
||||||
setInterval(clearTooltips, delay);
|
|
||||||
var checkRemoved = function (x) {
|
|
||||||
var out = false;
|
|
||||||
$(x).find('[aria-describedby]').each(function (i, el) {
|
|
||||||
var id = el.getAttribute('aria-describedby');
|
|
||||||
if (id.indexOf('tippy-tooltip-') !== 0) { return; }
|
|
||||||
out = true;
|
|
||||||
});
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
$('[title]').each(addTippy);
|
|
||||||
var observer = new MutationObserver(function(mutations) {
|
|
||||||
var removed = false;
|
|
||||||
mutations.forEach(function(mutation) {
|
|
||||||
for (var i = 0; i < mutation.addedNodes.length; i++) {
|
|
||||||
$(mutation.addedNodes[i]).find('[title]').each(addTippy);
|
|
||||||
}
|
|
||||||
for (var j = 0; j < mutation.removedNodes.length; j++) {
|
|
||||||
removed |= checkRemoved(mutation.removedNodes[j]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (removed) { clearTooltips(); }
|
|
||||||
});
|
|
||||||
observer.observe($('body')[0], {
|
|
||||||
attributes: false,
|
|
||||||
childList: true,
|
|
||||||
characterData: false,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return UI;
|
|
||||||
});
|
});
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
define(['json.sortify'], function (Sortify) {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (info, onLocal, Cryptget, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
var userData = exp.userData = {};
|
|
||||||
var userList = exp.userList = info.userList;
|
|
||||||
var myData = exp.myData = {};
|
|
||||||
exp.myUserName = info.myID;
|
|
||||||
exp.myNetfluxId = info.myID;
|
|
||||||
|
|
||||||
var network = Cryptpad.getNetwork();
|
|
||||||
|
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
|
||||||
var appType = parsed ? parsed.type : undefined;
|
|
||||||
|
|
||||||
var oldUserData = {};
|
|
||||||
var addToUserData = exp.addToUserData = function(data) {
|
|
||||||
var users = userList.users;
|
|
||||||
for (var attrname in data) { userData[attrname] = data[attrname]; }
|
|
||||||
|
|
||||||
if (users && users.length) {
|
|
||||||
for (var userKey in userData) {
|
|
||||||
if (users.indexOf(userKey) === -1) {
|
|
||||||
delete userData[userKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(userList && typeof userList.onChange === "function") {
|
|
||||||
// Make sure we don't update the userlist everytime someone makes a change to the pad
|
|
||||||
if (Sortify(oldUserData) === Sortify(userData)) { return; }
|
|
||||||
oldUserData = JSON.parse(JSON.stringify(userData));
|
|
||||||
|
|
||||||
userList.onChange(userData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getToolbarConfig = function () {
|
|
||||||
return {
|
|
||||||
data: userData,
|
|
||||||
list: userList,
|
|
||||||
userNetfluxId: exp.myNetfluxId
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var setName = exp.setName = function (newName, cb) {
|
|
||||||
if (typeof(newName) !== 'string') { return; }
|
|
||||||
var myUserNameTemp = newName.trim();
|
|
||||||
if(myUserNameTemp.length > 32) {
|
|
||||||
myUserNameTemp = myUserNameTemp.substr(0, 32);
|
|
||||||
}
|
|
||||||
exp.myUserName = myUserNameTemp;
|
|
||||||
myData = {};
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: exp.myUserName,
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
/*Cryptpad.setAttribute('username', exp.myUserName, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set username");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
});*/
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getLastName = function ($changeNameButton, isNew) {
|
|
||||||
Cryptpad.getLastName(function (err, lastName) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Could not get previous name");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Update the toolbar list:
|
|
||||||
// Add the current user in the metadata
|
|
||||||
if (typeof(lastName) === 'string') {
|
|
||||||
setName(lastName, onLocal);
|
|
||||||
} else {
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: "",
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
onLocal();
|
|
||||||
$changeNameButton.click();
|
|
||||||
}
|
|
||||||
if (isNew && appType) {
|
|
||||||
Cryptpad.selectTemplate(appType, info.realtime, Cryptget);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Cryptpad.onDisplayNameChanged(function (newName) {
|
|
||||||
setName(newName, onLocal);
|
|
||||||
});
|
|
||||||
|
|
||||||
network.on('reconnect', function (uid) {
|
|
||||||
exp.myNetfluxId = uid;
|
|
||||||
exp.setName(exp.myUserName);
|
|
||||||
});
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
define(function () {
|
|
||||||
var module = {};
|
|
||||||
|
|
||||||
module.create = function (info, onLocal, Cryptget, Cryptpad) {
|
|
||||||
var exp = {};
|
|
||||||
|
|
||||||
var userData = exp.userData = {};
|
|
||||||
var userList = exp.userList = info.userList;
|
|
||||||
var myData = exp.myData = {};
|
|
||||||
exp.myUserName = info.myID;
|
|
||||||
exp.myNetfluxId = info.myID;
|
|
||||||
|
|
||||||
var network = Cryptpad.getNetwork();
|
|
||||||
|
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
|
||||||
var appType = parsed ? parsed.type : undefined;
|
|
||||||
|
|
||||||
var addToUserData = exp.addToUserData = function(data) {
|
|
||||||
var users = userList.users;
|
|
||||||
for (var attrname in data) { userData[attrname] = data[attrname]; }
|
|
||||||
|
|
||||||
if (users && users.length) {
|
|
||||||
for (var userKey in userData) {
|
|
||||||
if (users.indexOf(userKey) === -1) {
|
|
||||||
delete userData[userKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(userList && typeof userList.onChange === "function") {
|
|
||||||
userList.onChange(userData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getToolbarConfig = function () {
|
|
||||||
return {
|
|
||||||
data: userData,
|
|
||||||
list: userList,
|
|
||||||
userNetfluxId: exp.myNetfluxId
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var setName = exp.setName = function (newName, cb) {
|
|
||||||
if (typeof(newName) !== 'string') { return; }
|
|
||||||
var myUserNameTemp = newName.trim();
|
|
||||||
if(myUserNameTemp.length > 32) {
|
|
||||||
myUserNameTemp = myUserNameTemp.substr(0, 32);
|
|
||||||
}
|
|
||||||
exp.myUserName = myUserNameTemp;
|
|
||||||
myData = {};
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: exp.myUserName,
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
/*Cryptpad.setAttribute('username', exp.myUserName, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set username");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
});*/
|
|
||||||
if (typeof cb === "function") { cb(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
exp.getLastName = function ($changeNameButton, isNew) {
|
|
||||||
Cryptpad.getLastName(function (err, lastName) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Could not get previous name");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Update the toolbar list:
|
|
||||||
// Add the current user in the metadata
|
|
||||||
if (typeof(lastName) === 'string') {
|
|
||||||
setName(lastName, onLocal);
|
|
||||||
} else {
|
|
||||||
myData[exp.myNetfluxId] = {
|
|
||||||
name: "",
|
|
||||||
uid: Cryptpad.getUid(),
|
|
||||||
avatar: Cryptpad.getAvatarUrl(),
|
|
||||||
profile: Cryptpad.getProfileUrl(),
|
|
||||||
curvePublic: Cryptpad.getProxy().curvePublic
|
|
||||||
};
|
|
||||||
addToUserData(myData);
|
|
||||||
onLocal();
|
|
||||||
$changeNameButton.click();
|
|
||||||
}
|
|
||||||
if (isNew && appType) {
|
|
||||||
Cryptpad.selectTemplate(appType, info.realtime, Cryptget);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Cryptpad.onDisplayNameChanged(function (newName) {
|
|
||||||
setName(newName, onLocal);
|
|
||||||
});
|
|
||||||
|
|
||||||
network.on('reconnect', function (uid) {
|
|
||||||
exp.myNetfluxId = uid;
|
|
||||||
exp.setName(exp.myUserName);
|
|
||||||
});
|
|
||||||
|
|
||||||
return exp;
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
@@ -89,22 +89,6 @@ define([], function () {
|
|||||||
return a;
|
return a;
|
||||||
};
|
};
|
||||||
|
|
||||||
Util.getHash = function () {
|
|
||||||
return window.location.hash.slice(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
Util.replaceHash = function (hash) {
|
|
||||||
if (window.history && window.history.replaceState) {
|
|
||||||
if (!/^#/.test(hash)) { hash = '#' + hash; }
|
|
||||||
void window.history.replaceState({}, window.document.title, hash);
|
|
||||||
if (typeof(window.onhashchange) === 'function') {
|
|
||||||
window.onhashchange();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window.location.hash = hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Saving files
|
* Saving files
|
||||||
*/
|
*/
|
||||||
@@ -186,13 +170,6 @@ define([], function () {
|
|||||||
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||||
};
|
};
|
||||||
|
|
||||||
Util.getAppType = function () {
|
|
||||||
var parts = window.location.pathname.split('/')
|
|
||||||
.filter(function (x) { return x; });
|
|
||||||
if (!parts[0]) { return ''; }
|
|
||||||
return parts[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* for wrapping async functions such that they can only be called once */
|
/* for wrapping async functions such that they can only be called once */
|
||||||
Util.once = function (f) {
|
Util.once = function (f) {
|
||||||
var called;
|
var called;
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
||||||
'/common/cryptpad-common.js',
|
'/common/common-util.js',
|
||||||
], function ($, Crypto, Realtime, Cryptpad) {
|
'/common/common-hash.js',
|
||||||
//var Messages = Cryptpad.Messages;
|
'/common/common-realtime.js',
|
||||||
//var noop = function () {};
|
//'/bower_components/textpatcher/TextPatcher.js'
|
||||||
|
], function (Crypto, CPNetflux, /* Cryptpad,*/ Util, Hash, Realtime) {
|
||||||
var finish = function (S, err, doc) {
|
var finish = function (S, err, doc) {
|
||||||
if (S.done) { return; }
|
if (S.done) { return; }
|
||||||
S.cb(err, doc);
|
S.cb(err, doc);
|
||||||
S.done = true;
|
S.done = true;
|
||||||
|
|
||||||
var disconnect = Cryptpad.find(S, ['network', 'disconnect']);
|
var disconnect = Util.find(S, ['network', 'disconnect']);
|
||||||
if (typeof(disconnect) === 'function') { disconnect(); }
|
if (typeof(disconnect) === 'function') { disconnect(); }
|
||||||
var abort = Cryptpad.find(S, ['realtime', 'realtime', 'abort']);
|
var abort = Util.find(S, ['realtime', 'realtime', 'abort']);
|
||||||
if (typeof(abort) === 'function') {
|
if (typeof(abort) === 'function') {
|
||||||
S.realtime.realtime.sync();
|
S.realtime.realtime.sync();
|
||||||
abort();
|
abort();
|
||||||
@@ -22,7 +22,7 @@ define([
|
|||||||
|
|
||||||
var makeConfig = function (hash) {
|
var makeConfig = function (hash) {
|
||||||
// We can't use cryptget with a file or a user so we can use 'pad' as hash type
|
// We can't use cryptget with a file or a user so we can use 'pad' as hash type
|
||||||
var secret = Cryptpad.getSecrets('pad', hash);
|
var secret = Hash.getSecrets('pad', hash);
|
||||||
if (!secret.keys) { secret.keys = secret.key; } // support old hashses
|
if (!secret.keys) { secret.keys = secret.key; } // support old hashses
|
||||||
var config = {
|
var config = {
|
||||||
websocketURL: Cryptpad.getWebsocketURL(),
|
websocketURL: Cryptpad.getWebsocketURL(),
|
||||||
@@ -57,7 +57,7 @@ define([
|
|||||||
};
|
};
|
||||||
overwrite(config, opt);
|
overwrite(config, opt);
|
||||||
|
|
||||||
Session.realtime = Realtime.start(config);
|
Session.realtime = CPNetflux.start(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
var put = function (hash, doc, cb, opt) {
|
var put = function (hash, doc, cb, opt) {
|
||||||
@@ -77,7 +77,7 @@ define([
|
|||||||
cb(new Error("Timeout"));
|
cb(new Error("Timeout"));
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
Cryptpad.whenRealtimeSyncs(realtime, function () {
|
Realtime.whenRealtimeSyncs(realtime, function () {
|
||||||
window.clearTimeout(to);
|
window.clearTimeout(to);
|
||||||
realtime.abort();
|
realtime.abort();
|
||||||
finish(Session, void 0);
|
finish(Session, void 0);
|
||||||
@@ -85,7 +85,7 @@ define([
|
|||||||
};
|
};
|
||||||
overwrite(config, opt);
|
overwrite(config, opt);
|
||||||
|
|
||||||
Session.session = Realtime.start(config);
|
Session.session = CPNetflux.start(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/bower_components/marked/marked.min.js',
|
'/bower_components/marked/marked.min.js',
|
||||||
'/common/cryptpad-common.js',
|
'/common/common-hash.js',
|
||||||
|
'/common/common-util.js',
|
||||||
'/common/media-tag.js',
|
'/common/media-tag.js',
|
||||||
'/bower_components/diff-dom/diffDOM.js',
|
'/bower_components/diff-dom/diffDOM.js',
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||||
],function ($, Marked, Cryptpad, MediaTag) {
|
],function ($, Marked, Hash, Util, MediaTag) {
|
||||||
var DiffMd = {};
|
var DiffMd = {};
|
||||||
|
|
||||||
var DiffDOM = window.diffDOM;
|
var DiffDOM = window.diffDOM;
|
||||||
@@ -40,8 +41,8 @@ define([
|
|||||||
};
|
};
|
||||||
renderer.image = function (href, title, text) {
|
renderer.image = function (href, title, text) {
|
||||||
if (href.slice(0,6) === '/file/') {
|
if (href.slice(0,6) === '/file/') {
|
||||||
var parsed = Cryptpad.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '">';
|
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '">';
|
||||||
if (mediaMap[src]) {
|
if (mediaMap[src]) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,12 @@ define([
|
|||||||
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
||||||
'/bower_components/chainpad-crypto/crypto.js?v=0.1.5',
|
'/bower_components/chainpad-crypto/crypto.js?v=0.1.5',
|
||||||
'/common/userObject.js',
|
'/common/userObject.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
'/common/migrate-user-object.js',
|
'/common/migrate-user-object.js',
|
||||||
], function ($, Listmap, Crypto, FO, Migrate) {
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
|
], function ($, Listmap, Crypto, /* TextPatcher, */ FO, UI, Hash, Constants, Migrate, ChainPad) {
|
||||||
/*
|
/*
|
||||||
This module uses localStorage, which is synchronous, but exposes an
|
This module uses localStorage, which is synchronous, but exposes an
|
||||||
asyncronous API. This is so that we can substitute other storage
|
asyncronous API. This is so that we can substitute other storage
|
||||||
@@ -188,7 +192,7 @@ define([
|
|||||||
var onReady = function (f, proxy, Cryptpad, exp) {
|
var onReady = function (f, proxy, Cryptpad, exp) {
|
||||||
var fo = exp.fo = FO.init(proxy.drive, {
|
var fo = exp.fo = FO.init(proxy.drive, {
|
||||||
Cryptpad: Cryptpad,
|
Cryptpad: Cryptpad,
|
||||||
rt: exp.realtime
|
loggedIn: Cryptpad.isLoggedIn()
|
||||||
});
|
});
|
||||||
var todo = function () {
|
var todo = function () {
|
||||||
fo.fixFiles();
|
fo.fixFiles();
|
||||||
@@ -246,7 +250,7 @@ define([
|
|||||||
if (typeof(proxy.uid) !== 'string' || proxy.uid.length !== 32) {
|
if (typeof(proxy.uid) !== 'string' || proxy.uid.length !== 32) {
|
||||||
// even anonymous users should have a persistent, unique-ish id
|
// even anonymous users should have a persistent, unique-ish id
|
||||||
console.log('generating a persistent identifier');
|
console.log('generating a persistent identifier');
|
||||||
proxy.uid = Cryptpad.createChannelId();
|
proxy.uid = Hash.createChannelId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user is logged in, but does not have signing keys...
|
// if the user is logged in, but does not have signing keys...
|
||||||
@@ -255,17 +259,17 @@ define([
|
|||||||
return void requestLogin();
|
return void requestLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.on('change', [Cryptpad.displayNameKey], function (o, n) {
|
proxy.on('change', [Constants.displayNameKey], function (o, n) {
|
||||||
if (typeof(n) !== "string") { return; }
|
if (typeof(n) !== "string") { return; }
|
||||||
Cryptpad.changeDisplayName(n);
|
Cryptpad.changeDisplayName(n);
|
||||||
});
|
});
|
||||||
proxy.on('change', ['profile'], function () {
|
proxy.on('change', ['profile'], function () {
|
||||||
// Trigger userlist update when the avatar has changed
|
// Trigger userlist update when the avatar has changed
|
||||||
Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]);
|
Cryptpad.changeDisplayName(proxy[Constants.displayNameKey]);
|
||||||
});
|
});
|
||||||
proxy.on('change', ['friends'], function () {
|
proxy.on('change', ['friends'], function () {
|
||||||
// Trigger userlist update when the avatar has changed
|
// Trigger userlist update when the avatar has changed
|
||||||
Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]);
|
Cryptpad.changeDisplayName(proxy[Constants.displayNameKey]);
|
||||||
});
|
});
|
||||||
proxy.on('change', [tokenKey], function () {
|
proxy.on('change', [tokenKey], function () {
|
||||||
var localToken = tryParsing(localStorage.getItem(tokenKey));
|
var localToken = tryParsing(localStorage.getItem(tokenKey));
|
||||||
@@ -283,11 +287,11 @@ define([
|
|||||||
if (!Cryptpad || initialized) { return; }
|
if (!Cryptpad || initialized) { return; }
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
var hash = Cryptpad.getUserHash() || localStorage.FS_hash || Cryptpad.createRandomHash();
|
var hash = Cryptpad.getUserHash() || localStorage.FS_hash || Hash.createRandomHash();
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
throw new Error('[Store.init] Unable to find or create a drive hash. Aborting...');
|
throw new Error('[Store.init] Unable to find or create a drive hash. Aborting...');
|
||||||
}
|
}
|
||||||
var secret = Cryptpad.getSecrets('drive', hash);
|
var secret = Hash.getSecrets('drive', hash);
|
||||||
var listmapConfig = {
|
var listmapConfig = {
|
||||||
data: {},
|
data: {},
|
||||||
websocketURL: Cryptpad.getWebsocketURL(),
|
websocketURL: Cryptpad.getWebsocketURL(),
|
||||||
@@ -297,31 +301,11 @@ define([
|
|||||||
crypto: Crypto.createEncryptor(secret.keys),
|
crypto: Crypto.createEncryptor(secret.keys),
|
||||||
userName: 'fs',
|
userName: 'fs',
|
||||||
logLevel: 1,
|
logLevel: 1,
|
||||||
|
ChainPad: ChainPad,
|
||||||
};
|
};
|
||||||
|
|
||||||
var exp = {};
|
var exp = {};
|
||||||
|
|
||||||
window.addEventListener('storage', function (e) {
|
|
||||||
if (e.key !== Cryptpad.userHashKey) { return; }
|
|
||||||
var o = e.oldValue;
|
|
||||||
var n = e.newValue;
|
|
||||||
if (!o && n) {
|
|
||||||
window.location.reload();
|
|
||||||
} else if (o && !n) {
|
|
||||||
$(window).on('keyup', function (e) {
|
|
||||||
if (e.keyCode === 27) {
|
|
||||||
Cryptpad.removeLoadingScreen();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Cryptpad.logout();
|
|
||||||
Cryptpad.addLoadingScreen({hideTips: true});
|
|
||||||
Cryptpad.errorLoadingScreen(Cryptpad.Messages.onLogout, true);
|
|
||||||
if (exp.info) {
|
|
||||||
exp.info.network.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var rt = window.rt = Listmap.create(listmapConfig);
|
var rt = window.rt = Listmap.create(listmapConfig);
|
||||||
|
|
||||||
exp.realtime = rt.realtime;
|
exp.realtime = rt.realtime;
|
||||||
@@ -329,38 +313,29 @@ define([
|
|||||||
rt.proxy.on('create', function (info) {
|
rt.proxy.on('create', function (info) {
|
||||||
exp.info = info;
|
exp.info = info;
|
||||||
if (!Cryptpad.getUserHash()) {
|
if (!Cryptpad.getUserHash()) {
|
||||||
localStorage.FS_hash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
|
localStorage.FS_hash = Hash.getEditHashFromKeys(info.channel, secret.keys);
|
||||||
}
|
}
|
||||||
}).on('ready', function () {
|
}).on('ready', function () {
|
||||||
if (store) { return; } // the store is already ready, it is a reconnection
|
if (store) { return; } // the store is already ready, it is a reconnection
|
||||||
if (!rt.proxy.drive || typeof(rt.proxy.drive) !== 'object') { rt.proxy.drive = {}; }
|
if (!rt.proxy.drive || typeof(rt.proxy.drive) !== 'object') { rt.proxy.drive = {}; }
|
||||||
var drive = rt.proxy.drive;
|
var drive = rt.proxy.drive;
|
||||||
// Creating a new anon drive: import anon pads from localStorage
|
// Creating a new anon drive: import anon pads from localStorage
|
||||||
if ((!drive[Cryptpad.oldStorageKey] || !Cryptpad.isArray(drive[Cryptpad.oldStorageKey]))
|
if ((!drive[Constants.oldStorageKey] || !Array.isArray(drive[Constants.oldStorageKey]))
|
||||||
&& !drive['filesData']) {
|
&& !drive['filesData']) {
|
||||||
drive[Cryptpad.oldStorageKey] = [];
|
drive[Constants.oldStorageKey] = [];
|
||||||
onReady(f, rt.proxy, Cryptpad, exp);
|
onReady(f, rt.proxy, Cryptpad, exp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Drive already exist: return the existing drive, don't load data from legacy store
|
// Drive already exist: return the existing drive, don't load data from legacy store
|
||||||
onReady(f, rt.proxy, Cryptpad, exp);
|
onReady(f, rt.proxy, Cryptpad, exp);
|
||||||
})
|
})
|
||||||
.on('disconnect', function (info) {
|
|
||||||
// We only manage errors during the loading screen here. Other websocket errors are handled by the apps
|
|
||||||
if (info.error) {
|
|
||||||
if (typeof Cryptpad.storeError === "function") {
|
|
||||||
Cryptpad.storeError();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on('change', ['drive', 'migrate'], function () {
|
.on('change', ['drive', 'migrate'], function () {
|
||||||
var path = arguments[2];
|
var path = arguments[2];
|
||||||
var value = arguments[1];
|
var value = arguments[1];
|
||||||
if (path[0] === 'drive' && path[1] === "migrate" && value === 1) {
|
if (path[0] === 'drive' && path[1] === "migrate" && value === 1) {
|
||||||
rt.network.disconnect();
|
rt.network.disconnect();
|
||||||
rt.realtime.abort();
|
rt.realtime.abort();
|
||||||
Cryptpad.alert(Cryptpad.Messages.fs_migration, null, true);
|
UI.alert(Cryptpad.Messages.fs_migration, null, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ define([
|
|||||||
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
|
'/common/common-util.js',
|
||||||
'/common/credential.js',
|
'/common/credential.js',
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||||
'/bower_components/scrypt-async/scrypt-async.min.js', // better load speed
|
'/bower_components/scrypt-async/scrypt-async.min.js', // better load speed
|
||||||
], function ($, Listmap, Crypto, Cryptpad, Cred) {
|
], function ($, Listmap, Crypto, Cryptpad, Util, Cred) {
|
||||||
var Exports = {
|
var Exports = {
|
||||||
Cred: Cred,
|
Cred: Cred,
|
||||||
};
|
};
|
||||||
@@ -43,12 +44,12 @@ define([
|
|||||||
keys.editKeyStr = keys.editKeyStr.replace(/\//g, '-');
|
keys.editKeyStr = keys.editKeyStr.replace(/\//g, '-');
|
||||||
|
|
||||||
// 32 bytes of hex
|
// 32 bytes of hex
|
||||||
var channelHex = opt.channelHex = Cryptpad.uint8ArrayToHex(channelSeed);
|
var channelHex = opt.channelHex = Util.uint8ArrayToHex(channelSeed);
|
||||||
|
|
||||||
// should never happen
|
// should never happen
|
||||||
if (channelHex.length !== 32) { throw new Error('invalid channel id'); }
|
if (channelHex.length !== 32) { throw new Error('invalid channel id'); }
|
||||||
|
|
||||||
opt.channel64 = Cryptpad.hexToBase64(channelHex);
|
opt.channel64 = Util.hexToBase64(channelHex);
|
||||||
|
|
||||||
opt.userHash = '/1/edit/' + [opt.channel64, opt.keys.editKeyStr].join('/');
|
opt.userHash = '/1/edit/' + [opt.channel64, opt.keys.editKeyStr].join('/');
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ define([
|
|||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/common/cryptget.js',
|
'/common/cryptget.js',
|
||||||
'/common/userObject.js',
|
'/common/userObject.js',
|
||||||
], function (Cryptpad, Crypt, FO) {
|
'/common/common-hash.js',
|
||||||
|
], function (Cryptpad, Crypt, FO, Hash) {
|
||||||
var exp = {};
|
var exp = {};
|
||||||
|
|
||||||
var getType = function (el) {
|
var getType = function (el) {
|
||||||
@@ -41,7 +42,7 @@ define([
|
|||||||
if (typeof(p) === "string") {
|
if (typeof(p) === "string") {
|
||||||
if (getType(root) !== "object") { root = undefined; error(); return; }
|
if (getType(root) !== "object") { root = undefined; error(); return; }
|
||||||
if (i === path.length - 1) {
|
if (i === path.length - 1) {
|
||||||
root[Cryptpad.createChannelId()] = id;
|
root[Hash.createChannelId()] = id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
next = getType(path[i+1]);
|
next = getType(path[i+1]);
|
||||||
@@ -104,7 +105,7 @@ define([
|
|||||||
if (parsed) {
|
if (parsed) {
|
||||||
var proxy = proxyData.proxy;
|
var proxy = proxyData.proxy;
|
||||||
var oldFo = FO.init(parsed.drive, {
|
var oldFo = FO.init(parsed.drive, {
|
||||||
Cryptpad: Cryptpad
|
loggedIn: Cryptpad.isLoggedIn()
|
||||||
});
|
});
|
||||||
var onMigrated = function () {
|
var onMigrated = function () {
|
||||||
oldFo.fixFiles();
|
oldFo.fixFiles();
|
||||||
@@ -120,10 +121,10 @@ define([
|
|||||||
// Do not migrate a pad if we already have it, it would create a duplicate in the drive
|
// Do not migrate a pad if we already have it, it would create a duplicate in the drive
|
||||||
if (newHrefs.indexOf(href) !== -1) { return; }
|
if (newHrefs.indexOf(href) !== -1) { return; }
|
||||||
// If we have a stronger version, do not add the current href
|
// If we have a stronger version, do not add the current href
|
||||||
if (Cryptpad.findStronger(href, newRecentPads)) { return; }
|
if (Hash.findStronger(href, newRecentPads)) { return; }
|
||||||
// If we have a weaker version, replace the href by the new one
|
// If we have a weaker version, replace the href by the new one
|
||||||
// NOTE: if that weaker version is in the trash, the strong one will be put in unsorted
|
// NOTE: if that weaker version is in the trash, the strong one will be put in unsorted
|
||||||
var weaker = Cryptpad.findWeaker(href, newRecentPads);
|
var weaker = Hash.findWeaker(href, newRecentPads);
|
||||||
if (weaker) {
|
if (weaker) {
|
||||||
// Update RECENTPADS
|
// Update RECENTPADS
|
||||||
newRecentPads.some(function (pad) {
|
newRecentPads.some(function (pad) {
|
||||||
|
|||||||
@@ -80,5 +80,27 @@ define([], function () {
|
|||||||
Cryptpad.feedback('Migrate-4', true);
|
Cryptpad.feedback('Migrate-4', true);
|
||||||
userObject.version = version = 4;
|
userObject.version = version = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Migration 5: dates to Number
|
||||||
|
var migrateDates = function () {
|
||||||
|
var data = userObject.drive && userObject.drive.filesData;
|
||||||
|
if (data) {
|
||||||
|
for (var id in data) {
|
||||||
|
if (typeof data[id].ctime !== "number") {
|
||||||
|
data[id].ctime = +new Date(data[id].ctime);
|
||||||
|
}
|
||||||
|
if (typeof data[id].atime !== "number") {
|
||||||
|
data[id].atime = +new Date(data[id].atime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (version < 5) {
|
||||||
|
migrateDates();
|
||||||
|
Cryptpad.feedback('Migrate-5', true);
|
||||||
|
userObject.version = version = 5;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
93
www/common/outer/upload.js
Normal file
93
www/common/outer/upload.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
define([
|
||||||
|
'/file/file-crypto.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||||
|
], function (FileCrypto, Hash) {
|
||||||
|
var Nacl = window.nacl;
|
||||||
|
var module = {};
|
||||||
|
|
||||||
|
module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) {
|
||||||
|
var u8 = file.blob; // This is not a blob but a uint8array
|
||||||
|
var metadata = file.metadata;
|
||||||
|
|
||||||
|
// if it exists, path contains the new pad location in the drive
|
||||||
|
var path = file.path;
|
||||||
|
|
||||||
|
var key = Nacl.randomBytes(32);
|
||||||
|
var next = FileCrypto.encrypt(u8, metadata, key);
|
||||||
|
|
||||||
|
var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata);
|
||||||
|
|
||||||
|
var sendChunk = function (box, cb) {
|
||||||
|
var enc = Nacl.util.encodeBase64(box);
|
||||||
|
common.rpc.send.unauthenticated('UPLOAD', enc, function (e, msg) {
|
||||||
|
cb(e, msg);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var actual = 0;
|
||||||
|
var again = function (err, box) {
|
||||||
|
if (err) { throw new Error(err); }
|
||||||
|
if (box) {
|
||||||
|
actual += box.length;
|
||||||
|
var progressValue = (actual / estimate * 100);
|
||||||
|
updateProgress(progressValue);
|
||||||
|
|
||||||
|
return void sendChunk(box, function (e) {
|
||||||
|
if (e) { return console.error(e); }
|
||||||
|
next(again);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actual !== estimate) {
|
||||||
|
console.error('Estimated size does not match actual size');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not box then done
|
||||||
|
common.uploadComplete(function (e, id) {
|
||||||
|
if (e) { return void console.error(e); }
|
||||||
|
var uri = ['', 'blob', id.slice(0,2), id].join('/');
|
||||||
|
console.log("encrypted blob is now available as %s", uri);
|
||||||
|
|
||||||
|
var b64Key = Nacl.util.encodeBase64(key);
|
||||||
|
|
||||||
|
var hash = Hash.getFileHashFromKeys(id, b64Key);
|
||||||
|
var href = '/file/#' + hash;
|
||||||
|
|
||||||
|
var title = metadata.name;
|
||||||
|
|
||||||
|
if (noStore) { return void onComplete(href); }
|
||||||
|
|
||||||
|
common.initialPath = path;
|
||||||
|
common.renamePad(title || "", href, function (err) {
|
||||||
|
if (err) { return void console.error(err); }
|
||||||
|
onComplete(href);
|
||||||
|
common.setPadAttribute('fileType', metadata.type, null, href);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
common.uploadStatus(estimate, function (e, pending) {
|
||||||
|
if (e) {
|
||||||
|
console.error(e);
|
||||||
|
onError(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending) {
|
||||||
|
return void onPending(function () {
|
||||||
|
// if the user wants to cancel the pending upload to execute that one
|
||||||
|
common.uploadCancel(function (e, res) {
|
||||||
|
if (e) {
|
||||||
|
return void console.error(e);
|
||||||
|
}
|
||||||
|
console.log(res);
|
||||||
|
next(again);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
next(again);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return module;
|
||||||
|
});
|
||||||
@@ -3,15 +3,16 @@ define([
|
|||||||
'/bower_components/hyperjson/hyperjson.js',
|
'/bower_components/hyperjson/hyperjson.js',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'json.sortify',
|
'json.sortify',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
'/common/common-thumbnail.js',
|
'/common/common-thumbnail.js',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
|
|
||||||
|
'/bower_components/file-saver/FileSaver.min.js',
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
'less!/customize/src/less2/main.less',
|
'less!/customize/src/less2/main.less',
|
||||||
@@ -20,11 +21,11 @@ define([
|
|||||||
Hyperjson,
|
Hyperjson,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
JSONSortify,
|
JSONSortify,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
Messages,
|
Messages,
|
||||||
Util,
|
Util,
|
||||||
|
UI,
|
||||||
Thumb,
|
Thumb,
|
||||||
AppConfig,
|
AppConfig,
|
||||||
ChainPad)
|
ChainPad)
|
||||||
@@ -45,10 +46,6 @@ define([
|
|||||||
var badStateTimeout = typeof(AppConfig.badStateTimeout) === 'number' ?
|
var badStateTimeout = typeof(AppConfig.badStateTimeout) === 'number' ?
|
||||||
AppConfig.badStateTimeout : 30000;
|
AppConfig.badStateTimeout : 30000;
|
||||||
|
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var create = function (options, cb) {
|
var create = function (options, cb) {
|
||||||
var evContentUpdate = Util.mkEvent();
|
var evContentUpdate = Util.mkEvent();
|
||||||
var evEditableStateChange = Util.mkEvent();
|
var evEditableStateChange = Util.mkEvent();
|
||||||
@@ -148,7 +145,7 @@ define([
|
|||||||
evContentUpdate.fire(newContent);
|
evContentUpdate.fire(newContent);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e.stack);
|
console.log(e.stack);
|
||||||
Cryptpad.errorLoadingScreen(e.message);
|
UI.errorLoadingScreen(e.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -254,7 +251,7 @@ define([
|
|||||||
newContent = normalize(newContent);
|
newContent = normalize(newContent);
|
||||||
contentUpdate(newContent);
|
contentUpdate(newContent);
|
||||||
} else {
|
} else {
|
||||||
title.updateTitle(Cryptpad.initialName || title.defaultTitle);
|
title.updateTitle(title.defaultTitle);
|
||||||
evOnDefaultContentNeeded.fire();
|
evOnDefaultContentNeeded.fire();
|
||||||
}
|
}
|
||||||
stateChange(STATE.READY);
|
stateChange(STATE.READY);
|
||||||
@@ -262,7 +259,7 @@ define([
|
|||||||
if (!readOnly) { onLocal(); }
|
if (!readOnly) { onLocal(); }
|
||||||
evOnReady.fire(newPad);
|
evOnReady.fire(newPad);
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen(emitResize);
|
UI.removeLoadingScreen(emitResize);
|
||||||
|
|
||||||
var privateDat = cpNfInner.metadataMgr.getPrivateData();
|
var privateDat = cpNfInner.metadataMgr.getPrivateData();
|
||||||
if (options.thumbnail && privateDat.thumbnails) {
|
if (options.thumbnail && privateDat.thumbnails) {
|
||||||
@@ -285,9 +282,9 @@ define([
|
|||||||
var onConnectionChange = function (info) {
|
var onConnectionChange = function (info) {
|
||||||
stateChange(info.state ? STATE.INITIALIZING : STATE.DISCONNECTED);
|
stateChange(info.state ? STATE.INITIALIZING : STATE.DISCONNECTED);
|
||||||
if (info.state) {
|
if (info.state) {
|
||||||
Cryptpad.findOKButton().click();
|
UI.findOKButton().click();
|
||||||
} else {
|
} else {
|
||||||
Cryptpad.alert(Messages.common_connectionLost, undefined, true);
|
UI.alert(Messages.common_connectionLost, undefined, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -295,8 +292,8 @@ define([
|
|||||||
var $export = common.createButton('export', true, {}, function () {
|
var $export = common.createButton('export', true, {}, function () {
|
||||||
var ext = (typeof(extension) === 'function') ? extension() : extension;
|
var ext = (typeof(extension) === 'function') ? extension() : extension;
|
||||||
var suggestion = title.suggestTitle('cryptpad-document');
|
var suggestion = title.suggestTitle('cryptpad-document');
|
||||||
Cryptpad.prompt(Messages.exportPrompt,
|
UI.prompt(Messages.exportPrompt,
|
||||||
Cryptpad.fixFileName(suggestion) + '.' + ext, function (filename)
|
Util.fixFileName(suggestion) + '.' + ext, function (filename)
|
||||||
{
|
{
|
||||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
if (!(typeof(filename) === 'string' && filename)) { return; }
|
||||||
if (async) {
|
if (async) {
|
||||||
@@ -371,7 +368,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
Cryptpad.addLoadingScreen();
|
UI.addLoadingScreen();
|
||||||
SFCommon.create(waitFor(function (c) { common = c; }));
|
SFCommon.create(waitFor(function (c) { common = c; }));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
cpNfInner = common.startRealtime({
|
cpNfInner = common.startRealtime({
|
||||||
@@ -422,25 +419,19 @@ define([
|
|||||||
if (infiniteSpinnerModal) { return; }
|
if (infiniteSpinnerModal) { return; }
|
||||||
infiniteSpinnerModal = true;
|
infiniteSpinnerModal = true;
|
||||||
stateChange(STATE.INFINITE_SPINNER);
|
stateChange(STATE.INFINITE_SPINNER);
|
||||||
Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
common.gotoURL();
|
common.gotoURL();
|
||||||
});
|
});
|
||||||
cpNfInner.chainpad.onSettle(function () {
|
cpNfInner.chainpad.onSettle(function () {
|
||||||
infiniteSpinnerModal = false;
|
infiniteSpinnerModal = false;
|
||||||
Cryptpad.findCancelButton().click();
|
UI.findCancelButton().click();
|
||||||
stateChange(STATE.READY);
|
stateChange(STATE.READY);
|
||||||
onRemote();
|
onRemote();
|
||||||
});
|
});
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
//Cryptpad.onLogout(function () { ... });
|
//common.onLogout(function () { ... });
|
||||||
|
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
|
|
||||||
if (readOnly) { $('body').addClass('cp-readonly'); }
|
if (readOnly) { $('body').addClass('cp-readonly'); }
|
||||||
@@ -472,7 +463,6 @@ define([
|
|||||||
metadataMgr: cpNfInner.metadataMgr,
|
metadataMgr: cpNfInner.metadataMgr,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
realtime: cpNfInner.chainpad,
|
realtime: cpNfInner.chainpad,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: $(toolbarContainer),
|
$container: $(toolbarContainer),
|
||||||
$contentContainer: $(contentContainer)
|
$contentContainer: $(contentContainer)
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/common/modes.js',
|
'/common/modes.js',
|
||||||
'/common/themes.js',
|
'/common/themes.js',
|
||||||
'/common/cryptpad-common.js',
|
'/customize/messages.js',
|
||||||
|
'/common/common-ui-elements.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-util.js',
|
||||||
'/common/text-cursor.js',
|
'/common/text-cursor.js',
|
||||||
'/bower_components/chainpad/chainpad.dist.js'
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
], function ($, Modes, Themes, Cryptpad, TextCursor, ChainPad) {
|
], function ($, Modes, Themes, Messages, UIElements, Hash, Util, TextCursor, ChainPad) {
|
||||||
var module = {};
|
var module = {};
|
||||||
|
|
||||||
var cursorToPos = function(cursor, oldText) {
|
var cursorToPos = function(cursor, oldText) {
|
||||||
@@ -102,7 +105,6 @@ define([
|
|||||||
|
|
||||||
module.create = function (Common, defaultMode, CMeditor) {
|
module.create = function (Common, defaultMode, CMeditor) {
|
||||||
var exp = {};
|
var exp = {};
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var CodeMirror = exp.CodeMirror = CMeditor;
|
var CodeMirror = exp.CodeMirror = CMeditor;
|
||||||
CodeMirror.modeURL = "cm/mode/%N/%N";
|
CodeMirror.modeURL = "cm/mode/%N/%N";
|
||||||
@@ -212,7 +214,7 @@ define([
|
|||||||
isSelect: true,
|
isSelect: true,
|
||||||
feedback: 'CODE_LANGUAGE',
|
feedback: 'CODE_LANGUAGE',
|
||||||
};
|
};
|
||||||
var $block = exp.$language = Cryptpad.createDropdown(dropdownConfig);
|
var $block = exp.$language = UIElements.createDropdown(dropdownConfig);
|
||||||
$block.find('button').attr('title', Messages.languageButtonTitle);
|
$block.find('button').attr('title', Messages.languageButtonTitle);
|
||||||
$block.find('a').click(function () {
|
$block.find('a').click(function () {
|
||||||
setMode($(this).attr('data-value'), onModeChanged);
|
setMode($(this).attr('data-value'), onModeChanged);
|
||||||
@@ -249,7 +251,7 @@ define([
|
|||||||
initialValue: lastTheme,
|
initialValue: lastTheme,
|
||||||
feedback: 'CODE_THEME',
|
feedback: 'CODE_THEME',
|
||||||
};
|
};
|
||||||
var $block = exp.$theme = Cryptpad.createDropdown(dropdownConfig);
|
var $block = exp.$theme = UIElements.createDropdown(dropdownConfig);
|
||||||
$block.find('button').attr('title', Messages.themeButtonTitle);
|
$block.find('button').attr('title', Messages.themeButtonTitle);
|
||||||
|
|
||||||
setTheme(lastTheme, $block);
|
setTheme(lastTheme, $block);
|
||||||
@@ -325,8 +327,8 @@ define([
|
|||||||
//var cursor = editor.getCursor();
|
//var cursor = editor.getCursor();
|
||||||
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
||||||
//var text = '';
|
//var text = '';
|
||||||
var parsed = Cryptpad.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' +
|
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' +
|
||||||
parsed.hashData.key + '"></media-tag>';
|
parsed.hashData.key + '"></media-tag>';
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/file/file-crypto.js',
|
'/file/file-crypto.js',
|
||||||
'/common/common-thumbnail.js',
|
'/common/common-thumbnail.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||||
], function ($, FileCrypto, Thumb) {
|
], function ($, FileCrypto, Thumb, UI, Util, Messages) {
|
||||||
var Nacl = window.nacl;
|
var Nacl = window.nacl;
|
||||||
var module = {};
|
var module = {};
|
||||||
|
|
||||||
@@ -15,15 +19,6 @@ define([
|
|||||||
reader.readAsArrayBuffer(blob);
|
reader.readAsArrayBuffer(blob);
|
||||||
};
|
};
|
||||||
|
|
||||||
var arrayBufferToString = function (AB) {
|
|
||||||
try {
|
|
||||||
return Nacl.util.encodeBase64(new Uint8Array(AB));
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.uploadFile = function (common, data, cb) {
|
module.uploadFile = function (common, data, cb) {
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
sframeChan.query('Q_UPLOAD_FILE', data, cb);
|
sframeChan.query('Q_UPLOAD_FILE', data, cb);
|
||||||
@@ -31,9 +26,6 @@ define([
|
|||||||
|
|
||||||
module.create = function (common, config) {
|
module.create = function (common, config) {
|
||||||
var File = {};
|
var File = {};
|
||||||
var Cryptpad = common.getCryptpadCommon();
|
|
||||||
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var queue = File.queue = {
|
var queue = File.queue = {
|
||||||
queue: [],
|
queue: [],
|
||||||
@@ -94,7 +86,7 @@ define([
|
|||||||
var id = file.id;
|
var id = file.id;
|
||||||
var dropEvent = file.dropEvent;
|
var dropEvent = file.dropEvent;
|
||||||
delete file.dropEvent;
|
delete file.dropEvent;
|
||||||
if (dropEvent.path) { file.path = dropEvent.path; }
|
if (dropEvent && dropEvent.path) { file.path = dropEvent.path; }
|
||||||
if (queue.inProgress) { return; }
|
if (queue.inProgress) { return; }
|
||||||
queue.inProgress = true;
|
queue.inProgress = true;
|
||||||
|
|
||||||
@@ -123,7 +115,7 @@ define([
|
|||||||
window.open(origin + $link.attr('href'), '_blank');
|
window.open(origin + $link.attr('href'), '_blank');
|
||||||
});
|
});
|
||||||
var title = metadata.name;
|
var title = metadata.name;
|
||||||
Cryptpad.log(Messages._getKey('upload_success', [title]));
|
UI.log(Messages._getKey('upload_success', [title]));
|
||||||
common.prepareFeedback('upload')();
|
common.prepareFeedback('upload')();
|
||||||
|
|
||||||
if (config.onUploaded) {
|
if (config.onUploaded) {
|
||||||
@@ -140,18 +132,18 @@ define([
|
|||||||
queue.next();
|
queue.next();
|
||||||
if (e === 'TOO_LARGE') {
|
if (e === 'TOO_LARGE') {
|
||||||
// TODO update table to say too big?
|
// TODO update table to say too big?
|
||||||
return void Cryptpad.alert(Messages.upload_tooLarge);
|
return void UI.alert(Messages.upload_tooLarge);
|
||||||
}
|
}
|
||||||
if (e === 'NOT_ENOUGH_SPACE') {
|
if (e === 'NOT_ENOUGH_SPACE') {
|
||||||
// TODO update table to say not enough space?
|
// TODO update table to say not enough space?
|
||||||
return void Cryptpad.alert(Messages.upload_notEnoughSpace);
|
return void UI.alert(Messages.upload_notEnoughSpace);
|
||||||
}
|
}
|
||||||
console.error(e);
|
console.error(e);
|
||||||
return void Cryptpad.alert(Messages.upload_serverError);
|
return void UI.alert(Messages.upload_serverError);
|
||||||
};
|
};
|
||||||
|
|
||||||
onPending = function (cb) {
|
onPending = function (cb) {
|
||||||
Cryptpad.confirm(Messages.upload_uploadPending, cb);
|
UI.confirm(Messages.upload_uploadPending, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
file.noStore = config.noStore;
|
file.noStore = config.noStore;
|
||||||
@@ -161,14 +153,14 @@ define([
|
|||||||
console.log('Upload started...');
|
console.log('Upload started...');
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Cryptpad.alert(Messages.upload_serverError);
|
UI.alert(Messages.upload_serverError);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var prettySize = function (bytes) {
|
var prettySize = function (bytes) {
|
||||||
var kB = Cryptpad.bytesToKilobytes(bytes);
|
var kB = Util.bytesToKilobytes(bytes);
|
||||||
if (kB < 1024) { return kB + Messages.KB; }
|
if (kB < 1024) { return kB + Messages.KB; }
|
||||||
var mB = Cryptpad.bytesToMegabytes(bytes);
|
var mB = Util.bytesToMegabytes(bytes);
|
||||||
return mB + Messages.MB;
|
return mB + Messages.MB;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -220,12 +212,41 @@ define([
|
|||||||
queue.next();
|
queue.next();
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleFile = File.handleFile = function (file, e, thumbnail) {
|
var showNamePrompt = true;
|
||||||
|
var promptName = function (file, cb) {
|
||||||
|
var extIdx = file.name.lastIndexOf('.');
|
||||||
|
var name = extIdx !== -1 ? file.name.slice(0,extIdx) : file.name;
|
||||||
|
var ext = extIdx !== -1 ? file.name.slice(extIdx) : "";
|
||||||
|
var msg = Messages._getKey('upload_rename', [
|
||||||
|
Util.fixHTML(file.name),
|
||||||
|
Util.fixHTML(ext)
|
||||||
|
]);
|
||||||
|
UI.prompt(msg, name, function (newName) {
|
||||||
|
if (newName === null) {
|
||||||
|
showNamePrompt = false;
|
||||||
|
return void cb (file.name);
|
||||||
|
}
|
||||||
|
if (!newName || !newName.trim()) { return void cb (file.name); }
|
||||||
|
var newExtIdx = newName.lastIndexOf('.');
|
||||||
|
var newExt = newExtIdx !== -1 ? newName.slice(newExtIdx) : "";
|
||||||
|
if (newExt !== ext) { newName += ext; }
|
||||||
|
cb(newName);
|
||||||
|
}, {cancel: Messages.doNotAskAgain}, true);
|
||||||
|
};
|
||||||
|
var handleFileState = {
|
||||||
|
queue: [],
|
||||||
|
inProgress: false
|
||||||
|
};
|
||||||
|
var handleFile = File.handleFile = function (file, e) {
|
||||||
|
//if (handleFileState.inProgress) { return void handleFileState.queue.push(file); }
|
||||||
|
handleFileState.inProgress = true;
|
||||||
|
|
||||||
var thumb;
|
var thumb;
|
||||||
var file_arraybuffer;
|
var file_arraybuffer;
|
||||||
|
var name = file.name;
|
||||||
var finish = function () {
|
var finish = function () {
|
||||||
var metadata = {
|
var metadata = {
|
||||||
name: file.name,
|
name: name,
|
||||||
type: file.type,
|
type: file.type,
|
||||||
};
|
};
|
||||||
if (thumb) { metadata.thumbnail = thumb; }
|
if (thumb) { metadata.thumbnail = thumb; }
|
||||||
@@ -234,33 +255,34 @@ define([
|
|||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
dropEvent: e
|
dropEvent: e
|
||||||
});
|
});
|
||||||
|
handleFileState.inProgress = false;
|
||||||
|
if (handleFileState.queue.length) { handleFile(handleFileState.queue.shift()); }
|
||||||
|
};
|
||||||
|
var getName = function () {
|
||||||
|
if (!showNamePrompt) { return void finish(); }
|
||||||
|
promptName(file, function (newName) {
|
||||||
|
name = newName;
|
||||||
|
finish();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
blobToArrayBuffer(file, function (e, buffer) {
|
blobToArrayBuffer(file, function (e, buffer) {
|
||||||
if (e) { console.error(e); }
|
if (e) { console.error(e); }
|
||||||
file_arraybuffer = buffer;
|
file_arraybuffer = buffer;
|
||||||
if (thumbnail) { // there is already a thumbnail
|
if (!Thumb.isSupportedType(file.type)) { return getName(); }
|
||||||
return blobToArrayBuffer(thumbnail, function (e, buffer) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
thumb = arrayBufferToString(buffer);
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Thumb.isSupportedType(file.type)) { return finish(); }
|
|
||||||
// make a resized thumbnail from the image..
|
// make a resized thumbnail from the image..
|
||||||
Thumb.fromBlob(file, function (e, thumb64) {
|
Thumb.fromBlob(file, function (e, thumb64) {
|
||||||
if (e) { console.error(e); }
|
if (e) { console.error(e); }
|
||||||
if (!thumb64) { return finish(); }
|
if (!thumb64) { return getName(); }
|
||||||
thumb = thumb64;
|
thumb = thumb64;
|
||||||
finish();
|
getName();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var onFileDrop = File.onFileDrop = function (file, e) {
|
var onFileDrop = File.onFileDrop = function (file, e) {
|
||||||
if (!common.isLoggedIn()) {
|
if (!common.isLoggedIn()) {
|
||||||
return Cryptpad.alert(common.Messages.upload_mustLogin);
|
return UI.alert(common.Messages.upload_mustLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.prototype.slice.call(file).forEach(function (d) {
|
Array.prototype.slice.call(file).forEach(function (d) {
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
//'/bower_components/chainpad-json-validator/json-ot.js',
|
||||||
|
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
], function ($, ChainPad) {
|
], function ($, UI, JsonOT) {
|
||||||
|
var ChainPad = window.ChainPad;
|
||||||
var History = {};
|
var History = {};
|
||||||
|
|
||||||
var getStates = function (rt) {
|
var getStates = function (rt) {
|
||||||
@@ -29,8 +33,10 @@ define([
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
initialState: '',
|
initialState: '',
|
||||||
patchTransformer: ChainPad.NaiveJSONTransformer,
|
//patchTransformer: ChainPad.NaiveJSONTransformer,
|
||||||
logLevel: 0,
|
//logLevel: 0,
|
||||||
|
//transformFunction: JsonOT.validate,
|
||||||
|
logLevel: config.debug ? 1 : 0,
|
||||||
noPrune: true
|
noPrune: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -81,7 +87,6 @@ define([
|
|||||||
var onReady = function () { };
|
var onReady = function () { };
|
||||||
|
|
||||||
var Messages = common.Messages;
|
var Messages = common.Messages;
|
||||||
var Cryptpad = common.getCryptpadCommon();
|
|
||||||
|
|
||||||
var realtime;
|
var realtime;
|
||||||
|
|
||||||
@@ -98,7 +103,7 @@ define([
|
|||||||
$right.hide();
|
$right.hide();
|
||||||
$cke.hide();
|
$cke.hide();
|
||||||
|
|
||||||
Cryptpad.spinner($hist).get().show();
|
UI.spinner($hist).get().show();
|
||||||
|
|
||||||
var onUpdate;
|
var onUpdate;
|
||||||
|
|
||||||
@@ -121,6 +126,15 @@ define([
|
|||||||
$hist.find('.cp-toolbar-history-next, .cp-toolbar-history-previous').css('visibility', '');
|
$hist.find('.cp-toolbar-history-next, .cp-toolbar-history-previous').css('visibility', '');
|
||||||
if (c === states.length - 1) { $hist.find('.cp-toolbar-history-next').css('visibility', 'hidden'); }
|
if (c === states.length - 1) { $hist.find('.cp-toolbar-history-next').css('visibility', 'hidden'); }
|
||||||
if (c === 0) { $hist.find('.cp-toolbar-history-previous').css('visibility', 'hidden'); }
|
if (c === 0) { $hist.find('.cp-toolbar-history-previous').css('visibility', 'hidden'); }
|
||||||
|
|
||||||
|
if (config.debug) {
|
||||||
|
console.log(states[i]);
|
||||||
|
var ops = states[i] && states[i].getPatch() && states[i].getPatch().operations;
|
||||||
|
if (Array.isArray(ops)) {
|
||||||
|
ops.forEach(function (op) { console.log(op); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return val || '';
|
return val || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -201,11 +215,11 @@ define([
|
|||||||
onClose();
|
onClose();
|
||||||
});
|
});
|
||||||
$rev.click(function () {
|
$rev.click(function () {
|
||||||
Cryptpad.confirm(Messages.history_restorePrompt, function (yes) {
|
UI.confirm(Messages.history_restorePrompt, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
close();
|
close();
|
||||||
onRevert();
|
onRevert();
|
||||||
Cryptpad.log(Messages.history_restoreDone);
|
UI.log(Messages.history_restoreDone);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,13 @@ define([
|
|||||||
var Cryptpad;
|
var Cryptpad;
|
||||||
var Crypto;
|
var Crypto;
|
||||||
var Cryptget;
|
var Cryptget;
|
||||||
|
var SFrameChannel;
|
||||||
var sframeChan;
|
var sframeChan;
|
||||||
var FilePicker;
|
var FilePicker;
|
||||||
var Messenger;
|
var Messenger;
|
||||||
|
var Messaging;
|
||||||
|
var Notifier;
|
||||||
|
var Utils = {};
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
// Load #2, the loading screen is up so grab whatever you need...
|
// Load #2, the loading screen is up so grab whatever you need...
|
||||||
@@ -29,14 +33,25 @@ define([
|
|||||||
'/common/sframe-channel.js',
|
'/common/sframe-channel.js',
|
||||||
'/filepicker/main.js',
|
'/filepicker/main.js',
|
||||||
'/common/common-messenger.js',
|
'/common/common-messenger.js',
|
||||||
], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, SFrameChannel,
|
'/common/common-messaging.js',
|
||||||
_FilePicker, _Messenger) {
|
'/common/common-notifier.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, _SFrameChannel,
|
||||||
|
_FilePicker, _Messenger, _Messaging, _Notifier, _Hash, _Util, _Realtime) {
|
||||||
CpNfOuter = _CpNfOuter;
|
CpNfOuter = _CpNfOuter;
|
||||||
Cryptpad = _Cryptpad;
|
Cryptpad = _Cryptpad;
|
||||||
Crypto = _Crypto;
|
Crypto = _Crypto;
|
||||||
Cryptget = _Cryptget;
|
Cryptget = _Cryptget;
|
||||||
|
SFrameChannel = _SFrameChannel;
|
||||||
FilePicker = _FilePicker;
|
FilePicker = _FilePicker;
|
||||||
Messenger = _Messenger;
|
Messenger = _Messenger;
|
||||||
|
Messaging = _Messaging;
|
||||||
|
Notifier = _Notifier;
|
||||||
|
Utils.Hash = _Hash;
|
||||||
|
Utils.Util = _Util;
|
||||||
|
Utils.Realtime = _Realtime;
|
||||||
|
|
||||||
if (localStorage.CRYPTPAD_URLARGS !== ApiConfig.requireConf.urlArgs) {
|
if (localStorage.CRYPTPAD_URLARGS !== ApiConfig.requireConf.urlArgs) {
|
||||||
console.log("New version, flushing cache");
|
console.log("New version, flushing cache");
|
||||||
@@ -82,18 +97,19 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
secret = cfg.getSecrets ? cfg.getSecrets(Cryptpad) : Cryptpad.getSecrets();
|
secret = cfg.getSecrets ? cfg.getSecrets(Cryptpad, Utils) : Utils.Hash.getSecrets();
|
||||||
if (!secret.channel) {
|
if (!secret.channel) {
|
||||||
// New pad: create a new random channel id
|
// New pad: create a new random channel id
|
||||||
secret.channel = Cryptpad.createChannelId();
|
secret.channel = Utils.Hash.createChannelId();
|
||||||
}
|
}
|
||||||
Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
|
Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
|
||||||
|
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
var readOnly = secret.keys && !secret.keys.editKeyStr;
|
var readOnly = secret.keys && !secret.keys.editKeyStr;
|
||||||
if (!secret.keys) { secret.keys = secret.key; }
|
if (!secret.keys) { secret.keys = secret.key; }
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
if (!parsed.type) { throw new Error(); }
|
if (!parsed.type) { throw new Error(); }
|
||||||
var defaultTitle = Cryptpad.getDefaultName(parsed);
|
var defaultTitle = Utils.Hash.getDefaultName(parsed);
|
||||||
var proxy = Cryptpad.getProxy();
|
var proxy = Cryptpad.getProxy();
|
||||||
var updateMeta = function () {
|
var updateMeta = function () {
|
||||||
//console.log('EV_METADATA_UPDATE');
|
//console.log('EV_METADATA_UPDATE');
|
||||||
@@ -148,20 +164,45 @@ define([
|
|||||||
sframeChan.onReg('EV_METADATA_UPDATE', updateMeta);
|
sframeChan.onReg('EV_METADATA_UPDATE', updateMeta);
|
||||||
proxy.on('change', 'settings', updateMeta);
|
proxy.on('change', 'settings', updateMeta);
|
||||||
|
|
||||||
Cryptpad.onError(function (info) {
|
Cryptpad.onLogout(function () {
|
||||||
console.log('error');
|
sframeChan.event('EV_LOGOUT');
|
||||||
console.log(info);
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
//onConnectError();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Put in the following function the RPC queries that should also work in filepicker
|
||||||
|
var addCommonRpc = function (sframeChan) {
|
||||||
sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) {
|
sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) {
|
||||||
Cryptpad.anonRpcMsg(data.msg, data.content, function (err, response) {
|
Cryptpad.anonRpcMsg(data.msg, data.content, function (err, response) {
|
||||||
cb({error: err, response: response});
|
cb({error: err, response: response});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sframeChan.on('Q_GET_PIN_LIMIT_STATUS', function (data, cb) {
|
||||||
|
Cryptpad.isOverPinLimit(function (e, overLimit, limits) {
|
||||||
|
cb({
|
||||||
|
error: e,
|
||||||
|
overLimit: overLimit,
|
||||||
|
limits: limits
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
sframeChan.on('Q_THUMBNAIL_GET', function (data, cb) {
|
||||||
|
Cryptpad.getThumbnail(data.key, function (e, data) {
|
||||||
|
cb({
|
||||||
|
error: e,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
sframeChan.on('Q_THUMBNAIL_SET', function (data, cb) {
|
||||||
|
Cryptpad.setThumbnail(data.key, data.value, function (e) {
|
||||||
|
cb({error:e});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
addCommonRpc(sframeChan);
|
||||||
|
|
||||||
var currentTitle;
|
var currentTitle;
|
||||||
var currentTabTitle;
|
var currentTabTitle;
|
||||||
var setDocumentTitle = function () {
|
var setDocumentTitle = function () {
|
||||||
@@ -176,7 +217,7 @@ define([
|
|||||||
currentTitle = newTitle;
|
currentTitle = newTitle;
|
||||||
setDocumentTitle();
|
setDocumentTitle();
|
||||||
Cryptpad.renamePad(newTitle, undefined, function (err) {
|
Cryptpad.renamePad(newTitle, undefined, function (err) {
|
||||||
if (err) { cb('ERROR'); } else { cb(); }
|
cb(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
sframeChan.on('EV_SET_TAB_TITLE', function (newTabTitle) {
|
sframeChan.on('EV_SET_TAB_TITLE', function (newTabTitle) {
|
||||||
@@ -203,7 +244,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('EV_NOTIFY', function () {
|
sframeChan.on('EV_NOTIFY', function () {
|
||||||
Cryptpad.notify();
|
Notifier.notify();
|
||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('Q_SET_LOGIN_REDIRECT', function (data, cb) {
|
sframeChan.on('Q_SET_LOGIN_REDIRECT', function (data, cb) {
|
||||||
@@ -211,16 +252,6 @@ define([
|
|||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('Q_GET_PIN_LIMIT_STATUS', function (data, cb) {
|
|
||||||
Cryptpad.isOverPinLimit(function (e, overLimit, limits) {
|
|
||||||
cb({
|
|
||||||
error: e,
|
|
||||||
overLimit: overLimit,
|
|
||||||
limits: limits
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('Q_MOVE_TO_TRASH', function (data, cb) {
|
sframeChan.on('Q_MOVE_TO_TRASH', function (data, cb) {
|
||||||
cb = cb || $.noop;
|
cb = cb || $.noop;
|
||||||
if (readOnly && hashes.editHash) {
|
if (readOnly && hashes.editHash) {
|
||||||
@@ -236,7 +267,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('Q_SEND_FRIEND_REQUEST', function (netfluxId, cb) {
|
sframeChan.on('Q_SEND_FRIEND_REQUEST', function (netfluxId, cb) {
|
||||||
Cryptpad.inviteFromUserlist(Cryptpad, netfluxId);
|
Messaging.inviteFromUserlist(Cryptpad, netfluxId);
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
Cryptpad.onFriendRequest = function (confirmText, cb) {
|
Cryptpad.onFriendRequest = function (confirmText, cb) {
|
||||||
@@ -310,20 +341,6 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
sframeChan.on('Q_THUMBNAIL_GET', function (data, cb) {
|
|
||||||
Cryptpad.getThumbnail(data.key, function (e, data) {
|
|
||||||
cb({
|
|
||||||
error: e,
|
|
||||||
data: data
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
sframeChan.on('Q_THUMBNAIL_SET', function (data, cb) {
|
|
||||||
Cryptpad.setThumbnail(data.key, data.value, function (e) {
|
|
||||||
cb({error:e});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('Q_SESSIONSTORAGE_PUT', function (data, cb) {
|
sframeChan.on('Q_SESSIONSTORAGE_PUT', function (data, cb) {
|
||||||
sessionStorage[data.key] = data.value;
|
sessionStorage[data.key] = data.value;
|
||||||
cb();
|
cb();
|
||||||
@@ -332,11 +349,11 @@ define([
|
|||||||
|
|
||||||
// Present mode URL
|
// Present mode URL
|
||||||
sframeChan.on('Q_PRESENT_URL_GET_VALUE', function (data, cb) {
|
sframeChan.on('Q_PRESENT_URL_GET_VALUE', function (data, cb) {
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
cb(parsed.hashData && parsed.hashData.present);
|
cb(parsed.hashData && parsed.hashData.present);
|
||||||
});
|
});
|
||||||
sframeChan.on('EV_PRESENT_URL_SET_VALUE', function (data) {
|
sframeChan.on('EV_PRESENT_URL_SET_VALUE', function (data) {
|
||||||
var parsed = Cryptpad.parsePadUrl(window.location.href);
|
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
window.location.href = parsed.getUrl({
|
window.location.href = parsed.getUrl({
|
||||||
embed: parsed.hashData.embed,
|
embed: parsed.hashData.embed,
|
||||||
present: data
|
present: data
|
||||||
@@ -346,6 +363,7 @@ define([
|
|||||||
|
|
||||||
// File upload
|
// File upload
|
||||||
var onFileUpload = function (sframeChan, data, cb) {
|
var onFileUpload = function (sframeChan, data, cb) {
|
||||||
|
require(['/common/outer/upload.js'], function (Files) {
|
||||||
var sendEvent = function (data) {
|
var sendEvent = function (data) {
|
||||||
sframeChan.event("EV_FILE_UPLOAD_STATE", data);
|
sframeChan.event("EV_FILE_UPLOAD_STATE", data);
|
||||||
};
|
};
|
||||||
@@ -373,8 +391,9 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
data.blob = Crypto.Nacl.util.decodeBase64(data.blob);
|
data.blob = Crypto.Nacl.util.decodeBase64(data.blob);
|
||||||
Cryptpad.uploadFileSecure(data, data.noStore, Cryptpad, updateProgress, onComplete, onError, onPending);
|
Files.upload(data, data.noStore, Cryptpad, updateProgress, onComplete, onError, onPending);
|
||||||
cb();
|
cb();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
sframeChan.on('Q_UPLOAD_FILE', function (data, cb) {
|
sframeChan.on('Q_UPLOAD_FILE', function (data, cb) {
|
||||||
onFileUpload(sframeChan, data, cb);
|
onFileUpload(sframeChan, data, cb);
|
||||||
@@ -393,6 +412,11 @@ define([
|
|||||||
};
|
};
|
||||||
config.onFileUpload = onFileUpload;
|
config.onFileUpload = onFileUpload;
|
||||||
config.types = cfg;
|
config.types = cfg;
|
||||||
|
config.addCommonRpc = addCommonRpc;
|
||||||
|
config.modules = {
|
||||||
|
Cryptpad: Cryptpad,
|
||||||
|
SFrameChannel: SFrameChannel
|
||||||
|
};
|
||||||
FP.$iframe = $('<iframe>', {id: 'sbox-filePicker-iframe'}).appendTo($('body'));
|
FP.$iframe = $('<iframe>', {id: 'sbox-filePicker-iframe'}).appendTo($('body'));
|
||||||
FP.picker = FilePicker.create(config);
|
FP.picker = FilePicker.create(config);
|
||||||
} else {
|
} else {
|
||||||
@@ -458,7 +482,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (cfg.addRpc) {
|
if (cfg.addRpc) {
|
||||||
cfg.addRpc(sframeChan, Cryptpad);
|
cfg.addRpc(sframeChan, Cryptpad, Utils);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.messaging) {
|
if (cfg.messaging) {
|
||||||
@@ -535,6 +559,13 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
sframeChan.on('Q_CONTACTS_CLEAR_OWNED_CHANNEL', function (channel, cb) {
|
||||||
|
messenger.clearOwnedChannel(channel, function (e) {
|
||||||
|
cb({
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
messenger.on('message', function (message) {
|
messenger.on('message', function (message) {
|
||||||
sframeChan.event('EV_CONTACTS_MESSAGE', message);
|
sframeChan.event('EV_CONTACTS_MESSAGE', message);
|
||||||
@@ -575,6 +606,18 @@ define([
|
|||||||
|
|
||||||
if (!realtime) { return; }
|
if (!realtime) { return; }
|
||||||
|
|
||||||
|
var replaceHash = function (hash) {
|
||||||
|
if (window.history && window.history.replaceState) {
|
||||||
|
if (!/^#/.test(hash)) { hash = '#' + hash; }
|
||||||
|
void window.history.replaceState({}, window.document.title, hash);
|
||||||
|
if (typeof(window.onhashchange) === 'function') {
|
||||||
|
window.onhashchange();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.location.hash = hash;
|
||||||
|
};
|
||||||
|
|
||||||
CpNfOuter.start({
|
CpNfOuter.start({
|
||||||
sframeChan: sframeChan,
|
sframeChan: sframeChan,
|
||||||
channel: secret.channel,
|
channel: secret.channel,
|
||||||
@@ -591,7 +634,7 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (readOnly || cfg.noHash) { return; }
|
if (readOnly || cfg.noHash) { return; }
|
||||||
Cryptpad.replaceHash(Cryptpad.getEditHashFromKeys(wc.id, secret.keys));
|
replaceHash(Utils.Hash.getEditHashFromKeys(wc.id, secret.keys));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/common-util.js'
|
'/common/common-util.js',
|
||||||
], function ($, Util) {
|
'/common/common-interface.js',
|
||||||
|
'/customize/messages.js'
|
||||||
|
], function ($, Util, UI, Messages) {
|
||||||
var module = {};
|
var module = {};
|
||||||
|
|
||||||
module.create = function (Common, cfg) {
|
module.create = function (Common, cfg) {
|
||||||
@@ -54,7 +56,9 @@ define([
|
|||||||
});
|
});
|
||||||
metadataMgr.onTitleChange(function (title) {
|
metadataMgr.onTitleChange(function (title) {
|
||||||
sframeChan.query('Q_SET_PAD_TITLE_IN_DRIVE', title, function (err) {
|
sframeChan.query('Q_SET_PAD_TITLE_IN_DRIVE', title, function (err) {
|
||||||
if (err) { return; }
|
if (err === 'E_OVER_LIMIT') {
|
||||||
|
return void UI.alert(Messages.pinLimitNotPinned, null, true);
|
||||||
|
} else if (err) { return; }
|
||||||
evTitleChange.fire(title);
|
evTitleChange.fire(title);
|
||||||
if (titleUpdated) { titleUpdated(undefined, title); }
|
if (titleUpdated) { titleUpdated(undefined, title); }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,17 +5,18 @@ define([
|
|||||||
'/common/sframe-chainpad-netflux-inner.js',
|
'/common/sframe-chainpad-netflux-inner.js',
|
||||||
'/common/sframe-channel.js',
|
'/common/sframe-channel.js',
|
||||||
'/common/sframe-common-title.js',
|
'/common/sframe-common-title.js',
|
||||||
'/common/sframe-common-interface.js',
|
'/common/common-ui-elements.js',
|
||||||
'/common/sframe-common-history.js',
|
'/common/sframe-common-history.js',
|
||||||
'/common/sframe-common-file.js',
|
'/common/sframe-common-file.js',
|
||||||
'/common/sframe-common-codemirror.js',
|
'/common/sframe-common-codemirror.js',
|
||||||
'/common/metadata-manager.js',
|
'/common/metadata-manager.js',
|
||||||
|
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/common-realtime.js',
|
'/common/common-realtime.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
'/common/common-thumbnail.js',
|
'/common/common-thumbnail.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
'/bower_components/localforage/dist/localforage.min.js'
|
'/bower_components/localforage/dist/localforage.min.js'
|
||||||
], function (
|
], function (
|
||||||
$,
|
$,
|
||||||
@@ -24,16 +25,17 @@ define([
|
|||||||
CpNfInner,
|
CpNfInner,
|
||||||
SFrameChannel,
|
SFrameChannel,
|
||||||
Title,
|
Title,
|
||||||
UI,
|
UIElements,
|
||||||
History,
|
History,
|
||||||
File,
|
File,
|
||||||
CodeMirror,
|
CodeMirror,
|
||||||
MetadataMgr,
|
MetadataMgr,
|
||||||
AppConfig,
|
AppConfig,
|
||||||
Cryptpad,
|
|
||||||
CommonRealtime,
|
CommonRealtime,
|
||||||
Util,
|
Util,
|
||||||
|
Hash,
|
||||||
Thumb,
|
Thumb,
|
||||||
|
UI,
|
||||||
localForage
|
localForage
|
||||||
) {
|
) {
|
||||||
// Chainpad Netflux Inner
|
// Chainpad Netflux Inner
|
||||||
@@ -55,7 +57,6 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
funcs.getMetadataMgr = function () { return ctx.metadataMgr; };
|
funcs.getMetadataMgr = function () { return ctx.metadataMgr; };
|
||||||
funcs.getCryptpadCommon = function () { return Cryptpad; };
|
|
||||||
funcs.getSframeChannel = function () { return ctx.sframeChan; };
|
funcs.getSframeChannel = function () { return ctx.sframeChan; };
|
||||||
funcs.getAppConfig = function () { return AppConfig; };
|
funcs.getAppConfig = function () { return AppConfig; };
|
||||||
|
|
||||||
@@ -74,16 +75,16 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
funcs.createUserAdminMenu = callWithCommon(UI.createUserAdminMenu);
|
funcs.createUserAdminMenu = callWithCommon(UIElements.createUserAdminMenu);
|
||||||
funcs.initFilePicker = callWithCommon(UI.initFilePicker);
|
funcs.initFilePicker = callWithCommon(UIElements.initFilePicker);
|
||||||
funcs.openFilePicker = callWithCommon(UI.openFilePicker);
|
funcs.openFilePicker = callWithCommon(UIElements.openFilePicker);
|
||||||
funcs.openTemplatePicker = callWithCommon(UI.openTemplatePicker);
|
funcs.openTemplatePicker = callWithCommon(UIElements.openTemplatePicker);
|
||||||
funcs.displayMediatagImage = callWithCommon(UI.displayMediatagImage);
|
funcs.displayMediatagImage = callWithCommon(UIElements.displayMediatagImage);
|
||||||
funcs.displayAvatar = callWithCommon(UI.displayAvatar);
|
funcs.displayAvatar = callWithCommon(UIElements.displayAvatar);
|
||||||
funcs.createButton = callWithCommon(UI.createButton);
|
funcs.createButton = callWithCommon(UIElements.createButton);
|
||||||
funcs.createUsageBar = callWithCommon(UI.createUsageBar);
|
funcs.createUsageBar = callWithCommon(UIElements.createUsageBar);
|
||||||
funcs.updateTags = callWithCommon(UI.updateTags);
|
funcs.updateTags = callWithCommon(UIElements.updateTags);
|
||||||
funcs.createLanguageSelector = callWithCommon(UI.createLanguageSelector);
|
funcs.createLanguageSelector = callWithCommon(UIElements.createLanguageSelector);
|
||||||
|
|
||||||
// Thumb
|
// Thumb
|
||||||
funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail);
|
funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail);
|
||||||
@@ -102,21 +103,21 @@ define([
|
|||||||
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>';
|
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>';
|
||||||
};
|
};
|
||||||
funcs.getMediatagFromHref = function (href) {
|
funcs.getMediatagFromHref = function (href) {
|
||||||
var parsed = Cryptpad.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var secret = Cryptpad.getSecrets('file', parsed.hash);
|
var secret = Hash.getSecrets('file', parsed.hash);
|
||||||
var data = ctx.metadataMgr.getPrivateData();
|
var data = ctx.metadataMgr.getPrivateData();
|
||||||
if (secret.keys && secret.channel) {
|
if (secret.keys && secret.channel) {
|
||||||
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||||
var hexFileName = Cryptpad.base64ToHex(secret.channel);
|
var hexFileName = Util.base64ToHex(secret.channel);
|
||||||
var origin = data.fileHost || data.origin;
|
var origin = data.fileHost || data.origin;
|
||||||
var src = origin + Cryptpad.getBlobPathFromHex(hexFileName);
|
var src = origin + Hash.getBlobPathFromHex(hexFileName);
|
||||||
return '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + cryptKey + '">' +
|
return '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + cryptKey + '">' +
|
||||||
'</media-tag>';
|
'</media-tag>';
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
funcs.getFileSize = function (href, cb) {
|
funcs.getFileSize = function (href, cb) {
|
||||||
var channelId = Cryptpad.hrefToHexChannelId(href);
|
var channelId = Hash.hrefToHexChannelId(href);
|
||||||
funcs.sendAnonRpcMsg("GET_FILE_SIZE", channelId, function (data) {
|
funcs.sendAnonRpcMsg("GET_FILE_SIZE", channelId, function (data) {
|
||||||
if (!data) { return void cb("No response"); }
|
if (!data) { return void cb("No response"); }
|
||||||
if (data.error) { return void cb(data.error); }
|
if (data.error) { return void cb(data.error); }
|
||||||
@@ -313,6 +314,14 @@ define([
|
|||||||
|
|
||||||
funcs.whenRealtimeSyncs = evRealtimeSynced.reg;
|
funcs.whenRealtimeSyncs = evRealtimeSynced.reg;
|
||||||
|
|
||||||
|
var logoutHandlers = [];
|
||||||
|
funcs.onLogout = function (h) {
|
||||||
|
if (typeof (h) !== "function") { return; }
|
||||||
|
if (logoutHandlers.indexOf(h) !== -1) { return; }
|
||||||
|
logoutHandlers.push(h);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Object.freeze(funcs);
|
Object.freeze(funcs);
|
||||||
return { create: function (cb) {
|
return { create: function (cb) {
|
||||||
|
|
||||||
@@ -359,17 +368,30 @@ define([
|
|||||||
|
|
||||||
UI.addTooltips();
|
UI.addTooltips();
|
||||||
|
|
||||||
|
ctx.sframeChan.on('EV_LOGOUT', function () {
|
||||||
|
$(window).on('keyup', function (e) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
UI.removeLoadingScreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
UI.addLoadingScreen({hideTips: true});
|
||||||
|
UI.errorLoadingScreen(Messages.onLogout, true);
|
||||||
|
logoutHandlers.forEach(function (h) {
|
||||||
|
if (typeof (h) === "function") { h(); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ctx.sframeChan.on('EV_RT_CONNECT', function () { CommonRealtime.setConnectionState(true); });
|
ctx.sframeChan.on('EV_RT_CONNECT', function () { CommonRealtime.setConnectionState(true); });
|
||||||
ctx.sframeChan.on('EV_RT_DISCONNECT', function () { CommonRealtime.setConnectionState(false); });
|
ctx.sframeChan.on('EV_RT_DISCONNECT', function () { CommonRealtime.setConnectionState(false); });
|
||||||
|
|
||||||
|
|
||||||
ctx.sframeChan.on('Q_INCOMING_FRIEND_REQUEST', function (confirmMsg, cb) {
|
ctx.sframeChan.on('Q_INCOMING_FRIEND_REQUEST', function (confirmMsg, cb) {
|
||||||
Cryptpad.confirm(confirmMsg, cb, null, true);
|
UI.confirm(confirmMsg, cb, null, true);
|
||||||
});
|
});
|
||||||
ctx.sframeChan.on('EV_FRIEND_REQUEST', function (data) {
|
ctx.sframeChan.on('EV_FRIEND_REQUEST', function (data) {
|
||||||
var i = pendingFriends.indexOf(data.netfluxId);
|
var i = pendingFriends.indexOf(data.netfluxId);
|
||||||
if (i !== -1) { pendingFriends.splice(i, 1); }
|
if (i !== -1) { pendingFriends.splice(i, 1); }
|
||||||
Cryptpad.log(data.logText);
|
UI.log(data.logText);
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.sframeChan.ready();
|
ctx.sframeChan.ready();
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ define([], function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
messenger.clearOwnedChannel = function (channel, cb) {
|
||||||
|
sFrameChan.query('Q_CONTACTS_CLEAR_OWNED_CHANNEL', channel, function (e) {
|
||||||
|
cb(e);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return messenger;
|
return messenger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,677 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
|
||||||
'/common/curve.js',
|
|
||||||
'/common/common-hash.js',
|
|
||||||
], function ($, Crypto, Curve, Hash) {
|
|
||||||
'use strict';
|
|
||||||
var Msg = {
|
|
||||||
inputs: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
var Types = {
|
|
||||||
message: 'MSG',
|
|
||||||
update: 'UPDATE',
|
|
||||||
unfriend: 'UNFRIEND',
|
|
||||||
mapId: 'MAP_ID',
|
|
||||||
mapIdAck: 'MAP_ID_ACK'
|
|
||||||
};
|
|
||||||
|
|
||||||
var clone = function (o) {
|
|
||||||
return JSON.parse(JSON.stringify(o));
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
// - mute a channel (hide notifications or don't open it?)
|
|
||||||
var createData = Msg.createData = function (proxy, hash) {
|
|
||||||
return {
|
|
||||||
channel: hash || Hash.createChannelId(),
|
|
||||||
displayName: proxy['cryptpad.username'],
|
|
||||||
profile: proxy.profile && proxy.profile.view,
|
|
||||||
edPublic: proxy.edPublic,
|
|
||||||
curvePublic: proxy.curvePublic,
|
|
||||||
avatar: proxy.profile && proxy.profile.avatar
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var getFriend = function (proxy, pubkey) {
|
|
||||||
if (pubkey === proxy.curvePublic) {
|
|
||||||
var data = createData(proxy);
|
|
||||||
delete data.channel;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
return proxy.friends ? proxy.friends[pubkey] : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
var getFriendList = Msg.getFriendList = function (proxy) {
|
|
||||||
if (!proxy.friends) { proxy.friends = {}; }
|
|
||||||
return proxy.friends;
|
|
||||||
};
|
|
||||||
|
|
||||||
var eachFriend = function (friends, cb) {
|
|
||||||
Object.keys(friends).forEach(function (id) {
|
|
||||||
if (id === 'me') { return; }
|
|
||||||
cb(friends[id], id, friends);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Msg.getFriendChannelsList = function (proxy) {
|
|
||||||
var list = [];
|
|
||||||
eachFriend(proxy, function (friend) {
|
|
||||||
list.push(friend.channel);
|
|
||||||
});
|
|
||||||
return list;
|
|
||||||
};
|
|
||||||
|
|
||||||
var msgAlreadyKnown = function (channel, sig) {
|
|
||||||
return channel.messages.some(function (message) {
|
|
||||||
return message[0] === sig;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Msg.messenger = function (common) {
|
|
||||||
var messenger = {
|
|
||||||
handlers: {
|
|
||||||
message: [],
|
|
||||||
join: [],
|
|
||||||
leave: [],
|
|
||||||
update: [],
|
|
||||||
friend: [],
|
|
||||||
unfriend: [],
|
|
||||||
},
|
|
||||||
range_requests: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
var eachHandler = function (type, g) {
|
|
||||||
messenger.handlers[type].forEach(g);
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.on = function (type, f) {
|
|
||||||
var stack = messenger.handlers[type];
|
|
||||||
if (!Array.isArray(stack)) {
|
|
||||||
return void console.error('unsupported message type');
|
|
||||||
}
|
|
||||||
if (typeof(f) !== 'function') {
|
|
||||||
return void console.error('expected function');
|
|
||||||
}
|
|
||||||
stack.push(f);
|
|
||||||
};
|
|
||||||
|
|
||||||
var channels = messenger.channels = {};
|
|
||||||
|
|
||||||
var joining = {};
|
|
||||||
|
|
||||||
// declare common variables
|
|
||||||
var network = common.getNetwork();
|
|
||||||
var proxy = common.getProxy();
|
|
||||||
var realtime = common.getRealtime();
|
|
||||||
Msg.hk = network.historyKeeper;
|
|
||||||
var friends = getFriendList(proxy);
|
|
||||||
|
|
||||||
var getChannel = function (curvePublic) {
|
|
||||||
var friend = friends[curvePublic];
|
|
||||||
if (!friend) { return; }
|
|
||||||
var chanId = friend.channel;
|
|
||||||
if (!chanId) { return; }
|
|
||||||
return channels[chanId];
|
|
||||||
};
|
|
||||||
|
|
||||||
var initRangeRequest = function (txid, curvePublic, sig, cb) {
|
|
||||||
messenger.range_requests[txid] = {
|
|
||||||
messages: [],
|
|
||||||
cb: cb,
|
|
||||||
curvePublic: curvePublic,
|
|
||||||
sig: sig,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var getRangeRequest = function (txid) {
|
|
||||||
return messenger.range_requests[txid];
|
|
||||||
};
|
|
||||||
|
|
||||||
var deleteRangeRequest = function (txid) {
|
|
||||||
delete messenger.range_requests[txid];
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.getMoreHistory = function (curvePublic, hash, count, cb) {
|
|
||||||
if (typeof(cb) !== 'function') { return; }
|
|
||||||
|
|
||||||
if (typeof(hash) !== 'string') {
|
|
||||||
// FIXME hash is not necessarily defined.
|
|
||||||
// What does this mean?
|
|
||||||
console.error("not sure what to do here");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var chan = getChannel(curvePublic);
|
|
||||||
if (typeof(chan) === 'undefined') {
|
|
||||||
console.error("chan is undefined. we're going to have a problem here");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var txid = common.uid();
|
|
||||||
initRangeRequest(txid, curvePublic, hash, cb);
|
|
||||||
var msg = [ 'GET_HISTORY_RANGE', chan.id, {
|
|
||||||
from: hash,
|
|
||||||
count: count,
|
|
||||||
txid: txid,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
network.sendto(network.historyKeeper, JSON.stringify(msg)).then(function () {
|
|
||||||
}, function (err) {
|
|
||||||
throw new Error(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var getCurveForChannel = function (id) {
|
|
||||||
var channel = channels[id];
|
|
||||||
if (!channel) { return; }
|
|
||||||
return channel.curve;
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.getChannelHead = function (curvePublic, cb) {
|
|
||||||
var friend = friends[curvePublic];
|
|
||||||
if (!friend) { return void cb('NO_SUCH_FRIEND'); }
|
|
||||||
cb(void 0, friend.lastKnownHash);
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.setChannelHead = function (curvePublic, hash, cb) {
|
|
||||||
var friend = friends[curvePublic];
|
|
||||||
if (!friend) { return void cb('NO_SUCH_FRIEND'); }
|
|
||||||
friend.lastKnownHash = hash;
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Id message allows us to map a netfluxId with a public curve key
|
|
||||||
var onIdMessage = function (msg, sender) {
|
|
||||||
var channel;
|
|
||||||
var isId = Object.keys(channels).some(function (chanId) {
|
|
||||||
if (channels[chanId].userList.indexOf(sender) !== -1) {
|
|
||||||
channel = channels[chanId];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isId) { return; }
|
|
||||||
|
|
||||||
var decryptedMsg = channel.encryptor.decrypt(msg);
|
|
||||||
|
|
||||||
if (decryptedMsg === null) {
|
|
||||||
return void console.error("Failed to decrypt message");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!decryptedMsg) {
|
|
||||||
console.error('decrypted message was falsey but not null');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var parsed;
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(decryptedMsg);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(decryptedMsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parsed[0] !== Types.mapId && parsed[0] !== Types.mapIdAck) { return; }
|
|
||||||
|
|
||||||
// check that the responding peer's encrypted netflux id matches
|
|
||||||
// the sender field. This is to prevent replay attacks.
|
|
||||||
if (parsed[2] !== sender || !parsed[1]) { return; }
|
|
||||||
channel.mapId[sender] = parsed[1];
|
|
||||||
eachHandler('join', function (f) {
|
|
||||||
f(parsed[1], channel.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (parsed[0] !== Types.mapId) { return; } // Don't send your key if it's already an ACK
|
|
||||||
// Answer with your own key
|
|
||||||
var rMsg = [Types.mapIdAck, proxy.curvePublic, channel.wc.myID];
|
|
||||||
var rMsgStr = JSON.stringify(rMsg);
|
|
||||||
var cryptMsg = channel.encryptor.encrypt(rMsgStr);
|
|
||||||
network.sendto(sender, cryptMsg);
|
|
||||||
};
|
|
||||||
|
|
||||||
var orderMessages = function (curvePublic, new_messages /*, sig */) {
|
|
||||||
var channel = getChannel(curvePublic);
|
|
||||||
var messages = channel.messages;
|
|
||||||
|
|
||||||
// TODO improve performance, guarantee correct ordering
|
|
||||||
new_messages.reverse().forEach(function (msg) {
|
|
||||||
messages.unshift(msg);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var removeFromFriendList = function (curvePublic, cb) {
|
|
||||||
if (!proxy.friends) { return; }
|
|
||||||
var friends = proxy.friends;
|
|
||||||
delete friends[curvePublic];
|
|
||||||
common.whenRealtimeSyncs(realtime, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
var pushMsg = function (channel, cryptMsg) {
|
|
||||||
var msg = channel.encryptor.decrypt(cryptMsg);
|
|
||||||
var sig = cryptMsg.slice(0, 64);
|
|
||||||
if (msgAlreadyKnown(channel, sig)) { return; }
|
|
||||||
|
|
||||||
var parsedMsg = JSON.parse(msg);
|
|
||||||
var curvePublic;
|
|
||||||
if (parsedMsg[0] === Types.message) {
|
|
||||||
// TODO validate messages here
|
|
||||||
var res = {
|
|
||||||
type: parsedMsg[0],
|
|
||||||
sig: sig,
|
|
||||||
author: parsedMsg[1],
|
|
||||||
time: parsedMsg[2],
|
|
||||||
text: parsedMsg[3],
|
|
||||||
// this makes debugging a whole lot easier
|
|
||||||
curve: getCurveForChannel(channel.id),
|
|
||||||
};
|
|
||||||
|
|
||||||
channel.messages.push(res);
|
|
||||||
eachHandler('message', function (f) {
|
|
||||||
f(res);
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (parsedMsg[0] === Types.update) {
|
|
||||||
if (parsedMsg[1] === proxy.curvePublic) { return; }
|
|
||||||
curvePublic = parsedMsg[1];
|
|
||||||
var newdata = parsedMsg[3];
|
|
||||||
var data = getFriend(proxy, parsedMsg[1]);
|
|
||||||
var types = [];
|
|
||||||
Object.keys(newdata).forEach(function (k) {
|
|
||||||
if (data[k] !== newdata[k]) {
|
|
||||||
types.push(k);
|
|
||||||
data[k] = newdata[k];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
eachHandler('update', function (f) {
|
|
||||||
f(clone(newdata), curvePublic);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parsedMsg[0] === Types.unfriend) {
|
|
||||||
curvePublic = parsedMsg[1];
|
|
||||||
delete friends[curvePublic];
|
|
||||||
|
|
||||||
removeFromFriendList(parsedMsg[1], function () {
|
|
||||||
channel.wc.leave(Types.unfriend);
|
|
||||||
eachHandler('unfriend', function (f) {
|
|
||||||
f(curvePublic);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Broadcast a display name, profile, or avatar change to all contacts
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO send event...
|
|
||||||
messenger.updateMyData = function () {
|
|
||||||
var friends = getFriendList(proxy);
|
|
||||||
var mySyncData = friends.me;
|
|
||||||
var myData = createData(proxy);
|
|
||||||
if (!mySyncData || mySyncData.displayName !== myData.displayName
|
|
||||||
|| mySyncData.profile !== myData.profile
|
|
||||||
|| mySyncData.avatar !== myData.avatar) {
|
|
||||||
delete myData.channel;
|
|
||||||
Object.keys(channels).forEach(function (chan) {
|
|
||||||
var channel = channels[chan];
|
|
||||||
|
|
||||||
if (!channel) {
|
|
||||||
return void console.error('NO_SUCH_CHANNEL');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var msg = [Types.update, myData.curvePublic, +new Date(), myData];
|
|
||||||
var msgStr = JSON.stringify(msg);
|
|
||||||
var cryptMsg = channel.encryptor.encrypt(msgStr);
|
|
||||||
channel.wc.bcast(cryptMsg).then(function () {
|
|
||||||
// TODO send event
|
|
||||||
//channel.refresh();
|
|
||||||
}, function (err) {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
eachHandler('update', function (f) {
|
|
||||||
f(myData, myData.curvePublic);
|
|
||||||
});
|
|
||||||
friends.me = myData;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var onChannelReady = function (chanId) {
|
|
||||||
var cb = joining[chanId];
|
|
||||||
if (typeof(cb) !== 'function') {
|
|
||||||
return void console.error('channel ready without callback');
|
|
||||||
}
|
|
||||||
delete joining[chanId];
|
|
||||||
return cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
var onDirectMessage = function (common, msg, sender) {
|
|
||||||
if (sender !== Msg.hk) { return void onIdMessage(msg, sender); }
|
|
||||||
var parsed = JSON.parse(msg);
|
|
||||||
|
|
||||||
if (/HISTORY_RANGE/.test(parsed[0])) {
|
|
||||||
//console.log(parsed);
|
|
||||||
var txid = parsed[1];
|
|
||||||
var req = getRangeRequest(txid);
|
|
||||||
var type = parsed[0];
|
|
||||||
if (!req) {
|
|
||||||
return void console.error("received response to unknown request");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'HISTORY_RANGE') {
|
|
||||||
req.messages.push(parsed[2]);
|
|
||||||
} else if (type === 'HISTORY_RANGE_END') {
|
|
||||||
// process all the messages (decrypt)
|
|
||||||
var curvePublic = req.curvePublic;
|
|
||||||
var channel = getChannel(curvePublic);
|
|
||||||
|
|
||||||
var decrypted = req.messages.map(function (msg) {
|
|
||||||
if (msg[2] !== 'MSG') { return; }
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
d: JSON.parse(channel.encryptor.decrypt(msg[4])),
|
|
||||||
sig: msg[4].slice(0, 64),
|
|
||||||
};
|
|
||||||
} catch (e) {
|
|
||||||
console.log('failed to decrypt');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}).filter(function (decrypted) {
|
|
||||||
return decrypted;
|
|
||||||
}).map(function (O) {
|
|
||||||
return {
|
|
||||||
type: O.d[0],
|
|
||||||
sig: O.sig,
|
|
||||||
author: O.d[1],
|
|
||||||
time: O.d[2],
|
|
||||||
text: O.d[3],
|
|
||||||
curve: curvePublic,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
orderMessages(curvePublic, decrypted, req.sig);
|
|
||||||
req.cb(void 0, decrypted);
|
|
||||||
return deleteRangeRequest(txid);
|
|
||||||
} else {
|
|
||||||
console.log(parsed);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((parsed.validateKey || parsed.owners) && parsed.channel) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parsed.state && parsed.state === 1 && parsed.channel) {
|
|
||||||
if (channels[parsed.channel]) {
|
|
||||||
// parsed.channel is Ready
|
|
||||||
// channel[parsed.channel].ready();
|
|
||||||
channels[parsed.channel].ready = true;
|
|
||||||
onChannelReady(parsed.channel);
|
|
||||||
var updateTypes = channels[parsed.channel].updateOnReady;
|
|
||||||
if (updateTypes) {
|
|
||||||
|
|
||||||
//channels[parsed.channel].updateUI(updateTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var chan = parsed[3];
|
|
||||||
if (!chan || !channels[chan]) { return; }
|
|
||||||
pushMsg(channels[chan], parsed[4]);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onMessage = function (msg, sender, chan) {
|
|
||||||
if (!channels[chan.id]) { return; }
|
|
||||||
|
|
||||||
var isMessage = pushMsg(channels[chan.id], msg);
|
|
||||||
if (isMessage) {
|
|
||||||
if (channels[chan.id].wc.myID !== sender) {
|
|
||||||
// Don't notify for your own messages
|
|
||||||
//channels[chan.id].notify();
|
|
||||||
}
|
|
||||||
//channels[chan.id].refresh();
|
|
||||||
// TODO emit message event
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// listen for messages...
|
|
||||||
network.on('message', function(msg, sender) {
|
|
||||||
onDirectMessage(common, msg, sender);
|
|
||||||
});
|
|
||||||
|
|
||||||
messenger.removeFriend = function (curvePublic, cb) {
|
|
||||||
if (typeof(cb) !== 'function') { throw new Error('NO_CALLBACK'); }
|
|
||||||
var data = getFriend(proxy, curvePublic);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
// friend is not valid
|
|
||||||
console.error('friend is not valid');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var channel = channels[data.channel];
|
|
||||||
if (!channel) {
|
|
||||||
return void cb("NO_SUCH_CHANNEL");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!network.webChannels.some(function (wc) {
|
|
||||||
return wc.id === channel.id;
|
|
||||||
})) {
|
|
||||||
console.error('bad channel: ', curvePublic);
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg = [Types.unfriend, proxy.curvePublic, +new Date()];
|
|
||||||
var msgStr = JSON.stringify(msg);
|
|
||||||
var cryptMsg = channel.encryptor.encrypt(msgStr);
|
|
||||||
|
|
||||||
// TODO emit remove_friend event?
|
|
||||||
try {
|
|
||||||
channel.wc.bcast(cryptMsg).then(function () {
|
|
||||||
delete friends[curvePublic];
|
|
||||||
delete channels[curvePublic];
|
|
||||||
common.whenRealtimeSyncs(realtime, function () {
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
console.error(err);
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
cb(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var getChannelMessagesSince = function (chan, data, keys) {
|
|
||||||
console.log('Fetching [%s] messages since [%s]', data.curvePublic, data.lastKnownHash || '');
|
|
||||||
var cfg = {
|
|
||||||
validateKey: keys.validateKey,
|
|
||||||
owners: [proxy.edPublic, data.edPublic],
|
|
||||||
lastKnownHash: data.lastKnownHash
|
|
||||||
};
|
|
||||||
var msg = ['GET_HISTORY', chan.id, cfg];
|
|
||||||
network.sendto(network.historyKeeper, JSON.stringify(msg))
|
|
||||||
.then($.noop, function (err) {
|
|
||||||
throw new Error(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var openFriendChannel = function (data, f) {
|
|
||||||
var keys = Curve.deriveKeys(data.curvePublic, proxy.curvePrivate);
|
|
||||||
var encryptor = Curve.createEncryptor(keys);
|
|
||||||
network.join(data.channel).then(function (chan) {
|
|
||||||
var channel = channels[data.channel] = {
|
|
||||||
id: data.channel,
|
|
||||||
sending: false,
|
|
||||||
friendEd: f,
|
|
||||||
keys: keys,
|
|
||||||
curve: data.curvePublic,
|
|
||||||
encryptor: encryptor,
|
|
||||||
messages: [],
|
|
||||||
wc: chan,
|
|
||||||
userList: [],
|
|
||||||
mapId: {},
|
|
||||||
send: function (payload, cb) {
|
|
||||||
if (!network.webChannels.some(function (wc) {
|
|
||||||
if (wc.id === channel.wc.id) { return true; }
|
|
||||||
})) {
|
|
||||||
return void cb('NO_SUCH_CHANNEL');
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg = [Types.message, proxy.curvePublic, +new Date(), payload];
|
|
||||||
var msgStr = JSON.stringify(msg);
|
|
||||||
var cryptMsg = channel.encryptor.encrypt(msgStr);
|
|
||||||
|
|
||||||
channel.wc.bcast(cryptMsg).then(function () {
|
|
||||||
pushMsg(channel, cryptMsg);
|
|
||||||
cb();
|
|
||||||
}, function (err) {
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
chan.on('message', function (msg, sender) {
|
|
||||||
onMessage(msg, sender, chan);
|
|
||||||
});
|
|
||||||
|
|
||||||
var onJoining = function (peer) {
|
|
||||||
if (peer === Msg.hk) { return; }
|
|
||||||
if (channel.userList.indexOf(peer) !== -1) { return; }
|
|
||||||
|
|
||||||
channel.userList.push(peer);
|
|
||||||
var msg = [Types.mapId, proxy.curvePublic, chan.myID];
|
|
||||||
var msgStr = JSON.stringify(msg);
|
|
||||||
var cryptMsg = channel.encryptor.encrypt(msgStr);
|
|
||||||
network.sendto(peer, cryptMsg);
|
|
||||||
};
|
|
||||||
chan.members.forEach(function (peer) {
|
|
||||||
if (peer === Msg.hk) { return; }
|
|
||||||
if (channel.userList.indexOf(peer) !== -1) { return; }
|
|
||||||
channel.userList.push(peer);
|
|
||||||
});
|
|
||||||
chan.on('join', onJoining);
|
|
||||||
chan.on('leave', function (peer) {
|
|
||||||
var curvePublic = channel.mapId[peer];
|
|
||||||
var i = channel.userList.indexOf(peer);
|
|
||||||
while (i !== -1) {
|
|
||||||
channel.userList.splice(i, 1);
|
|
||||||
i = channel.userList.indexOf(peer);
|
|
||||||
}
|
|
||||||
// update status
|
|
||||||
if (!curvePublic) { return; }
|
|
||||||
eachHandler('leave', function (f) {
|
|
||||||
f(curvePublic, channel.id);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME don't subscribe to the channel implicitly
|
|
||||||
getChannelMessagesSince(chan, data, keys);
|
|
||||||
}, function (err) {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.getFriendList = function (cb) {
|
|
||||||
var friends = proxy.friends;
|
|
||||||
if (!friends) { return void cb(void 0, []); }
|
|
||||||
|
|
||||||
cb(void 0, Object.keys(proxy.friends).filter(function (k) {
|
|
||||||
return k !== 'me';
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.openFriendChannel = function (curvePublic, cb) {
|
|
||||||
if (typeof(curvePublic) !== 'string') { return void cb('INVALID_ID'); }
|
|
||||||
if (typeof(cb) !== 'function') { throw new Error('expected callback'); }
|
|
||||||
|
|
||||||
var friend = clone(friends[curvePublic]);
|
|
||||||
if (typeof(friend) !== 'object') {
|
|
||||||
return void cb('NO_FRIEND_DATA');
|
|
||||||
}
|
|
||||||
var channel = friend.channel;
|
|
||||||
if (!channel) { return void cb('E_NO_CHANNEL'); }
|
|
||||||
joining[channel] = cb;
|
|
||||||
openFriendChannel(friend, curvePublic);
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.sendMessage = function (curvePublic, payload, cb) {
|
|
||||||
var channel = getChannel(curvePublic);
|
|
||||||
if (!channel) { return void cb('NO_CHANNEL'); }
|
|
||||||
if (!network.webChannels.some(function (wc) {
|
|
||||||
if (wc.id === channel.wc.id) { return true; }
|
|
||||||
})) {
|
|
||||||
return void cb('NO_SUCH_CHANNEL');
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg = [Types.message, proxy.curvePublic, +new Date(), payload];
|
|
||||||
var msgStr = JSON.stringify(msg);
|
|
||||||
var cryptMsg = channel.encryptor.encrypt(msgStr);
|
|
||||||
|
|
||||||
channel.wc.bcast(cryptMsg).then(function () {
|
|
||||||
pushMsg(channel, cryptMsg);
|
|
||||||
cb();
|
|
||||||
}, function (err) {
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.getStatus = function (curvePublic, cb) {
|
|
||||||
var channel = getChannel(curvePublic);
|
|
||||||
if (!channel) { return void cb('NO_SUCH_CHANNEL'); }
|
|
||||||
var online = channel.userList.some(function (nId) {
|
|
||||||
return channel.mapId[nId] === curvePublic;
|
|
||||||
});
|
|
||||||
cb(void 0, online);
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.getFriendInfo = function (curvePublic, cb) {
|
|
||||||
setTimeout(function () {
|
|
||||||
var friend = friends[curvePublic];
|
|
||||||
if (!friend) { return void cb('NO_SUCH_FRIEND'); }
|
|
||||||
// this clone will be redundant when ui uses postmessage
|
|
||||||
cb(void 0, clone(friend));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.getMyInfo = function (cb) {
|
|
||||||
cb(void 0, {
|
|
||||||
curvePublic: proxy.curvePublic,
|
|
||||||
displayName: common.getDisplayName(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO listen for changes to your friend list
|
|
||||||
// emit 'update' events for clients
|
|
||||||
|
|
||||||
//var update = function (curvePublic
|
|
||||||
proxy.on('change', ['friends'], function (o, n, p) {
|
|
||||||
var curvePublic;
|
|
||||||
if (o === undefined) {
|
|
||||||
// new friend added
|
|
||||||
curvePublic = p.slice(-1)[0];
|
|
||||||
eachHandler('friend', function (f) {
|
|
||||||
f(curvePublic, clone(n));
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error(o, n, p);
|
|
||||||
}).on('remove', ['friends'], function (o, p) {
|
|
||||||
eachHandler('unfriend', function (f) {
|
|
||||||
f(p[1]); // TODO
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.freeze(messenger);
|
|
||||||
|
|
||||||
return messenger;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Msg;
|
|
||||||
});
|
|
||||||
@@ -56,6 +56,8 @@ define({
|
|||||||
|
|
||||||
// Log the user out in all the tabs
|
// Log the user out in all the tabs
|
||||||
'Q_LOGOUT': true,
|
'Q_LOGOUT': true,
|
||||||
|
// Tell the user that he has been logged out from outside (probably from another tab)
|
||||||
|
'EV_LOGOUT': true,
|
||||||
|
|
||||||
// When moving to the login or register page from a pad, we need to redirect to that pad at the
|
// When moving to the login or register page from a pad, we need to redirect to that pad at the
|
||||||
// end of the login process. This query set the current href to the sessionStorage.
|
// end of the login process. This query set the current href to the sessionStorage.
|
||||||
@@ -154,6 +156,7 @@ define({
|
|||||||
'Q_CONTACTS_GET_MORE_HISTORY': true,
|
'Q_CONTACTS_GET_MORE_HISTORY': true,
|
||||||
'Q_CONTACTS_SEND_MESSAGE': true,
|
'Q_CONTACTS_SEND_MESSAGE': true,
|
||||||
'Q_CONTACTS_SET_CHANNEL_HEAD': true,
|
'Q_CONTACTS_SET_CHANNEL_HEAD': true,
|
||||||
|
'Q_CONTACTS_CLEAR_OWNED_CHANNEL': true,
|
||||||
|
|
||||||
// Put one or more entries to the localStore which will go in localStorage.
|
// Put one or more entries to the localStore which will go in localStorage.
|
||||||
'EV_LOCALSTORE_PUT': true,
|
'EV_LOCALSTORE_PUT': true,
|
||||||
|
|||||||
@@ -1,865 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/customize/application_config.js',
|
|
||||||
'/api/config'
|
|
||||||
], function ($, Config, ApiConfig) {
|
|
||||||
|
|
||||||
var urlArgs = ApiConfig.requireConf.urlArgs;
|
|
||||||
|
|
||||||
var Messages = {};
|
|
||||||
|
|
||||||
var Bar = {
|
|
||||||
constants: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Id of the div containing the user list. */
|
|
||||||
var USER_LIST_CLS = Bar.constants.userlist = 'cryptpad-user-list';
|
|
||||||
|
|
||||||
/** Id of the div containing the lag info. */
|
|
||||||
var LAG_ELEM_CLS = Bar.constants.lag = 'cryptpad-lag';
|
|
||||||
|
|
||||||
var LIMIT_ELEM_CLS = Bar.constants.lag = 'cryptpad-limit';
|
|
||||||
|
|
||||||
/** The toolbar class which contains the user list, debug link and lag. */
|
|
||||||
var TOOLBAR_CLS = Bar.constants.toolbar = 'cryptpad-toolbar';
|
|
||||||
|
|
||||||
var TOP_CLS = Bar.constants.top = 'cryptpad-toolbar-top';
|
|
||||||
var LEFTSIDE_CLS = Bar.constants.leftside = 'cryptpad-toolbar-leftside';
|
|
||||||
var RIGHTSIDE_CLS = Bar.constants.rightside = 'cryptpad-toolbar-rightside';
|
|
||||||
var HISTORY_CLS = Bar.constants.history = 'cryptpad-toolbar-history';
|
|
||||||
|
|
||||||
var SPINNER_CLS = Bar.constants.spinner = 'cryptpad-spinner';
|
|
||||||
|
|
||||||
var STATE_CLS = Bar.constants.state = 'cryptpad-state';
|
|
||||||
|
|
||||||
var USERNAME_CLS = Bar.constants.username = 'cryptpad-toolbar-username';
|
|
||||||
|
|
||||||
var READONLY_CLS = Bar.constants.readonly = 'cryptpad-readonly';
|
|
||||||
|
|
||||||
var USERBUTTONS_CONTAINER_CLS = Bar.constants.userButtonsContainer = "cryptpad-userbuttons-container";
|
|
||||||
var USERLIST_CLS = Bar.constants.userlist = "cryptpad-dropdown-users";
|
|
||||||
var EDITSHARE_CLS = Bar.constants.editShare = "cryptpad-dropdown-editShare";
|
|
||||||
var VIEWSHARE_CLS = Bar.constants.viewShare = "cryptpad-dropdown-viewShare";
|
|
||||||
var SHARE_CLS = Bar.constants.viewShare = "cryptpad-dropdown-share";
|
|
||||||
var DROPDOWN_CONTAINER_CLS = Bar.constants.dropdownContainer = "cryptpad-dropdown-container";
|
|
||||||
var DROPDOWN_CLS = Bar.constants.dropdown = "cryptpad-dropdown";
|
|
||||||
var TITLE_CLS = Bar.constants.title = "cryptpad-title";
|
|
||||||
var USER_CLS = Bar.constants.userAdmin = "cryptpad-user";
|
|
||||||
var USERBUTTON_CLS = Bar.constants.changeUsername = "cryptpad-change-username";
|
|
||||||
|
|
||||||
var SPINNER_DISAPPEAR_TIME = 3000;
|
|
||||||
|
|
||||||
var uid = function () {
|
|
||||||
return 'cryptpad-uid-' + String(Math.random()).substring(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
var $style;
|
|
||||||
|
|
||||||
var connected = false;
|
|
||||||
var firstConnection = true;
|
|
||||||
var lagErrors = 0;
|
|
||||||
|
|
||||||
var styleToolbar = function ($container, href, version) {
|
|
||||||
href = href || '/customize/toolbar.css' + (version?('?' + version): '');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: href,
|
|
||||||
dataType: 'text',
|
|
||||||
success: function (data) {
|
|
||||||
$container.append($('<style>').text(data));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var createRealtimeToolbar = function ($container, config) {
|
|
||||||
var $toolbar = $('<div>', {
|
|
||||||
'class': TOOLBAR_CLS,
|
|
||||||
id: uid(),
|
|
||||||
})
|
|
||||||
.append($('<div>', {'class': TOP_CLS}))
|
|
||||||
.append($('<div>', {'class': LEFTSIDE_CLS}))
|
|
||||||
.append($('<div>', {'class': RIGHTSIDE_CLS}))
|
|
||||||
.append($('<div>', {'class': HISTORY_CLS}));
|
|
||||||
|
|
||||||
// The 'notitle' class removes the line added for the title with a small screen
|
|
||||||
if (!config || typeof config !== "object") {
|
|
||||||
$toolbar.addClass('notitle');
|
|
||||||
}
|
|
||||||
|
|
||||||
$container.prepend($toolbar);
|
|
||||||
|
|
||||||
if (ApiConfig && ApiConfig.requireConf && ApiConfig.requireConf.urlArgs) {
|
|
||||||
styleToolbar($container, undefined, ApiConfig.requireConf.urlArgs);
|
|
||||||
} else {
|
|
||||||
styleToolbar($container);
|
|
||||||
}
|
|
||||||
return $toolbar;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createSpinner = function ($container, config) {
|
|
||||||
if (config.displayed.indexOf('spinner') !== -1) {
|
|
||||||
var $spin = $('<span>', {'class':SPINNER_CLS});
|
|
||||||
var $spinner = $('<span>', {
|
|
||||||
id: uid(),
|
|
||||||
'class': 'spin fa fa-spinner fa-pulse',
|
|
||||||
}).appendTo($spin).hide();
|
|
||||||
$('<span>', {
|
|
||||||
id: uid(),
|
|
||||||
'class': 'synced fa fa-check',
|
|
||||||
title: Messages.synced
|
|
||||||
}).appendTo($spin);
|
|
||||||
$container.prepend($spin);
|
|
||||||
return $spin[0];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var kickSpinner = function (Cryptpad, realtime, local, spinnerElement) {
|
|
||||||
if (!spinnerElement) { return; }
|
|
||||||
$(spinnerElement).find('.spin').show();
|
|
||||||
$(spinnerElement).find('.synced').hide();
|
|
||||||
var onSynced = function () {
|
|
||||||
if (spinnerElement.timeout) { clearTimeout(spinnerElement.timeout); }
|
|
||||||
spinnerElement.timeout = setTimeout(function () {
|
|
||||||
$(spinnerElement).find('.spin').hide();
|
|
||||||
$(spinnerElement).find('.synced').show();
|
|
||||||
}, local ? 0 : SPINNER_DISAPPEAR_TIME);
|
|
||||||
};
|
|
||||||
if (Cryptpad) {
|
|
||||||
Cryptpad.whenRealtimeSyncs(realtime, onSynced);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onSynced();
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUserButtons = function ($userlistElement, config, readOnly, Cryptpad) {
|
|
||||||
// User list button
|
|
||||||
if (config.displayed.indexOf('userlist') !== -1) {
|
|
||||||
if (!config.userData) {
|
|
||||||
throw new Error("You must provide a `userData` object to display the userlist");
|
|
||||||
}
|
|
||||||
var dropdownConfig = {
|
|
||||||
options: [{
|
|
||||||
tag: 'p',
|
|
||||||
attributes: {'class': USERLIST_CLS},
|
|
||||||
}] // Entries displayed in the menu
|
|
||||||
};
|
|
||||||
var $block = Cryptpad.createDropdown(dropdownConfig);
|
|
||||||
$block.attr('id', 'userButtons');
|
|
||||||
$userlistElement.append($block);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Share button
|
|
||||||
if (config.displayed.indexOf('share') !== -1) {
|
|
||||||
var secret = Cryptpad.find(config, ['share', 'secret']);
|
|
||||||
var channel = Cryptpad.find(config, ['share', 'channel']);
|
|
||||||
if (!secret || !channel) {
|
|
||||||
throw new Error("Unable to display the share button: share.secret and share.channel required");
|
|
||||||
}
|
|
||||||
Cryptpad.getRecentPads(function (err, recent) {
|
|
||||||
var $shareIcon = $('<span>', {'class': 'fa fa-share-alt'});
|
|
||||||
var $span = $('<span>', {'class': 'large'}).append(' ' +Messages.shareButton);
|
|
||||||
var hashes = Cryptpad.getHashes(channel, secret);
|
|
||||||
var options = [];
|
|
||||||
|
|
||||||
// If we have a stronger version in drive, add it and add a redirect button
|
|
||||||
var stronger = recent && Cryptpad.findStronger(null, recent);
|
|
||||||
if (stronger) {
|
|
||||||
var parsed = Cryptpad.parsePadUrl(stronger);
|
|
||||||
hashes.editHash = parsed.hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashes.editHash) {
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {title: Messages.editShareTitle, 'class': 'editShare'},
|
|
||||||
content: '<span class="fa fa-users"></span> ' + Messages.editShare
|
|
||||||
});
|
|
||||||
if (stronger) {
|
|
||||||
// We're in view mode, display the "open editing link" button
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {
|
|
||||||
title: Messages.editOpenTitle,
|
|
||||||
'class': 'editOpen',
|
|
||||||
href: window.location.pathname + '#' + hashes.editHash,
|
|
||||||
target: '_blank'
|
|
||||||
},
|
|
||||||
content: '<span class="fa fa-users"></span> ' + Messages.editOpen
|
|
||||||
});
|
|
||||||
}
|
|
||||||
options.push({tag: 'hr'});
|
|
||||||
}
|
|
||||||
if (hashes.viewHash) {
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {title: Messages.viewShareTitle, 'class': 'viewShare'},
|
|
||||||
content: '<span class="fa fa-eye"></span> ' + Messages.viewShare
|
|
||||||
});
|
|
||||||
if (hashes.editHash && !stronger) {
|
|
||||||
// We're in edit mode, display the "open readonly" button
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {
|
|
||||||
title: Messages.viewOpenTitle,
|
|
||||||
'class': 'viewOpen',
|
|
||||||
href: window.location.pathname + '#' + hashes.viewHash,
|
|
||||||
target: '_blank'
|
|
||||||
},
|
|
||||||
content: '<span class="fa fa-eye"></span> ' + Messages.viewOpen
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hashes.fileHash) {
|
|
||||||
options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {title: Messages.viewShareTitle, 'class': 'fileShare'},
|
|
||||||
content: '<span class="fa fa-eye"></span> ' + Messages.viewShare
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var dropdownConfigShare = {
|
|
||||||
text: $('<div>').append($shareIcon).append($span).html(),
|
|
||||||
options: options
|
|
||||||
};
|
|
||||||
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare);
|
|
||||||
$shareBlock.find('button').attr('id', 'shareButton');
|
|
||||||
$shareBlock.find('.dropdown-bar-content').addClass(SHARE_CLS).addClass(EDITSHARE_CLS).addClass(VIEWSHARE_CLS);
|
|
||||||
$userlistElement.append($shareBlock);
|
|
||||||
|
|
||||||
if (hashes.editHash) {
|
|
||||||
$shareBlock.find('a.editShare').click(function () {
|
|
||||||
var url = window.location.origin + window.location.pathname + '#' + hashes.editHash;
|
|
||||||
var success = Cryptpad.Clipboard.copy(url);
|
|
||||||
if (success) { Cryptpad.log(Messages.shareSuccess); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (hashes.viewHash) {
|
|
||||||
$shareBlock.find('a.viewShare').click(function () {
|
|
||||||
var url = window.location.origin + window.location.pathname + '#' + hashes.viewHash ;
|
|
||||||
var success = Cryptpad.Clipboard.copy(url);
|
|
||||||
if (success) { Cryptpad.log(Messages.shareSuccess); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (hashes.fileHash) {
|
|
||||||
$shareBlock.find('a.fileShare').click(function () {
|
|
||||||
var url = window.location.origin + window.location.pathname + '#' + hashes.fileHash ;
|
|
||||||
var success = Cryptpad.Clipboard.copy(url);
|
|
||||||
if (success) { Cryptpad.log(Messages.shareSuccess); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUserList = function ($container, config, readOnly, Cryptpad) {
|
|
||||||
if (config.displayed.indexOf('userlist') === -1 && config.displayed.indexOf('share') === -1) { return; }
|
|
||||||
var $userlist = $('<div>', {
|
|
||||||
'class': USER_LIST_CLS,
|
|
||||||
id: uid(),
|
|
||||||
});
|
|
||||||
createUserButtons($userlist, config, readOnly, Cryptpad);
|
|
||||||
$container.append($userlist);
|
|
||||||
return $userlist[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
var getOtherUsers = function(myUserName, userList, userData) {
|
|
||||||
var i = 0; // duplicates counter
|
|
||||||
var list = [];
|
|
||||||
var myUid = userData[myUserName] ? userData[myUserName].uid : undefined;
|
|
||||||
var uids = [];
|
|
||||||
userList.forEach(function(user) {
|
|
||||||
if(user !== myUserName) {
|
|
||||||
var data = (userData) ? (userData[user] || null) : null;
|
|
||||||
var userName = (data) ? data.name : null;
|
|
||||||
var userId = (data) ? data.uid : null;
|
|
||||||
if (userName && uids.indexOf(userId) === -1 && (!myUid || userId !== myUid)) {
|
|
||||||
uids.push(userId);
|
|
||||||
list.push(userName);
|
|
||||||
} else { i++; }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
list: list,
|
|
||||||
duplicates: i
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var arrayIntersect = function(a, b) {
|
|
||||||
return $.grep(a, function(i) {
|
|
||||||
return $.inArray(i, b) > -1;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var getViewers = function (n) {
|
|
||||||
if (!n || !parseInt(n) || n === 0) { return ''; }
|
|
||||||
if (n === 1) { return '; + ' + Messages.oneViewer; }
|
|
||||||
return '; + ' + Messages._getKey('viewers', [n]);
|
|
||||||
};
|
|
||||||
|
|
||||||
var checkSynchronizing = function (userList, myUserName, $stateElement) {
|
|
||||||
var meIdx = userList.indexOf(myUserName);
|
|
||||||
if (meIdx === -1) {
|
|
||||||
$stateElement.text(Messages.synchronizing);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$stateElement.text('');
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateUserList = function (config, myUserName, userlistElement, userList, userData, readOnly, $userAdminElement) {
|
|
||||||
// Make sure the elements are displayed
|
|
||||||
var $userButtons = $(userlistElement).find("#userButtons");
|
|
||||||
$userButtons.attr('display', 'inline');
|
|
||||||
|
|
||||||
if (config.displayed.indexOf('userlist') !== -1) {
|
|
||||||
var numberOfUsers = userList.length;
|
|
||||||
|
|
||||||
// If we are using old pads (readonly unavailable), only editing users are in userList.
|
|
||||||
// With new pads, we also have readonly users in userList, so we have to intersect with
|
|
||||||
// the userData to have only the editing users. We can't use userData directly since it
|
|
||||||
// may contain data about users that have already left the channel.
|
|
||||||
userList = readOnly === -1 ? userList : arrayIntersect(userList, Object.keys(userData));
|
|
||||||
|
|
||||||
// Names of editing users
|
|
||||||
var others = getOtherUsers(myUserName, userList, userData);
|
|
||||||
var editUsersNames = others.list;
|
|
||||||
var duplicates = others.duplicates;
|
|
||||||
|
|
||||||
var numberOfEditUsers = userList.length - duplicates;
|
|
||||||
var numberOfViewUsers = numberOfUsers - numberOfEditUsers - duplicates;
|
|
||||||
|
|
||||||
// Number of anonymous editing users
|
|
||||||
var anonymous = numberOfEditUsers - editUsersNames.length;
|
|
||||||
|
|
||||||
// Update the userlist
|
|
||||||
var $usersTitle = $('<h2>').text(Messages.users);
|
|
||||||
var $editUsers = $userButtons.find('.' + USERLIST_CLS);
|
|
||||||
$editUsers.html('').append($usersTitle);
|
|
||||||
|
|
||||||
var $editUsersList = $('<pre>');
|
|
||||||
if (readOnly !== 1) { // Yourself - edit
|
|
||||||
$editUsers.append('<span class="yourself">' + Messages.yourself + '</span>');
|
|
||||||
anonymous--;
|
|
||||||
}
|
|
||||||
// Editors
|
|
||||||
$editUsersList.text(editUsersNames.join('\n')); // .text() to avoid XSS
|
|
||||||
$editUsers.append($editUsersList);
|
|
||||||
if (anonymous > 0) { // Anonymous editors
|
|
||||||
var text = anonymous === 1 ? Messages.anonymousUser : Messages.anonymousUsers;
|
|
||||||
$editUsers.append('<span class="anonymous">' + anonymous + ' ' + text + '</span>');
|
|
||||||
}
|
|
||||||
if (numberOfViewUsers > 0) { // Viewers
|
|
||||||
var viewText = '<span class="viewer">';
|
|
||||||
if (numberOfEditUsers > 0) {
|
|
||||||
$editUsers.append('<br>');
|
|
||||||
viewText += Messages.and + ' ';
|
|
||||||
}
|
|
||||||
var viewerText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
|
|
||||||
viewText += numberOfViewUsers + ' ' + viewerText + '</span>';
|
|
||||||
$editUsers.append(viewText);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Update the buttons
|
|
||||||
var fa_editusers = '<span class="fa fa-users"></span>';
|
|
||||||
var fa_viewusers = '<span class="fa fa-eye"></span>';
|
|
||||||
var viewersText = numberOfViewUsers !== 1 ? Messages.viewers : Messages.viewer;
|
|
||||||
var editorsText = numberOfEditUsers !== 1 ? Messages.editors : Messages.editor;
|
|
||||||
var $span = $('<span>', {'class': 'large'}).html(fa_editusers + ' ' + numberOfEditUsers + ' ' + editorsText + ' ' + fa_viewusers + ' ' + numberOfViewUsers + ' ' + viewersText);
|
|
||||||
var $spansmall = $('<span>', {'class': 'narrow'}).html(fa_editusers + ' ' + numberOfEditUsers + ' ' + fa_viewusers + ' ' + numberOfViewUsers);
|
|
||||||
$userButtons.find('.buttonTitle').html('').append($span).append($spansmall);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.displayed.indexOf('useradmin') !== -1) {
|
|
||||||
// Change username in useradmin dropdown
|
|
||||||
var $userElement = $userAdminElement.find('.' + USERNAME_CLS);
|
|
||||||
$userElement.show();
|
|
||||||
if (readOnly === 1) {
|
|
||||||
$userElement.addClass(READONLY_CLS).text(Messages.readonly);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var name = userData[myUserName] && userData[myUserName].name;
|
|
||||||
if (!name) {
|
|
||||||
name = Messages.anonymous;
|
|
||||||
}
|
|
||||||
$userElement.removeClass(READONLY_CLS).text(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var createLagElement = function () {
|
|
||||||
var $lag = $('<span>', {
|
|
||||||
'class': LAG_ELEM_CLS,
|
|
||||||
id: uid(),
|
|
||||||
});
|
|
||||||
var $a = $('<span>', {'class': 'cryptpad-lag', id: 'newLag'});
|
|
||||||
$('<span>', {'class': 'bar1'}).appendTo($a);
|
|
||||||
$('<span>', {'class': 'bar2'}).appendTo($a);
|
|
||||||
$('<span>', {'class': 'bar3'}).appendTo($a);
|
|
||||||
$('<span>', {'class': 'bar4'}).appendTo($a);
|
|
||||||
return $a[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
var checkLag = function (getLag, lagElement) {
|
|
||||||
var lag;
|
|
||||||
if(typeof getLag === "function") {
|
|
||||||
lag = getLag();
|
|
||||||
}
|
|
||||||
var lagLight = $('<div>', {
|
|
||||||
'class': 'lag'
|
|
||||||
});
|
|
||||||
var title;
|
|
||||||
var $lag = $(lagElement);
|
|
||||||
if (lag) {
|
|
||||||
$lag.attr('class', 'cryptpad-lag');
|
|
||||||
firstConnection = false;
|
|
||||||
title = Messages.lag + ' : ' + lag + ' ms\n';
|
|
||||||
if (lag > 30000) {
|
|
||||||
$lag.addClass('lag0');
|
|
||||||
title = Messages.redLight;
|
|
||||||
} else if (lag > 5000) {
|
|
||||||
$lag.addClass('lag1');
|
|
||||||
title += Messages.orangeLight;
|
|
||||||
} else if (lag > 1000) {
|
|
||||||
$lag.addClass('lag2');
|
|
||||||
title += Messages.orangeLight;
|
|
||||||
} else if (lag > 300) {
|
|
||||||
$lag.addClass('lag3');
|
|
||||||
title += Messages.greenLight;
|
|
||||||
} else {
|
|
||||||
$lag.addClass('lag4');
|
|
||||||
title += Messages.greenLight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!firstConnection) {
|
|
||||||
$lag.attr('class', 'cryptpad-lag');
|
|
||||||
// Display the red light at the 2nd failed attemp to get the lag
|
|
||||||
lagLight.addClass('lag-red');
|
|
||||||
title = Messages.redLight;
|
|
||||||
}
|
|
||||||
if (title) {
|
|
||||||
$lag.attr('title', title);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var createLinkToMain = function ($topContainer) {
|
|
||||||
var $linkContainer = $('<span>', {
|
|
||||||
'class': "cryptpad-link"
|
|
||||||
}).appendTo($topContainer);
|
|
||||||
var $imgTag = $('<img>', {
|
|
||||||
src: "/customize/cryptofist_mini.png?" + urlArgs,
|
|
||||||
alt: "Cryptpad"
|
|
||||||
});
|
|
||||||
|
|
||||||
// We need to override the "a" tag action here because it is inside the iframe!
|
|
||||||
var $aTagSmall = $('<a>', {
|
|
||||||
href: "/",
|
|
||||||
title: Messages.header_logoTitle,
|
|
||||||
'class': "cryptpad-logo"
|
|
||||||
}).append($imgTag);
|
|
||||||
var $span = $('<span>').text('CryptPad');
|
|
||||||
var $aTagBig = $aTagSmall.clone().addClass('large').append($span);
|
|
||||||
$aTagSmall.addClass('narrow');
|
|
||||||
var onClick = function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (e.ctrlKey) {
|
|
||||||
window.open('/');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window.location = "/";
|
|
||||||
};
|
|
||||||
|
|
||||||
var onContext = function (e) { e.stopPropagation(); };
|
|
||||||
|
|
||||||
$aTagBig.click(onClick).contextmenu(onContext);
|
|
||||||
$aTagSmall.click(onClick).contextmenu(onContext);
|
|
||||||
|
|
||||||
$linkContainer.append($aTagSmall).append($aTagBig);
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUserAdmin = function ($topContainer, config, readOnly, lagElement, Cryptpad) {
|
|
||||||
var $lag = $(lagElement);
|
|
||||||
|
|
||||||
var $userContainer = $('<span>', {
|
|
||||||
'class': USER_CLS
|
|
||||||
}).appendTo($topContainer);
|
|
||||||
|
|
||||||
if (config.displayed.indexOf('state') !== -1) {
|
|
||||||
var $state = $('<span>', {
|
|
||||||
'class': STATE_CLS
|
|
||||||
}).text(Messages.synchronizing).appendTo($userContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.displayed.indexOf('lag') !== -1) {
|
|
||||||
$userContainer.append($lag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.displayed.indexOf('limit') !== -1 && Config.enablePinning) {
|
|
||||||
var usage;
|
|
||||||
var $limitIcon = $('<span>', {'class': 'fa fa-exclamation-triangle'});
|
|
||||||
var $limit = $('<span>', {
|
|
||||||
'class': LIMIT_ELEM_CLS,
|
|
||||||
'title': Messages.pinLimitReached
|
|
||||||
}).append($limitIcon).hide().appendTo($userContainer);
|
|
||||||
var todo = function (e, overLimit) {
|
|
||||||
if (e) { return void console.error("Unable to get the pinned usage"); }
|
|
||||||
if (overLimit) {
|
|
||||||
var message = Messages.pinLimitReachedAlert;
|
|
||||||
if (ApiConfig.noSubscriptionButton === true) {
|
|
||||||
message = Messages.pinLimitReachedAlertNoAccounts;
|
|
||||||
}
|
|
||||||
$limit.show().click(function () {
|
|
||||||
Cryptpad.alert(message, null, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Cryptpad.isOverPinLimit(todo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.displayed.indexOf('newpad') !== -1) {
|
|
||||||
var pads_options = [];
|
|
||||||
Config.availablePadTypes.forEach(function (p) {
|
|
||||||
if (p === 'drive') { return; }
|
|
||||||
pads_options.push({
|
|
||||||
tag: 'a',
|
|
||||||
attributes: {
|
|
||||||
'target': '_blank',
|
|
||||||
'href': '/' + p + '/',
|
|
||||||
},
|
|
||||||
content: Messages.type[p]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var $plusIcon = $('<span>', {'class': 'fa fa-plus'});
|
|
||||||
var $newbig = $('<span>', {'class': 'big'}).append(' ' +Messages.newButton);
|
|
||||||
var $newButton = $('<div>').append($plusIcon).append($newbig);
|
|
||||||
var dropdownConfig = {
|
|
||||||
text: $newButton.html(), // Button initial text
|
|
||||||
options: pads_options, // Entries displayed in the menu
|
|
||||||
left: true, // Open to the left of the button
|
|
||||||
};
|
|
||||||
var $newPadBlock = Cryptpad.createDropdown(dropdownConfig);
|
|
||||||
$newPadBlock.find('button').attr('title', Messages.newButtonTitle);
|
|
||||||
$newPadBlock.find('button').attr('id', 'newdoc');
|
|
||||||
$newPadBlock.appendTo($userContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// User dropdown
|
|
||||||
if (config.displayed.indexOf('useradmin') !== -1) {
|
|
||||||
var userMenuCfg = {};
|
|
||||||
if (!config.hideDisplayName) {
|
|
||||||
userMenuCfg = {
|
|
||||||
displayNameCls: USERNAME_CLS,
|
|
||||||
changeNameButtonCls: USERBUTTON_CLS,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (readOnly !== 1) {
|
|
||||||
userMenuCfg.displayName = 1;
|
|
||||||
userMenuCfg.displayChangeName = 1;
|
|
||||||
}
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
|
|
||||||
$userAdmin.attr('id', 'userDropdown');
|
|
||||||
$userContainer.append($userAdmin);
|
|
||||||
|
|
||||||
var $userButton = $userAdmin.find('a.' + USERBUTTON_CLS);
|
|
||||||
var renameAlertOpened;
|
|
||||||
$userButton.click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
Cryptpad.getLastName(function (err, lastName) {
|
|
||||||
if (err) { return void console.error("Cannot get last name", err); }
|
|
||||||
Cryptpad.prompt(Messages.changeNamePrompt, lastName || '', function (newName) {
|
|
||||||
if (newName === null && typeof(lastName) === "string") { return; }
|
|
||||||
if (newName === null) { newName = ''; }
|
|
||||||
Cryptpad.changeDisplayName(newName);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Cryptpad.onDisplayNameChanged(function (newName) {
|
|
||||||
Cryptpad.findCancelButton().click();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $userContainer;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createTitle = function ($container, readOnly, config, Cryptpad) {
|
|
||||||
var $titleContainer = $('<span>', {
|
|
||||||
id: 'toolbarTitle',
|
|
||||||
'class': TITLE_CLS
|
|
||||||
}).appendTo($container);
|
|
||||||
|
|
||||||
if (!config || typeof config !== "object") { return; }
|
|
||||||
|
|
||||||
var callback = config.onRename;
|
|
||||||
var placeholder = config.defaultName;
|
|
||||||
var suggestName = config.suggestName;
|
|
||||||
|
|
||||||
// Buttons
|
|
||||||
var $text = $('<span>', {
|
|
||||||
'class': 'title'
|
|
||||||
}).appendTo($titleContainer);
|
|
||||||
var $pencilIcon = $('<span>', {
|
|
||||||
'class': 'pencilIcon',
|
|
||||||
'title': Messages.clickToEdit
|
|
||||||
});
|
|
||||||
if (readOnly === 1 || typeof(Cryptpad) === "undefined") { return $titleContainer; }
|
|
||||||
var $input = $('<input>', {
|
|
||||||
type: 'text',
|
|
||||||
placeholder: placeholder
|
|
||||||
}).appendTo($titleContainer).hide();
|
|
||||||
if (readOnly !== 1) {
|
|
||||||
$text.attr("title", Messages.clickToEdit);
|
|
||||||
$text.addClass("editable");
|
|
||||||
var $icon = $('<span>', {
|
|
||||||
'class': 'fa fa-pencil readonly',
|
|
||||||
style: 'font-family: FontAwesome;'
|
|
||||||
});
|
|
||||||
$pencilIcon.append($icon).appendTo($titleContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Events
|
|
||||||
$input.on('mousedown', function (e) {
|
|
||||||
if (!$input.is(":focus")) {
|
|
||||||
$input.focus();
|
|
||||||
}
|
|
||||||
e.stopPropagation();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
$input.on('keyup', function (e) {
|
|
||||||
if (e.which === 13 && connected === true) {
|
|
||||||
var name = $input.val().trim();
|
|
||||||
if (name === "") {
|
|
||||||
name = $input.attr('placeholder');
|
|
||||||
}
|
|
||||||
Cryptpad.renamePad(name, function (err, newtitle) {
|
|
||||||
if (err) { return; }
|
|
||||||
$text.text(newtitle);
|
|
||||||
callback(null, newtitle);
|
|
||||||
$input.hide();
|
|
||||||
$text.show();
|
|
||||||
//$pencilIcon.css('display', '');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (e.which === 27) {
|
|
||||||
$input.hide();
|
|
||||||
$text.show();
|
|
||||||
//$pencilIcon.css('display', '');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var displayInput = function () {
|
|
||||||
if (connected === false) { return; }
|
|
||||||
$text.hide();
|
|
||||||
//$pencilIcon.css('display', 'none');
|
|
||||||
var inputVal = suggestName() || "";
|
|
||||||
$input.val(inputVal);
|
|
||||||
$input.show();
|
|
||||||
$input.focus();
|
|
||||||
};
|
|
||||||
$text.on('click', displayInput);
|
|
||||||
$pencilIcon.on('click', displayInput);
|
|
||||||
return $titleContainer;
|
|
||||||
};
|
|
||||||
|
|
||||||
var create = Bar.create = function ($container, myUserName, realtime, getLag, userList, config) {
|
|
||||||
config = config || {};
|
|
||||||
var readOnly = (typeof config.readOnly !== "undefined") ? (config.readOnly ? 1 : 0) : -1;
|
|
||||||
var Cryptpad = config.common;
|
|
||||||
Messages = Cryptpad.Messages;
|
|
||||||
config.displayed = config.displayed || [];
|
|
||||||
|
|
||||||
var toolbar = createRealtimeToolbar($container, config.title);
|
|
||||||
var userListElement = createUserList(toolbar.find('.' + LEFTSIDE_CLS), config, readOnly, Cryptpad);
|
|
||||||
var $titleElement = createTitle(toolbar.find('.' + TOP_CLS), readOnly, config.title, Cryptpad);
|
|
||||||
var $linkElement = createLinkToMain(toolbar.find('.' + TOP_CLS));
|
|
||||||
var lagElement = createLagElement();
|
|
||||||
var $userAdminElement = createUserAdmin(toolbar.find('.' + TOP_CLS), config, readOnly, lagElement, Cryptpad);
|
|
||||||
var spinner = createSpinner($userAdminElement, config);
|
|
||||||
var userData = config.userData;
|
|
||||||
// readOnly = 1 (readOnly enabled), 0 (disabled), -1 (old pad without readOnly mode)
|
|
||||||
var saveElement;
|
|
||||||
var loadElement;
|
|
||||||
var $stateElement = toolbar.find('.' + STATE_CLS);
|
|
||||||
|
|
||||||
if (config.ifrw) {
|
|
||||||
var removeDropdowns = function (e) {
|
|
||||||
$container.find('.cryptpad-dropdown').hide();
|
|
||||||
};
|
|
||||||
var cancelEditTitle = function (e) {
|
|
||||||
// Now we want to apply the title even if we click somewhere else
|
|
||||||
if ($(e.target).parents('.' + TITLE_CLS).length || !$titleElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$titleElement.find('input').is(':visible')) { return; }
|
|
||||||
|
|
||||||
var ev = $.Event("keyup");
|
|
||||||
ev.which = 13;
|
|
||||||
$titleElement.find('input').trigger(ev);
|
|
||||||
|
|
||||||
/*
|
|
||||||
$titleElement.find('input').hide();
|
|
||||||
$titleElement.find('span.title').show();
|
|
||||||
$titleElement.find('span.pencilIcon').css('display', '');
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
$(config.ifrw).on('click', removeDropdowns);
|
|
||||||
$(config.ifrw).on('click', cancelEditTitle);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (config.ifrw.$('iframe').length) {
|
|
||||||
var innerIfrw = config.ifrw.$('iframe').each(function (i, el) {
|
|
||||||
$(el.contentWindow).on('click', removeDropdowns);
|
|
||||||
$(el.contentWindow).on('click', cancelEditTitle);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// empty try catch in case this iframe is problematic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update user list
|
|
||||||
if (userList) {
|
|
||||||
if (userData) {
|
|
||||||
userList.change.push(function (newUserData) {
|
|
||||||
var users = userList.users;
|
|
||||||
if (users.indexOf(myUserName) !== -1) { connected = true; }
|
|
||||||
if (!connected) { return; }
|
|
||||||
checkSynchronizing(users, myUserName, $stateElement);
|
|
||||||
updateUserList(config, myUserName, userListElement, users, userData, readOnly, $userAdminElement);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
userList.change.push(function () {
|
|
||||||
var users = userList.users;
|
|
||||||
if (users.indexOf(myUserName) !== -1) { connected = true; }
|
|
||||||
if (!connected) { return; }
|
|
||||||
checkSynchronizing(users, myUserName, $stateElement);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Display notifications when users are joining/leaving the session
|
|
||||||
var oldUserData;
|
|
||||||
if (typeof Cryptpad !== "undefined" && userList) {
|
|
||||||
var notify = function(type, name, oldname) {
|
|
||||||
// type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
|
|
||||||
if (typeof name === "undefined") { return; }
|
|
||||||
name = (name === "") ? Messages.anonymous : name;
|
|
||||||
switch(type) {
|
|
||||||
case 1:
|
|
||||||
Cryptpad.log(Messages._getKey("notifyJoined", [name]));
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
oldname = (oldname === "") ? Messages.anonymous : oldname;
|
|
||||||
Cryptpad.log(Messages._getKey("notifyRenamed", [oldname, name]));
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
Cryptpad.log(Messages._getKey("notifyLeft", [name]));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log("Invalid type of notification");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var userPresent = function (id, user, data) {
|
|
||||||
if (!(user && user.uid)) {
|
|
||||||
console.log('no uid');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!data) {
|
|
||||||
console.log('no data');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var count = 0;
|
|
||||||
Object.keys(data).forEach(function (k) {
|
|
||||||
if (data[k] && data[k].uid === user.uid) { count++; }
|
|
||||||
});
|
|
||||||
return count;
|
|
||||||
};
|
|
||||||
|
|
||||||
userList.change.push(function (newdata) {
|
|
||||||
// Notify for disconnected users
|
|
||||||
if (typeof oldUserData !== "undefined") {
|
|
||||||
for (var u in oldUserData) {
|
|
||||||
// if a user's uid is still present after having left, don't notify
|
|
||||||
if (userList.users.indexOf(u) === -1) {
|
|
||||||
var temp = JSON.parse(JSON.stringify(oldUserData[u]));
|
|
||||||
delete oldUserData[u];
|
|
||||||
if (userPresent(u, temp, newdata || oldUserData) < 1) {
|
|
||||||
notify(-1, temp.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Update the "oldUserData" object and notify for new users and names changed
|
|
||||||
if (typeof newdata === "undefined") { return; }
|
|
||||||
if (typeof oldUserData === "undefined") {
|
|
||||||
oldUserData = JSON.parse(JSON.stringify(newdata));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (readOnly === 0 && !oldUserData[myUserName]) {
|
|
||||||
oldUserData = JSON.parse(JSON.stringify(newdata));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var k in newdata) {
|
|
||||||
if (k !== myUserName && userList.users.indexOf(k) !== -1) {
|
|
||||||
if (typeof oldUserData[k] === "undefined") {
|
|
||||||
// if the same uid is already present in the userdata, don't notify
|
|
||||||
if (!userPresent(k, newdata[k], oldUserData)) {
|
|
||||||
notify(1, newdata[k].name);
|
|
||||||
}
|
|
||||||
} else if (oldUserData[k].name !== newdata[k].name) {
|
|
||||||
notify(0, newdata[k].name, oldUserData[k].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oldUserData = JSON.parse(JSON.stringify(newdata));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var ks = function (local) {
|
|
||||||
return function () {
|
|
||||||
if (connected) { kickSpinner(Cryptpad, realtime, local, spinner); }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
if (realtime) {
|
|
||||||
realtime.onPatch(ks());
|
|
||||||
realtime.onMessage(ks(true));
|
|
||||||
|
|
||||||
checkLag(getLag, lagElement);
|
|
||||||
setInterval(function () {
|
|
||||||
if (!connected) { return; }
|
|
||||||
checkLag(getLag, lagElement);
|
|
||||||
}, 3000);
|
|
||||||
} else { connected = true; }
|
|
||||||
|
|
||||||
var failed = function () {
|
|
||||||
connected = false;
|
|
||||||
$stateElement.text(Messages.disconnected);
|
|
||||||
checkLag(undefined, lagElement);
|
|
||||||
};
|
|
||||||
|
|
||||||
// On log out, remove permanently the realtime elements of the toolbar
|
|
||||||
Cryptpad.onLogout(function () {
|
|
||||||
failed();
|
|
||||||
$userAdminElement.find('#userDropdown').hide();
|
|
||||||
$(userListElement).hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
failed: failed,
|
|
||||||
reconnecting: function (userId) {
|
|
||||||
myUserName = userId;
|
|
||||||
connected = false;
|
|
||||||
$stateElement.text(Messages.reconnecting);
|
|
||||||
checkLag(getLag, lagElement);
|
|
||||||
},
|
|
||||||
connected: function () {
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return Bar;
|
|
||||||
});
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,12 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/api/config',
|
'/api/config',
|
||||||
], function ($, Config, ApiConfig) {
|
'/common/common-ui-elements.js',
|
||||||
var Messages = {};
|
'/common/common-interface.js',
|
||||||
var Cryptpad;
|
'/common/common-hash.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/common/clipboard.js',
|
||||||
|
], function ($, Config, ApiConfig, UIElements, UI, Hash, Messages, Clipboard) {
|
||||||
var Common;
|
var Common;
|
||||||
|
|
||||||
var Bar = {
|
var Bar = {
|
||||||
@@ -148,6 +151,18 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var avatars = {};
|
var avatars = {};
|
||||||
|
var editingUserName = {
|
||||||
|
state: false
|
||||||
|
};
|
||||||
|
var setDisplayName = function (newName) {
|
||||||
|
Common.setDisplayName(newName, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log("Couldn't set username");
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
var updateUserList = function (toolbar, config) {
|
var updateUserList = function (toolbar, config) {
|
||||||
// Make sure the elements are displayed
|
// Make sure the elements are displayed
|
||||||
var $userButtons = toolbar.userlist;
|
var $userButtons = toolbar.userlist;
|
||||||
@@ -182,6 +197,16 @@ define([
|
|||||||
var numberOfEditUsers = Object.keys(userData).length - duplicates;
|
var numberOfEditUsers = Object.keys(userData).length - duplicates;
|
||||||
var numberOfViewUsers = viewers;
|
var numberOfViewUsers = viewers;
|
||||||
|
|
||||||
|
// If the user was changing his username, do not reste the input, store the current value
|
||||||
|
// and cursor
|
||||||
|
if (editingUserName.state) {
|
||||||
|
var $input = $userlistContent.find('.cp-toolbar-userlist-name-input');
|
||||||
|
editingUserName.value = $input.val();
|
||||||
|
editingUserName.select = [$input[0].selectionStart, $input[0].selectionEnd];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Update the userlist
|
// Update the userlist
|
||||||
var $editUsers = $userlistContent.find('.' + USERLIST_CLS).html('');
|
var $editUsers = $userlistContent.find('.' + USERLIST_CLS).html('');
|
||||||
|
|
||||||
@@ -210,14 +235,63 @@ define([
|
|||||||
var $span = $('<span>', {'class': 'cp-avatar'});
|
var $span = $('<span>', {'class': 'cp-avatar'});
|
||||||
var $rightCol = $('<span>', {'class': 'cp-toolbar-userlist-rightcol'});
|
var $rightCol = $('<span>', {'class': 'cp-toolbar-userlist-rightcol'});
|
||||||
var $nameSpan = $('<span>', {'class': 'cp-toolbar-userlist-name'}).text(name).appendTo($rightCol);
|
var $nameSpan = $('<span>', {'class': 'cp-toolbar-userlist-name'}).text(name).appendTo($rightCol);
|
||||||
var isMe = data.curvePublic === user.curvePublic;
|
var isMe = data.uid === user.uid;
|
||||||
if (Common.isLoggedIn() && data.curvePublic) {
|
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
$span.attr('title', Messages._getKey('userlist_thisIsYou', [
|
$nameSpan.html('');
|
||||||
name
|
var $nameValue = $('<span>', {
|
||||||
]));
|
'class': 'cp-toolbar-userlist-name-value'
|
||||||
$nameSpan.text(name);
|
}).text(name).appendTo($nameSpan);
|
||||||
} else if (!friends[data.curvePublic]) {
|
var $button = $('<button>', {
|
||||||
|
'class': 'fa fa-pencil cp-toolbar-userlist-name-edit',
|
||||||
|
title: Messages.user_rename
|
||||||
|
}).appendTo($nameSpan);
|
||||||
|
$button.hover(function (e) { e.preventDefault(); e.stopPropagation(); });
|
||||||
|
$button.mouseenter(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
window.setTimeout(function () {
|
||||||
|
$button.parents().mouseleave();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var $nameInput = $('<input>', {
|
||||||
|
'class': 'cp-toolbar-userlist-name-input'
|
||||||
|
}).val(name).appendTo($rightCol);
|
||||||
|
$button.click(function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
$nameSpan.hide();
|
||||||
|
$nameInput.show().focus().select();
|
||||||
|
editingUserName.state = true;
|
||||||
|
editingUserName.oldName = $nameInput.val();
|
||||||
|
});
|
||||||
|
$nameInput.click(function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
$nameInput.on('keydown', function (e) {
|
||||||
|
if (e.which === 13 || e.which === 27) {
|
||||||
|
$nameInput.hide();
|
||||||
|
$nameSpan.show();
|
||||||
|
$button.show();
|
||||||
|
editingUserName.state = false;
|
||||||
|
}
|
||||||
|
if (e.which === 13) {
|
||||||
|
var newName = $nameInput.val(); // TODO clean
|
||||||
|
$nameValue.text(newName);
|
||||||
|
setDisplayName(newName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.which === 27) {
|
||||||
|
$nameValue.text(editingUserName.oldName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (editingUserName.state) {
|
||||||
|
$button.click();
|
||||||
|
$nameInput.val(editingUserName.value);
|
||||||
|
$nameInput[0].setSelectionRange(editingUserName.select[0],
|
||||||
|
editingUserName.select[1]);
|
||||||
|
setTimeout(function () { $nameInput.focus(); });
|
||||||
|
}
|
||||||
|
} else if (Common.isLoggedIn() && data.curvePublic && !friends[data.curvePublic]) {
|
||||||
if (pendingFriends.indexOf(data.netfluxId) !== -1) {
|
if (pendingFriends.indexOf(data.netfluxId) !== -1) {
|
||||||
$('<span>', {'class': 'cp-toolbar-userlist-friend'}).text(Messages.userlist_pending)
|
$('<span>', {'class': 'cp-toolbar-userlist-friend'}).text(Messages.userlist_pending)
|
||||||
.appendTo($rightCol);
|
.appendTo($rightCol);
|
||||||
@@ -233,7 +307,6 @@ define([
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (data.profile) {
|
if (data.profile) {
|
||||||
$span.addClass('cp-userlist-clickable');
|
$span.addClass('cp-userlist-clickable');
|
||||||
$span.click(function () {
|
$span.click(function () {
|
||||||
@@ -426,7 +499,7 @@ define([
|
|||||||
options: options,
|
options: options,
|
||||||
feedback: 'SHARE_MENU',
|
feedback: 'SHARE_MENU',
|
||||||
};
|
};
|
||||||
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare);
|
var $shareBlock = UIElements.createDropdown(dropdownConfigShare);
|
||||||
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS).addClass(EDITSHARE_CLS).addClass(VIEWSHARE_CLS);
|
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS).addClass(EDITSHARE_CLS).addClass(VIEWSHARE_CLS);
|
||||||
$shareBlock.addClass('cp-toolbar-share-button');
|
$shareBlock.addClass('cp-toolbar-share-button');
|
||||||
$shareBlock.find('button').attr('title', Messages.shareButton);
|
$shareBlock.find('button').attr('title', Messages.shareButton);
|
||||||
@@ -434,25 +507,25 @@ define([
|
|||||||
if (hashes.editHash) {
|
if (hashes.editHash) {
|
||||||
$shareBlock.find('a.cp-toolbar-share-edit-copy').click(function () {
|
$shareBlock.find('a.cp-toolbar-share-edit-copy').click(function () {
|
||||||
/*Common.storeLinkToClipboard(false, function (err) {
|
/*Common.storeLinkToClipboard(false, function (err) {
|
||||||
if (!err) { Cryptpad.log(Messages.shareSuccess); }
|
if (!err) { UI.log(Messages.shareSuccess); }
|
||||||
});*/
|
});*/
|
||||||
var url = origin + pathname + '#' + hashes.editHash;
|
var url = origin + pathname + '#' + hashes.editHash;
|
||||||
var success = Cryptpad.Clipboard.copy(url);
|
var success = Clipboard.copy(url);
|
||||||
if (success) { Cryptpad.log(Messages.shareSuccess); }
|
if (success) { UI.log(Messages.shareSuccess); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (hashes.viewHash) {
|
if (hashes.viewHash) {
|
||||||
$shareBlock.find('a.cp-toolbar-share-view-copy').click(function () {
|
$shareBlock.find('a.cp-toolbar-share-view-copy').click(function () {
|
||||||
/*Common.storeLinkToClipboard(true, function (err) {
|
/*Common.storeLinkToClipboard(true, function (err) {
|
||||||
if (!err) { Cryptpad.log(Messages.shareSuccess); }
|
if (!err) { UI.log(Messages.shareSuccess); }
|
||||||
});*/
|
});*/
|
||||||
var url = origin + pathname + '#' + hashes.viewHash;
|
var url = origin + pathname + '#' + hashes.viewHash;
|
||||||
var success = Cryptpad.Clipboard.copy(url);
|
var success = Clipboard.copy(url);
|
||||||
if (success) { Cryptpad.log(Messages.shareSuccess); }
|
if (success) { UI.log(Messages.shareSuccess); }
|
||||||
});
|
});
|
||||||
$shareBlock.find('a.cp-toolbar-share-view-embed').click(function () {
|
$shareBlock.find('a.cp-toolbar-share-view-embed').click(function () {
|
||||||
var url = origin + pathname + '#' + hashes.viewHash;
|
var url = origin + pathname + '#' + hashes.viewHash;
|
||||||
var parsed = Cryptpad.parsePadUrl(url);
|
var parsed = Hash.parsePadUrl(url);
|
||||||
url = origin + parsed.getUrl({embed: true, present: true});
|
url = origin + parsed.getUrl({embed: true, present: true});
|
||||||
// Alertify content
|
// Alertify content
|
||||||
var $content = $('<div>');
|
var $content = $('<div>');
|
||||||
@@ -468,12 +541,12 @@ define([
|
|||||||
readonly: 'readonly',
|
readonly: 'readonly',
|
||||||
value: iframeEmbed,
|
value: iframeEmbed,
|
||||||
}).appendTo($tag);
|
}).appendTo($tag);
|
||||||
Cryptpad.alert($content.html(), null, true);
|
UI.alert($content.html(), null, true);
|
||||||
$('#'+iframeId).click(function () {
|
$('#'+iframeId).click(function () {
|
||||||
this.select();
|
this.select();
|
||||||
});
|
});
|
||||||
//var success = Cryptpad.Clipboard.copy(url);
|
//var success = Clipboard.copy(url);
|
||||||
//if (success) { Cryptpad.log(Messages.shareSuccess); }
|
//if (success) { UI.log(Messages.shareSuccess); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,15 +584,15 @@ define([
|
|||||||
options: options,
|
options: options,
|
||||||
feedback: 'FILESHARE_MENU',
|
feedback: 'FILESHARE_MENU',
|
||||||
};
|
};
|
||||||
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare);
|
var $shareBlock = UIElements.createDropdown(dropdownConfigShare);
|
||||||
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS);
|
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS);
|
||||||
$shareBlock.addClass('cp-toolbar-share-button');
|
$shareBlock.addClass('cp-toolbar-share-button');
|
||||||
$shareBlock.find('button').attr('title', Messages.shareButton);
|
$shareBlock.find('button').attr('title', Messages.shareButton);
|
||||||
|
|
||||||
// Add handlers
|
// Add handlers
|
||||||
$shareBlock.find('a.cp-toolbar-share-file-copy').click(function () {
|
$shareBlock.find('a.cp-toolbar-share-file-copy').click(function () {
|
||||||
var success = Cryptpad.Clipboard.copy(url);
|
var success = Clipboard.copy(url);
|
||||||
if (success) { Cryptpad.log(Messages.shareSuccess); }
|
if (success) { UI.log(Messages.shareSuccess); }
|
||||||
});
|
});
|
||||||
$shareBlock.find('a.cp-toolbar-share-file-embed').click(function () {
|
$shareBlock.find('a.cp-toolbar-share-file-embed').click(function () {
|
||||||
var $content = $('<div>');
|
var $content = $('<div>');
|
||||||
@@ -527,11 +600,11 @@ define([
|
|||||||
$('<h3>').text(Messages.fileEmbedTitle).appendTo($content);
|
$('<h3>').text(Messages.fileEmbedTitle).appendTo($content);
|
||||||
var $script = $('<p>').text(Messages.fileEmbedScript).appendTo($content);
|
var $script = $('<p>').text(Messages.fileEmbedScript).appendTo($content);
|
||||||
$('<br>').appendTo($script);
|
$('<br>').appendTo($script);
|
||||||
$script.append(Cryptpad.dialog.selectable(Common.getMediatagScript()));
|
$script.append(UI.dialog.selectable(Common.getMediatagScript()));
|
||||||
var $tag = $('<p>').text(Messages.fileEmbedTag).appendTo($content);
|
var $tag = $('<p>').text(Messages.fileEmbedTag).appendTo($content);
|
||||||
$('<br>').appendTo($tag);
|
$('<br>').appendTo($tag);
|
||||||
$tag.append(Cryptpad.dialog.selectable(Common.getMediatagFromHref(url)));
|
$tag.append(UI.dialog.selectable(Common.getMediatagFromHref(url)));
|
||||||
Cryptpad.alert($content[0], null, true);
|
UI.alert($content[0], null, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
toolbar.$leftside.append($shareBlock);
|
toolbar.$leftside.append($shareBlock);
|
||||||
@@ -568,8 +641,8 @@ define([
|
|||||||
if (config.readOnly === 1) {
|
if (config.readOnly === 1) {
|
||||||
$titleContainer.append($('<span>', {'class': 'cp-toolbar-title-readonly'})
|
$titleContainer.append($('<span>', {'class': 'cp-toolbar-title-readonly'})
|
||||||
.text('('+Messages.readonly+')'));
|
.text('('+Messages.readonly+')'));
|
||||||
|
return $titleContainer;
|
||||||
}
|
}
|
||||||
if (config.readOnly === 1 || typeof(Cryptpad) === "undefined") { return $titleContainer; }
|
|
||||||
var $input = $('<input>', {
|
var $input = $('<input>', {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
placeholder: placeholder
|
placeholder: placeholder
|
||||||
@@ -760,7 +833,7 @@ define([
|
|||||||
key = 'pinLimitReachedAlertNoAccounts';
|
key = 'pinLimitReachedAlertNoAccounts';
|
||||||
}
|
}
|
||||||
$limit.show().click(function () {
|
$limit.show().click(function () {
|
||||||
Cryptpad.alert(Messages._getKey(key, [encodeURIComponent(window.location.hostname)]), null, true);
|
UI.alert(Messages._getKey(key, [encodeURIComponent(window.location.hostname)]), null, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -785,7 +858,7 @@ define([
|
|||||||
'target': '_blank',
|
'target': '_blank',
|
||||||
'href': origin + '/' + p + '/',
|
'href': origin + '/' + p + '/',
|
||||||
},
|
},
|
||||||
content: $('<div>').append(Cryptpad.getIcon(p)).html() + Messages.type[p]
|
content: $('<div>').append(UI.getIcon(p)).html() + Messages.type[p]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var dropdownConfig = {
|
var dropdownConfig = {
|
||||||
@@ -796,7 +869,7 @@ define([
|
|||||||
feedback: /drive/.test(window.location.pathname)?
|
feedback: /drive/.test(window.location.pathname)?
|
||||||
'DRIVE_NEWPAD': 'NEWPAD',
|
'DRIVE_NEWPAD': 'NEWPAD',
|
||||||
};
|
};
|
||||||
var $newPadBlock = Cryptpad.createDropdown(dropdownConfig);
|
var $newPadBlock = UIElements.createDropdown(dropdownConfig);
|
||||||
$newPadBlock.find('button').attr('title', Messages.newButtonTitle);
|
$newPadBlock.find('button').attr('title', Messages.newButtonTitle);
|
||||||
$newPadBlock.find('button').addClass('fa fa-th');
|
$newPadBlock.find('button').addClass('fa fa-th');
|
||||||
return $newPadBlock;
|
return $newPadBlock;
|
||||||
@@ -821,8 +894,11 @@ define([
|
|||||||
userMenuCfg.displayName = 1;
|
userMenuCfg.displayName = 1;
|
||||||
userMenuCfg.displayChangeName = 1;
|
userMenuCfg.displayChangeName = 1;
|
||||||
}
|
}
|
||||||
|
/*if (config.displayed.indexOf('userlist') !== -1) {
|
||||||
|
userMenuCfg.displayChangeName = 0;
|
||||||
|
}*/
|
||||||
Common.createUserAdminMenu(userMenuCfg);
|
Common.createUserAdminMenu(userMenuCfg);
|
||||||
$userAdmin.find('button').attr('title', Messages.userAccountButton);
|
$userAdmin.find('> button').attr('title', Messages.userAccountButton);
|
||||||
|
|
||||||
var $userButton = toolbar.$userNameButton = $userAdmin.find('a.' + USERBUTTON_CLS);
|
var $userButton = toolbar.$userNameButton = $userAdmin.find('a.' + USERBUTTON_CLS);
|
||||||
$userButton.click(function (e) {
|
$userButton.click(function (e) {
|
||||||
@@ -830,18 +906,11 @@ define([
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
var myData = metadataMgr.getMetadata().users[metadataMgr.getNetfluxId()];
|
var myData = metadataMgr.getMetadata().users[metadataMgr.getNetfluxId()];
|
||||||
var lastName = myData.name;
|
var lastName = myData.name;
|
||||||
Cryptpad.prompt(Messages.changeNamePrompt, lastName || '', function (newName) {
|
UI.prompt(Messages.changeNamePrompt, lastName || '', function (newName) {
|
||||||
if (newName === null && typeof(lastName) === "string") { return; }
|
if (newName === null && typeof(lastName) === "string") { return; }
|
||||||
if (newName === null) { newName = ''; }
|
if (newName === null) { newName = ''; }
|
||||||
else { Common.feedback('NAME_CHANGED'); }
|
else { Common.feedback('NAME_CHANGED'); }
|
||||||
Common.setDisplayName(newName, function (err) {
|
setDisplayName(newName);
|
||||||
if (err) {
|
|
||||||
console.log("Couldn't set username");
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//Cryptpad.changeDisplayName(newName, true); Already done?
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -892,7 +961,6 @@ define([
|
|||||||
if (!config.metadataMgr) { return; }
|
if (!config.metadataMgr) { return; }
|
||||||
var metadataMgr = config.metadataMgr;
|
var metadataMgr = config.metadataMgr;
|
||||||
var userNetfluxId = metadataMgr.getNetfluxId();
|
var userNetfluxId = metadataMgr.getNetfluxId();
|
||||||
if (typeof Cryptpad !== "undefined") {
|
|
||||||
var notify = function(type, name, oldname) {
|
var notify = function(type, name, oldname) {
|
||||||
// type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
|
// type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
|
||||||
if (typeof name === "undefined") { return; }
|
if (typeof name === "undefined") { return; }
|
||||||
@@ -900,14 +968,14 @@ define([
|
|||||||
if (Config.disableUserlistNotifications) { return; }
|
if (Config.disableUserlistNotifications) { return; }
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 1:
|
case 1:
|
||||||
Cryptpad.log(Messages._getKey("notifyJoined", [name]));
|
UI.log(Messages._getKey("notifyJoined", [name]));
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
oldname = (!oldname) ? Messages.anonymous : oldname;
|
oldname = (!oldname) ? Messages.anonymous : oldname;
|
||||||
Cryptpad.log(Messages._getKey("notifyRenamed", [oldname, name]));
|
UI.log(Messages._getKey("notifyRenamed", [oldname, name]));
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
Cryptpad.log(Messages._getKey("notifyLeft", [name]));
|
UI.log(Messages._getKey("notifyLeft", [name]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log("Invalid type of notification");
|
console.log("Invalid type of notification");
|
||||||
@@ -975,7 +1043,6 @@ define([
|
|||||||
joined = true;
|
joined = true;
|
||||||
oldUserData = JSON.parse(JSON.stringify(newdata));
|
oldUserData = JSON.parse(JSON.stringify(newdata));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -984,9 +1051,7 @@ define([
|
|||||||
|
|
||||||
Bar.create = function (cfg) {
|
Bar.create = function (cfg) {
|
||||||
var config = cfg || {};
|
var config = cfg || {};
|
||||||
Cryptpad = config.common;
|
|
||||||
Common = config.sfCommon;
|
Common = config.sfCommon;
|
||||||
Messages = Cryptpad.Messages;
|
|
||||||
config.readOnly = (typeof config.readOnly !== "undefined") ? (config.readOnly ? 1 : 0) : -1;
|
config.readOnly = (typeof config.readOnly !== "undefined") ? (config.readOnly ? 1 : 0) : -1;
|
||||||
config.displayed = config.displayed || [];
|
config.displayed = config.displayed || [];
|
||||||
|
|
||||||
@@ -1081,7 +1146,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
// On log out, remove permanently the realtime elements of the toolbar
|
// On log out, remove permanently the realtime elements of the toolbar
|
||||||
Cryptpad.onLogout(function () {
|
Common.onLogout(function () {
|
||||||
failed();
|
failed();
|
||||||
if (toolbar.useradmin) { toolbar.useradmin.hide(); }
|
if (toolbar.useradmin) { toolbar.useradmin.hide(); }
|
||||||
if (toolbar.userlist) { toolbar.userlist.hide(); }
|
if (toolbar.userlist) { toolbar.userlist.hide(); }
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/customize/application_config.js'
|
'/customize/application_config.js',
|
||||||
], function ($, AppConfig) {
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
'/customize/messages.js'
|
||||||
|
], function ($, AppConfig, Util, Hash, Realtime, Constants, Messages) {
|
||||||
var module = {};
|
var module = {};
|
||||||
|
|
||||||
var ROOT = module.ROOT = "root";
|
var ROOT = module.ROOT = "root";
|
||||||
@@ -17,11 +22,10 @@ define([
|
|||||||
module.init = function (files, config) {
|
module.init = function (files, config) {
|
||||||
var exp = {};
|
var exp = {};
|
||||||
var Cryptpad = config.Cryptpad;
|
var Cryptpad = config.Cryptpad;
|
||||||
var Messages = Cryptpad.Messages;
|
var loggedIn = config.loggedIn;
|
||||||
var loggedIn = config.loggedIn || Cryptpad.isLoggedIn();
|
|
||||||
|
|
||||||
var FILES_DATA = module.FILES_DATA = exp.FILES_DATA = Cryptpad.storageKey;
|
var FILES_DATA = module.FILES_DATA = exp.FILES_DATA = Constants.storageKey;
|
||||||
var OLD_FILES_DATA = module.OLD_FILES_DATA = exp.OLD_FILES_DATA = Cryptpad.oldStorageKey;
|
var OLD_FILES_DATA = module.OLD_FILES_DATA = exp.OLD_FILES_DATA = Constants.oldStorageKey;
|
||||||
var NEW_FOLDER_NAME = Messages.fm_newFolder;
|
var NEW_FOLDER_NAME = Messages.fm_newFolder;
|
||||||
var NEW_FILE_NAME = Messages.fm_newFile;
|
var NEW_FILE_NAME = Messages.fm_newFile;
|
||||||
|
|
||||||
@@ -74,7 +78,7 @@ define([
|
|||||||
exp.isReadOnlyFile = function (element) {
|
exp.isReadOnlyFile = function (element) {
|
||||||
if (!isFile(element)) { return false; }
|
if (!isFile(element)) { return false; }
|
||||||
var data = exp.getFileData(element);
|
var data = exp.getFileData(element);
|
||||||
var parsed = Cryptpad.parsePadUrl(data.href);
|
var parsed = Hash.parsePadUrl(data.href);
|
||||||
if (!parsed) { return false; }
|
if (!parsed) { return false; }
|
||||||
var pHash = parsed.hashData;
|
var pHash = parsed.hashData;
|
||||||
if (!pHash || pHash.type !== "pad") { return; }
|
if (!pHash || pHash.type !== "pad") { return; }
|
||||||
@@ -243,7 +247,7 @@ define([
|
|||||||
getHrefArray().forEach(function (c) {
|
getHrefArray().forEach(function (c) {
|
||||||
ret = ret.concat(_getFiles[c]());
|
ret = ret.concat(_getFiles[c]());
|
||||||
});
|
});
|
||||||
return Cryptpad.deduplicateString(ret);
|
return Util.deduplicateString(ret);
|
||||||
};
|
};
|
||||||
_getFiles[ROOT] = function () {
|
_getFiles[ROOT] = function () {
|
||||||
var ret = [];
|
var ret = [];
|
||||||
@@ -294,7 +298,7 @@ define([
|
|||||||
ret = ret.concat(_getFiles[c]());
|
ret = ret.concat(_getFiles[c]());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Cryptpad.deduplicateString(ret);
|
return Util.deduplicateString(ret);
|
||||||
};
|
};
|
||||||
|
|
||||||
var getIdFromHref = exp.getIdFromHref = function (href) {
|
var getIdFromHref = exp.getIdFromHref = function (href) {
|
||||||
@@ -437,13 +441,13 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Search Href
|
// Search Href
|
||||||
var href = Cryptpad.getRelativeHref(value);
|
var href = Hash.getRelativeHref(value);
|
||||||
if (href) {
|
if (href) {
|
||||||
var id = getIdFromHref(href);
|
var id = getIdFromHref(href);
|
||||||
if (id) { res.push(id); }
|
if (id) { res.push(id); }
|
||||||
}
|
}
|
||||||
|
|
||||||
res = Cryptpad.deduplicateString(res);
|
res = Util.deduplicateString(res);
|
||||||
|
|
||||||
var ret = [];
|
var ret = [];
|
||||||
res.forEach(function (l) {
|
res.forEach(function (l) {
|
||||||
@@ -484,16 +488,17 @@ define([
|
|||||||
// FILES DATA
|
// FILES DATA
|
||||||
exp.pushData = function (data, cb) {
|
exp.pushData = function (data, cb) {
|
||||||
// TODO: can only be called from outside atm
|
// TODO: can only be called from outside atm
|
||||||
|
if (!Cryptpad) { return; }
|
||||||
if (typeof cb !== "function") { cb = function () {}; }
|
if (typeof cb !== "function") { cb = function () {}; }
|
||||||
var todo = function () {
|
var todo = function () {
|
||||||
var id = Cryptpad.createRandomInteger();
|
var id = Util.createRandomInteger();
|
||||||
files[FILES_DATA][id] = data;
|
files[FILES_DATA][id] = data;
|
||||||
cb(null, id);
|
cb(null, id);
|
||||||
};
|
};
|
||||||
if (!loggedIn || !AppConfig.enablePinning || config.testMode) {
|
if (!loggedIn || !AppConfig.enablePinning || config.testMode) {
|
||||||
return void todo();
|
return void todo();
|
||||||
}
|
}
|
||||||
Cryptpad.pinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e) {
|
Cryptpad.pinPads([Hash.hrefToHexChannelId(data.href)], function (e) {
|
||||||
if (e) { return void cb(e); }
|
if (e) { return void cb(e); }
|
||||||
todo();
|
todo();
|
||||||
});
|
});
|
||||||
@@ -547,7 +552,7 @@ define([
|
|||||||
}
|
}
|
||||||
// Move to root
|
// Move to root
|
||||||
var newName = isFile(element) ?
|
var newName = isFile(element) ?
|
||||||
getAvailableName(newParent, Cryptpad.createChannelId()) :
|
getAvailableName(newParent, Hash.createChannelId()) :
|
||||||
isInTrashRoot(elementPath) ?
|
isInTrashRoot(elementPath) ?
|
||||||
elementPath[1] : elementPath.pop();
|
elementPath[1] : elementPath.pop();
|
||||||
|
|
||||||
@@ -605,7 +610,7 @@ define([
|
|||||||
if (path && isPathIn(newPath, [ROOT]) || filesList.indexOf(id) === -1) {
|
if (path && isPathIn(newPath, [ROOT]) || filesList.indexOf(id) === -1) {
|
||||||
parentEl = find(newPath || [ROOT]);
|
parentEl = find(newPath || [ROOT]);
|
||||||
if (parentEl) {
|
if (parentEl) {
|
||||||
var newName = getAvailableName(parentEl, Cryptpad.createChannelId());
|
var newName = getAvailableName(parentEl, Hash.createChannelId());
|
||||||
parentEl[newName] = id;
|
parentEl[newName] = id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -852,8 +857,6 @@ define([
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
debug("Migrating file system...");
|
debug("Migrating file system...");
|
||||||
// TODO
|
|
||||||
Cryptpad.feedback('Migrate-oldFilesData', true);
|
|
||||||
files.migrate = 1;
|
files.migrate = 1;
|
||||||
var next = function () {
|
var next = function () {
|
||||||
var oldData = files[OLD_FILES_DATA].slice();
|
var oldData = files[OLD_FILES_DATA].slice();
|
||||||
@@ -865,10 +868,10 @@ define([
|
|||||||
oldData.forEach(function (obj) {
|
oldData.forEach(function (obj) {
|
||||||
if (!obj || !obj.href) { return; }
|
if (!obj || !obj.href) { return; }
|
||||||
var href = obj.href;
|
var href = obj.href;
|
||||||
var id = Cryptpad.createRandomInteger();
|
var id = Util.createRandomInteger();
|
||||||
var paths = findFile(href);
|
var paths = findFile(href);
|
||||||
var data = obj;
|
var data = obj;
|
||||||
var key = Cryptpad.createChannelId();
|
var key = Hash.createChannelId();
|
||||||
if (data) {
|
if (data) {
|
||||||
newData[id] = data;
|
newData[id] = data;
|
||||||
} else {
|
} else {
|
||||||
@@ -901,7 +904,7 @@ define([
|
|||||||
if (exp.rt) {
|
if (exp.rt) {
|
||||||
exp.rt.sync();
|
exp.rt.sync();
|
||||||
// TODO
|
// TODO
|
||||||
Cryptpad.whenRealtimeSyncs(exp.rt, next);
|
Realtime.whenRealtimeSyncs(exp.rt, next);
|
||||||
} else {
|
} else {
|
||||||
window.setTimeout(next, 1000);
|
window.setTimeout(next, 1000);
|
||||||
}
|
}
|
||||||
@@ -943,8 +946,8 @@ define([
|
|||||||
}
|
}
|
||||||
if (typeof element[el] === "string") {
|
if (typeof element[el] === "string") {
|
||||||
// We have an old file (href) which is not in filesData: add it
|
// We have an old file (href) which is not in filesData: add it
|
||||||
var id = Cryptpad.createRandomInteger();
|
var id = Util.createRandomInteger();
|
||||||
var key = Cryptpad.createChannelId();
|
var key = Hash.createChannelId();
|
||||||
files[FILES_DATA][id] = {href: element[el], filename: el};
|
files[FILES_DATA][id] = {href: element[el], filename: el};
|
||||||
element[key] = id;
|
element[key] = id;
|
||||||
delete element[el];
|
delete element[el];
|
||||||
@@ -968,7 +971,7 @@ define([
|
|||||||
if (!$.isArray(obj.path)) { toClean.push(idx); return; }
|
if (!$.isArray(obj.path)) { toClean.push(idx); return; }
|
||||||
if (typeof obj.element === "string") {
|
if (typeof obj.element === "string") {
|
||||||
// We have an old file (href) which is not in filesData: add it
|
// We have an old file (href) which is not in filesData: add it
|
||||||
var id = Cryptpad.createRandomInteger();
|
var id = Util.createRandomInteger();
|
||||||
files[FILES_DATA][id] = {href: obj.element, filename: el};
|
files[FILES_DATA][id] = {href: obj.element, filename: el};
|
||||||
obj.element = id;
|
obj.element = id;
|
||||||
}
|
}
|
||||||
@@ -1002,7 +1005,7 @@ define([
|
|||||||
};
|
};
|
||||||
var fixTemplate = function () {
|
var fixTemplate = function () {
|
||||||
if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; }
|
if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; }
|
||||||
files[TEMPLATE] = Cryptpad.deduplicateString(files[TEMPLATE].slice());
|
files[TEMPLATE] = Util.deduplicateString(files[TEMPLATE].slice());
|
||||||
var us = files[TEMPLATE];
|
var us = files[TEMPLATE];
|
||||||
var rootFiles = getFiles([ROOT]).slice();
|
var rootFiles = getFiles([ROOT]).slice();
|
||||||
var toClean = [];
|
var toClean = [];
|
||||||
@@ -1012,7 +1015,7 @@ define([
|
|||||||
}
|
}
|
||||||
if (typeof el === "string") {
|
if (typeof el === "string") {
|
||||||
// We have an old file (href) which is not in filesData: add it
|
// We have an old file (href) which is not in filesData: add it
|
||||||
var id = Cryptpad.createRandomInteger();
|
var id = Util.createRandomInteger();
|
||||||
files[FILES_DATA][id] = {href: el};
|
files[FILES_DATA][id] = {href: el};
|
||||||
us[idx] = id;
|
us[idx] = id;
|
||||||
}
|
}
|
||||||
@@ -1050,16 +1053,25 @@ define([
|
|||||||
toClean.push(id);
|
toClean.push(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var parsed = Cryptpad.parsePadUrl(el.href);
|
if (/^https*:\/\//.test(el.href)) { el.href = Hash.getRelativeHref(el.href); }
|
||||||
|
if (!el.ctime) { el.ctime = el.atime; }
|
||||||
|
|
||||||
|
var parsed = Hash.parsePadUrl(el.href);
|
||||||
|
if (!el.title) { el.title = Hash.getDefaultName(parsed); }
|
||||||
if (!parsed.hash) {
|
if (!parsed.hash) {
|
||||||
debug("Removing an element in filesData with a invalid href.", el);
|
debug("Removing an element in filesData with a invalid href.", el);
|
||||||
toClean.push(id);
|
toClean.push(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!parsed.type) {
|
||||||
|
debug("Removing an element in filesData with a invalid type.", el);
|
||||||
|
toClean.push(id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ((loggedIn || config.testMode) && rootFiles.indexOf(id) === -1) {
|
if ((loggedIn || config.testMode) && rootFiles.indexOf(id) === -1) {
|
||||||
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el);
|
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el);
|
||||||
var newName = Cryptpad.createChannelId();
|
var newName = Hash.createChannelId();
|
||||||
root[newName] = id;
|
root[newName] = id;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/common/hyperscript.js',
|
'/common/hyperscript.js',
|
||||||
'/contacts/messenger-ui.js',
|
'/contacts/messenger-ui.js',
|
||||||
'/common/sframe-messenger-inner.js',
|
'/common/sframe-messenger-inner.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
@@ -16,35 +17,26 @@ define([
|
|||||||
$,
|
$,
|
||||||
Crypto,
|
Crypto,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
h,
|
h,
|
||||||
UI,
|
MessengerUI,
|
||||||
Messenger
|
Messenger,
|
||||||
|
Messages,
|
||||||
|
UI
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
var APP = {};
|
var APP = {};
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var common;
|
var common;
|
||||||
var sFrameChan;
|
var sFrameChan;
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(Cryptpad.addLoadingScreen));
|
$(waitFor(UI.addLoadingScreen));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
sFrameChan = common.getSframeChannel();
|
sFrameChan = common.getSframeChannel();
|
||||||
sFrameChan.onReady(waitFor());
|
sFrameChan.onReady(waitFor());
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var toolbarElement = h('div#cp-toolbar.cp-toolbar-container');
|
var toolbarElement = h('div#cp-toolbar.cp-toolbar-container');
|
||||||
|
|
||||||
document.body.appendChild(toolbarElement);
|
document.body.appendChild(toolbarElement);
|
||||||
@@ -71,10 +63,8 @@ define([
|
|||||||
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
||||||
var configTb = {
|
var configTb = {
|
||||||
displayed: displayed,
|
displayed: displayed,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: $(toolbarElement),
|
$container: $(toolbarElement),
|
||||||
network: Cryptpad.getNetwork(),
|
|
||||||
pageTitle: Messages.contacts_title,
|
pageTitle: Messages.contacts_title,
|
||||||
metadataMgr: common.getMetadataMgr(),
|
metadataMgr: common.getMetadataMgr(),
|
||||||
};
|
};
|
||||||
@@ -83,17 +73,17 @@ define([
|
|||||||
|
|
||||||
var messenger = Messenger.create(sFrameChan);
|
var messenger = Messenger.create(sFrameChan);
|
||||||
|
|
||||||
UI.create(messenger, $(friendList), $(messaging), common);
|
MessengerUI.create(messenger, $(friendList), $(messaging), common);
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sFrameChan.query('Q_HEY_BUDDY', null, function (err, data) {
|
sFrameChan.query('Q_HEY_BUDDY', null, function (err, data) {
|
||||||
if (!data) { return; }
|
if (!data) { return; }
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
Cryptpad.warn(data.error);
|
UI.warn(data.error);
|
||||||
} else {
|
} else {
|
||||||
Cryptpad.log(data.response);
|
UI.log(data.response);
|
||||||
}
|
}
|
||||||
});*/
|
});*/
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-notifier.js',
|
||||||
'/common/hyperscript.js',
|
'/common/hyperscript.js',
|
||||||
'/bower_components/marked/marked.min.js',
|
'/bower_components/marked/marked.min.js',
|
||||||
'/common/media-tag.js',
|
'/common/media-tag.js',
|
||||||
], function ($, Cryptpad, h, Marked, MediaTag) {
|
], function ($, Cryptpad, Messages, Util, UI, Notifier, h, Marked, MediaTag) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var UI = {};
|
var MessengerUI = {};
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var m = function (md) {
|
var m = function (md) {
|
||||||
var d = h('div.cp-app-contacts-content');
|
var d = h('div.cp-app-contacts-content');
|
||||||
@@ -18,6 +21,14 @@ define([
|
|||||||
// remove potentially malicious elements
|
// remove potentially malicious elements
|
||||||
$d.find('script, iframe, object, applet, video, audio').remove();
|
$d.find('script, iframe, object, applet, video, audio').remove();
|
||||||
|
|
||||||
|
// override link clicking, because we're in an iframe
|
||||||
|
$d.find('a').each(function () {
|
||||||
|
var href = $(this).click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
window.open(href);
|
||||||
|
}).attr('href');
|
||||||
|
});
|
||||||
|
|
||||||
// activate media-tags
|
// activate media-tags
|
||||||
$d.find('media-tag').each(function (i, e) { MediaTag(e); });
|
$d.find('media-tag').each(function (i, e) { MediaTag(e); });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -40,7 +51,7 @@ define([
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.create = function (messenger, $userlist, $messages, common) {
|
MessengerUI.create = function (messenger, $userlist, $messages, common) {
|
||||||
var origin = common.getMetadataMgr().getPrivateData().origin;
|
var origin = common.getMetadataMgr().getPrivateData().origin;
|
||||||
|
|
||||||
var state = window.state = {
|
var state = window.state = {
|
||||||
@@ -163,12 +174,13 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(removeHistory).click(function () {
|
$(removeHistory).click(function () {
|
||||||
Cryptpad.confirm(Messages.contacts_confirmRemoveHistory, function (yes) {
|
UI.confirm(Messages.contacts_confirmRemoveHistory, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
Cryptpad.clearOwnedChannel(data.channel, function (e) {
|
|
||||||
|
messenger.clearOwnedChannel(data.channel, function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
Cryptpad.alert(Messages.contacts_removeHistoryServerError);
|
UI.alert(Messages.contacts_removeHistoryServerError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -355,8 +367,8 @@ define([
|
|||||||
|
|
||||||
$(remove).click(function (e) {
|
$(remove).click(function (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
Cryptpad.confirm(Messages._getKey('contacts_confirmRemove', [
|
UI.confirm(Messages._getKey('contacts_confirmRemove', [
|
||||||
Cryptpad.fixHTML(data.displayName)
|
Util.fixHTML(data.displayName)
|
||||||
]), function (yes) {
|
]), function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
removeFriend(curvePublic, function (e) {
|
removeFriend(curvePublic, function (e) {
|
||||||
@@ -389,7 +401,7 @@ define([
|
|||||||
|
|
||||||
var initializing = true;
|
var initializing = true;
|
||||||
messenger.on('message', function (message) {
|
messenger.on('message', function (message) {
|
||||||
if (!initializing) { Cryptpad.notify(); }
|
if (!initializing) { Notifier.notify(); }
|
||||||
var curvePublic = message.curve;
|
var curvePublic = message.curve;
|
||||||
|
|
||||||
var name = displayNames[curvePublic];
|
var name = displayNames[curvePublic];
|
||||||
@@ -514,7 +526,7 @@ define([
|
|||||||
count--;
|
count--;
|
||||||
if (count === 0) {
|
if (count === 0) {
|
||||||
initializing = false;
|
initializing = false;
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ready();
|
ready();
|
||||||
@@ -524,5 +536,5 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return UI;
|
return MessengerUI;
|
||||||
});
|
});
|
||||||
|
|||||||
31
www/debug/app-debug.less
Normal file
31
www/debug/app-debug.less
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
@import (once) "../../customize/src/less2/include/browser.less";
|
||||||
|
@import (once) "../../customize/src/less2/include/toolbar.less";
|
||||||
|
@import (once) "../../customize/src/less2/include/markdown.less";
|
||||||
|
@import (once) '../../customize/src/less2/include/fileupload.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/alertify.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/tools.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/tokenfield.less';
|
||||||
|
|
||||||
|
.toolbar_main();
|
||||||
|
.fileupload_main();
|
||||||
|
.alertify_main();
|
||||||
|
.tokenfield_main();
|
||||||
|
|
||||||
|
// body
|
||||||
|
&.cp-app-debug {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
#cp-app-debug {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
#cp-app-debug-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
52
www/debug/colors.js
Normal file
52
www/debug/colors.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
define(function () {
|
||||||
|
var padZero = function (str, len) {
|
||||||
|
len = len || 2;
|
||||||
|
var zeros = new Array(len).join('0');
|
||||||
|
return (zeros + str).slice(-len);
|
||||||
|
};
|
||||||
|
var invertColor = function (hex) {
|
||||||
|
if (hex.indexOf('#') === 0) {
|
||||||
|
hex = hex.slice(1);
|
||||||
|
}
|
||||||
|
// convert 3-digit hex to 6-digits.
|
||||||
|
if (hex.length === 3) {
|
||||||
|
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||||
|
}
|
||||||
|
if (hex.length !== 6) {
|
||||||
|
console.error(hex);
|
||||||
|
throw new Error('Invalid HEX color.');
|
||||||
|
}
|
||||||
|
// invert color components
|
||||||
|
var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16),
|
||||||
|
g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16),
|
||||||
|
b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16);
|
||||||
|
// pad each with zeros and return
|
||||||
|
return '#' + padZero(r) + padZero(g) + padZero(b);
|
||||||
|
};
|
||||||
|
var rgb2hex = function (rgb) {
|
||||||
|
if (rgb.indexOf('#') === 0) { return rgb; }
|
||||||
|
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
||||||
|
var hex = function (x) {
|
||||||
|
return ("0" + parseInt(x).toString(16)).slice(-2);
|
||||||
|
};
|
||||||
|
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
|
||||||
|
};
|
||||||
|
var hex2rgba = function (hex, opacity) {
|
||||||
|
if (hex.indexOf('#') === 0) {
|
||||||
|
hex = hex.slice(1);
|
||||||
|
}
|
||||||
|
if (hex.length === 3) {
|
||||||
|
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||||
|
}
|
||||||
|
if (!opacity) { opacity = 1; }
|
||||||
|
var r = parseInt(hex.slice(0,2), 16);
|
||||||
|
var g = parseInt(hex.slice(2,4), 16);
|
||||||
|
var b = parseInt(hex.slice(4,6), 16);
|
||||||
|
return 'rgba('+r+', '+g+', '+b+', '+opacity+')';
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
invert: invertColor,
|
||||||
|
rgb2hex: rgb2hex,
|
||||||
|
hex2rgba: hex2rgba
|
||||||
|
};
|
||||||
|
});
|
||||||
38
www/debug/index.html
Normal file
38
www/debug/index.html
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CryptPad</title>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="referrer" content="no-referrer" />
|
||||||
|
<script async data-bootload="main.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
#sbox-iframe {
|
||||||
|
position:fixed;
|
||||||
|
top:0px;
|
||||||
|
left:0px;
|
||||||
|
bottom:0px;
|
||||||
|
right:0px;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
border:none;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
#sbox-filePicker-iframe {
|
||||||
|
position: fixed;
|
||||||
|
top:0; left:0;
|
||||||
|
bottom:0; right:0;
|
||||||
|
width:100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="sbox-iframe">
|
||||||
19
www/debug/inner.html
Normal file
19
www/debug/inner.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="cp-app-noscroll">
|
||||||
|
<head>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<script async data-bootload="/debug/inner.js" data-main="/common/sframe-boot.js?ver=1.6" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
<style>
|
||||||
|
.loading-hidden { display: none; }
|
||||||
|
#editor1 { display: none; }
|
||||||
|
.html2canvas-container { width: 3000px !important; height: 3000px !important; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="cp-app-debug">
|
||||||
|
<div id="cp-toolbar" class="cp-toolbar-container"></div>
|
||||||
|
<div id="cp-app-debug">
|
||||||
|
<div id="cp-app-debug-content"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
179
www/debug/inner.js
Normal file
179
www/debug/inner.js
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
define([
|
||||||
|
'jquery',
|
||||||
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
|
'/bower_components/textpatcher/TextPatcher.js',
|
||||||
|
'/common/toolbar3.js',
|
||||||
|
'json.sortify',
|
||||||
|
'/bower_components/chainpad-json-validator/json-ot.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/bower_components/nthen/index.js',
|
||||||
|
'/common/sframe-common.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/api/config',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/customize/application_config.js',
|
||||||
|
|
||||||
|
'/bower_components/secure-fabric.js/dist/fabric.min.js',
|
||||||
|
|
||||||
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
|
'less!/customize/src/less2/main.less',
|
||||||
|
], function (
|
||||||
|
$,
|
||||||
|
Crypto,
|
||||||
|
TextPatcher,
|
||||||
|
Toolbar,
|
||||||
|
JSONSortify,
|
||||||
|
JsonOT,
|
||||||
|
Util,
|
||||||
|
nThen,
|
||||||
|
SFCommon,
|
||||||
|
UI,
|
||||||
|
ApiConfig,
|
||||||
|
CommonRealtime,
|
||||||
|
Messages,
|
||||||
|
AppConfig)
|
||||||
|
{
|
||||||
|
var APP = window.APP = {
|
||||||
|
$: $,
|
||||||
|
AppConfig: AppConfig,
|
||||||
|
SFCommon: SFCommon,
|
||||||
|
Crypto: Crypto,
|
||||||
|
ApiConfig: ApiConfig
|
||||||
|
};
|
||||||
|
|
||||||
|
var toolbar;
|
||||||
|
var common;
|
||||||
|
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
$(waitFor(function () {
|
||||||
|
UI.addLoadingScreen();
|
||||||
|
}));
|
||||||
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
|
}).nThen(function (/*waitFor*/) {
|
||||||
|
var initializing = true;
|
||||||
|
var $bar = $('#cp-toolbar');
|
||||||
|
var Title;
|
||||||
|
var cpNfInner;
|
||||||
|
var metadataMgr;
|
||||||
|
var readOnly = true;
|
||||||
|
|
||||||
|
var config = APP.config = {
|
||||||
|
readOnly: readOnly,
|
||||||
|
transformFunction: JsonOT.validate,
|
||||||
|
// cryptpad debug logging (default is 1)
|
||||||
|
// logLevel: 0,
|
||||||
|
validateContent: function (content) {
|
||||||
|
try {
|
||||||
|
JSON.parse(content);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Failed to parse, rejecting patch");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var history = false;
|
||||||
|
|
||||||
|
var setHistory = function (bool, update) {
|
||||||
|
history = bool;
|
||||||
|
if (!bool && update) { config.onRemote(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
var displayDoc = function (doc) {
|
||||||
|
$('#cp-app-debug-content').text(JSON.stringify(doc, 0, 2));
|
||||||
|
console.log(doc);
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onLocal = function () { };
|
||||||
|
|
||||||
|
config.onInit = function (info) {
|
||||||
|
Title = common.createTitle({});
|
||||||
|
|
||||||
|
var configTb = {
|
||||||
|
displayed: ['title', 'useradmin', 'spinner', 'share', 'userlist', 'newpad', 'limit'],
|
||||||
|
title: Title.getTitleConfig(),
|
||||||
|
metadataMgr: metadataMgr,
|
||||||
|
readOnly: 1,
|
||||||
|
realtime: info.realtime,
|
||||||
|
sfCommon: common,
|
||||||
|
$container: $bar,
|
||||||
|
$contentContainer: $('#cp-app-debug')
|
||||||
|
};
|
||||||
|
toolbar = APP.toolbar = Toolbar.create(configTb);
|
||||||
|
Title.setToolbar(toolbar);
|
||||||
|
|
||||||
|
/* add a history button */
|
||||||
|
var histConfig = {
|
||||||
|
onLocal: config.onLocal,
|
||||||
|
onRemote: config.onRemote,
|
||||||
|
setHistory: setHistory,
|
||||||
|
applyVal: function (val) {
|
||||||
|
displayDoc(JSON.parse(val) || {});
|
||||||
|
},
|
||||||
|
$toolbar: $bar,
|
||||||
|
debug: true
|
||||||
|
};
|
||||||
|
var $hist = common.createButton('history', true, {histConfig: histConfig});
|
||||||
|
$hist.addClass('cp-hidden-if-readonly');
|
||||||
|
toolbar.$rightside.append($hist);
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onReady = function (info) {
|
||||||
|
if (APP.realtime !== info.realtime) {
|
||||||
|
var realtime = APP.realtime = info.realtime;
|
||||||
|
APP.patchText = TextPatcher.create({
|
||||||
|
realtime: realtime,
|
||||||
|
//logging: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var userDoc = APP.realtime.getUserDoc();
|
||||||
|
if (userDoc !== "") {
|
||||||
|
var hjson = JSON.parse(userDoc);
|
||||||
|
|
||||||
|
if (Array.isArray(hjson)) {
|
||||||
|
metadataMgr.updateMetadata(hjson[3]);
|
||||||
|
} else if (hjson && hjson.metadata) {
|
||||||
|
metadataMgr.updateMetadata(hjson.metadata);
|
||||||
|
}
|
||||||
|
displayDoc(hjson);
|
||||||
|
}
|
||||||
|
|
||||||
|
initializing = false;
|
||||||
|
UI.removeLoadingScreen();
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onRemote = function () {
|
||||||
|
if (initializing) { return; }
|
||||||
|
if (history) { return; }
|
||||||
|
var userDoc = APP.realtime.getUserDoc();
|
||||||
|
|
||||||
|
var json = JSON.parse(userDoc);
|
||||||
|
if (Array.isArray(json)) {
|
||||||
|
metadataMgr.updateMetadata(json[3]);
|
||||||
|
} else if (json && json.metadata) {
|
||||||
|
metadataMgr.updateMetadata(json.metadata);
|
||||||
|
}
|
||||||
|
displayDoc(json);
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onAbort = function () {
|
||||||
|
console.log('onAbort');
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onConnectionChange = function (info) {
|
||||||
|
console.log('onConnectionChange', info.state);
|
||||||
|
};
|
||||||
|
|
||||||
|
cpNfInner = APP.cpNfInner = common.startRealtime(config);
|
||||||
|
metadataMgr = APP.metadataMgr = cpNfInner.metadataMgr;
|
||||||
|
|
||||||
|
cpNfInner.onInfiniteSpinner(function () {
|
||||||
|
console.error('infinite spinner');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
58
www/debug/main.js
Normal file
58
www/debug/main.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Load #1, load as little as possible because we are in a race to get the loading screen up.
|
||||||
|
define([
|
||||||
|
'/bower_components/nthen/index.js',
|
||||||
|
'/api/config',
|
||||||
|
'jquery',
|
||||||
|
'/common/requireconfig.js',
|
||||||
|
'/common/sframe-common-outer.js',
|
||||||
|
'/common/cryptpad-common.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
], function (nThen, ApiConfig, $, RequireConfig, SFCommonO,
|
||||||
|
Cryptpad, Util, Hash, Realtime, Constants, UI) {
|
||||||
|
|
||||||
|
window.Cryptpad = {
|
||||||
|
Common: Cryptpad,
|
||||||
|
Util: Util,
|
||||||
|
Hash: Hash,
|
||||||
|
Realtime: Realtime,
|
||||||
|
Constants: Constants,
|
||||||
|
UI: UI
|
||||||
|
};
|
||||||
|
|
||||||
|
var requireConfig = RequireConfig();
|
||||||
|
|
||||||
|
// Loaded in load #2
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
$(waitFor());
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
var req = {
|
||||||
|
cfg: requireConfig,
|
||||||
|
req: [ '/common/loading.js' ],
|
||||||
|
pfx: window.location.origin
|
||||||
|
};
|
||||||
|
window.rc = requireConfig;
|
||||||
|
window.apiconf = ApiConfig;
|
||||||
|
$('#sbox-iframe').attr('src',
|
||||||
|
ApiConfig.httpSafeOrigin + '/debug/inner.html?' + requireConfig.urlArgs +
|
||||||
|
'#' + encodeURIComponent(JSON.stringify(req)));
|
||||||
|
|
||||||
|
// This is a cheap trick to avoid loading sframe-channel in parallel with the
|
||||||
|
// loading screen setup.
|
||||||
|
var done = waitFor();
|
||||||
|
var onMsg = function (msg) {
|
||||||
|
var data = JSON.parse(msg.data);
|
||||||
|
if (data.q !== 'READY') { return; }
|
||||||
|
window.removeEventListener('message', onMsg);
|
||||||
|
var _done = done;
|
||||||
|
done = function () { };
|
||||||
|
_done();
|
||||||
|
};
|
||||||
|
window.addEventListener('message', onMsg);
|
||||||
|
}).nThen(function (/*waitFor*/) {
|
||||||
|
SFCommonO.start();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,8 +2,11 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'json.sortify',
|
'json.sortify',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-ui-elements.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
'/common/cryptget.js',
|
'/common/cryptget.js',
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
@@ -11,6 +14,7 @@ define([
|
|||||||
'/common/userObject.js',
|
'/common/userObject.js',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/common/sframe-chainpad-listmap.js',
|
'/common/sframe-chainpad-listmap.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
@@ -19,21 +23,22 @@ define([
|
|||||||
$,
|
$,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
JSONSortify,
|
JSONSortify,
|
||||||
Cryptpad,
|
|
||||||
Util,
|
Util,
|
||||||
|
Hash,
|
||||||
|
UIElements,
|
||||||
|
UI,
|
||||||
|
Constants,
|
||||||
Cryptget,
|
Cryptget,
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
CommonRealtime,
|
CommonRealtime,
|
||||||
FO,
|
FO,
|
||||||
AppConfig,
|
AppConfig,
|
||||||
Listmap)
|
Listmap,
|
||||||
|
Messages)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var APP = window.APP = {
|
var APP = window.APP = {
|
||||||
editable: false,
|
editable: false,
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
mobile: function () { return $('body').width() <= 600; } // Menu and content area are not inline-block anymore for mobiles
|
mobile: function () { return $('body').width() <= 600; } // Menu and content area are not inline-block anymore for mobiles
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,17 +46,13 @@ define([
|
|||||||
return JSONSortify(obj);
|
return JSONSortify(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var E_OVER_LIMIT = 'E_OVER_LIMIT';
|
var E_OVER_LIMIT = 'E_OVER_LIMIT';
|
||||||
|
|
||||||
var SEARCH = "search";
|
var SEARCH = "search";
|
||||||
var SEARCH_NAME = Messages.fm_searchName;
|
var SEARCH_NAME = Messages.fm_searchName;
|
||||||
var ROOT = "root";
|
var ROOT = "root";
|
||||||
var ROOT_NAME = Messages.fm_rootName;
|
var ROOT_NAME = Messages.fm_rootName;
|
||||||
var FILES_DATA = Cryptpad.storageKey;
|
var FILES_DATA = Constants.storageKey;
|
||||||
var FILES_DATA_NAME = Messages.fm_filesDataName;
|
var FILES_DATA_NAME = Messages.fm_filesDataName;
|
||||||
var TEMPLATE = "template";
|
var TEMPLATE = "template";
|
||||||
var TEMPLATE_NAME = Messages.fm_templateName;
|
var TEMPLATE_NAME = Messages.fm_templateName;
|
||||||
@@ -74,7 +75,7 @@ define([
|
|||||||
var logError = config.logError = function () {
|
var logError = config.logError = function () {
|
||||||
console.error.apply(console, arguments);
|
console.error.apply(console, arguments);
|
||||||
};
|
};
|
||||||
var log = config.log = Cryptpad.log;
|
var log = config.log = UI.log;
|
||||||
|
|
||||||
var localStore = window.cryptpadStore;
|
var localStore = window.cryptpadStore;
|
||||||
APP.store = {};
|
APP.store = {};
|
||||||
@@ -191,13 +192,11 @@ define([
|
|||||||
var user = metadataMgr.getUserData();
|
var user = metadataMgr.getUserData();
|
||||||
var isOwnDrive = function () {
|
var isOwnDrive = function () {
|
||||||
return true; // TODO
|
return true; // TODO
|
||||||
//return Cryptpad.getUserHash() === APP.hash || localStorage.FS_hash === APP.hash;
|
|
||||||
};
|
};
|
||||||
var isWorkgroup = function () {
|
var isWorkgroup = function () {
|
||||||
return files.workgroup === 1;
|
return files.workgroup === 1;
|
||||||
};
|
};
|
||||||
config.workgroup = isWorkgroup();
|
config.workgroup = isWorkgroup();
|
||||||
config.Cryptpad = Cryptpad;
|
|
||||||
config.loggedIn = APP.loggedIn;
|
config.loggedIn = APP.loggedIn;
|
||||||
|
|
||||||
APP.origin = priv.origin;
|
APP.origin = priv.origin;
|
||||||
@@ -253,7 +252,7 @@ define([
|
|||||||
currentPath = [FILES_DATA];
|
currentPath = [FILES_DATA];
|
||||||
$tree.hide();
|
$tree.hide();
|
||||||
if (Object.keys(files.root).length && !proxy.anonymousAlert) {
|
if (Object.keys(files.root).length && !proxy.anonymousAlert) {
|
||||||
Cryptpad.alert(Messages.fm_alert_anonymous, null, true);
|
UI.alert(Messages.fm_alert_anonymous, null, true);
|
||||||
proxy.anonymousAlert = true;
|
proxy.anonymousAlert = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,10 +414,6 @@ define([
|
|||||||
var ev = {};
|
var ev = {};
|
||||||
if (e.ctrlKey) { ev.ctrlKey = true; }
|
if (e.ctrlKey) { ev.ctrlKey = true; }
|
||||||
if (e.shiftKey) { ev.shiftKey = true; }
|
if (e.shiftKey) { ev.shiftKey = true; }
|
||||||
var click = function (el) {
|
|
||||||
if (!el) { return; }
|
|
||||||
APP.onElementClick(ev, $(el));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Enter
|
// Enter
|
||||||
if (e.which === 13) {
|
if (e.which === 13) {
|
||||||
@@ -440,6 +435,11 @@ define([
|
|||||||
if ([37, 38, 39, 40].indexOf(e.which) === -1) { return; }
|
if ([37, 38, 39, 40].indexOf(e.which) === -1) { return; }
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
var click = function (el) {
|
||||||
|
if (!el) { return; }
|
||||||
|
APP.onElementClick(ev, $(el));
|
||||||
|
};
|
||||||
|
|
||||||
var $selection = $content.find('.cp-app-drive-element.cp-app-drive-element-selected');
|
var $selection = $content.find('.cp-app-drive-element.cp-app-drive-element-selected');
|
||||||
if ($selection.length === 0) { return void click($elements.first()[0]); }
|
if ($selection.length === 0) { return void click($elements.first()[0]); }
|
||||||
|
|
||||||
@@ -577,6 +577,7 @@ define([
|
|||||||
$input.on('keydown', function (e) { e.stopPropagation(); });
|
$input.on('keydown', function (e) { e.stopPropagation(); });
|
||||||
|
|
||||||
$input.on('keyup', function (e) {
|
$input.on('keyup', function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
if (e.which === 13) {
|
if (e.which === 13) {
|
||||||
removeInput(true);
|
removeInput(true);
|
||||||
filesOp.rename(path, $input.val(), refresh);
|
filesOp.rename(path, $input.val(), refresh);
|
||||||
@@ -585,7 +586,7 @@ define([
|
|||||||
if (e.which === 27) {
|
if (e.which === 27) {
|
||||||
removeInput(true);
|
removeInput(true);
|
||||||
}
|
}
|
||||||
});
|
}).on('keypress', function (e) { e.stopPropagation(); });
|
||||||
//$element.parent().append($input);
|
//$element.parent().append($input);
|
||||||
$name.after($input);
|
$name.after($input);
|
||||||
$input.focus();
|
$input.focus();
|
||||||
@@ -1142,7 +1143,7 @@ define([
|
|||||||
var data = filesOp.getFileData(element);
|
var data = filesOp.getFileData(element);
|
||||||
if (!data) { return void logError("No data for the file", element); }
|
if (!data) { return void logError("No data for the file", element); }
|
||||||
|
|
||||||
var hrefData = Cryptpad.parsePadUrl(data.href);
|
var hrefData = Hash.parsePadUrl(data.href);
|
||||||
if (hrefData.type) {
|
if (hrefData.type) {
|
||||||
$span.addClass('cp-border-color-'+hrefData.type);
|
$span.addClass('cp-border-color-'+hrefData.type);
|
||||||
}
|
}
|
||||||
@@ -1209,9 +1210,9 @@ define([
|
|||||||
// This is duplicated in cryptpad-common, it should be unified
|
// This is duplicated in cryptpad-common, it should be unified
|
||||||
var getFileIcon = function (id) {
|
var getFileIcon = function (id) {
|
||||||
var data = filesOp.getFileData(id);
|
var data = filesOp.getFileData(id);
|
||||||
return Cryptpad.getFileIcon(data);
|
return UI.getFileIcon(data);
|
||||||
};
|
};
|
||||||
var getIcon = Cryptpad.getIcon;
|
var getIcon = UI.getIcon;
|
||||||
|
|
||||||
// Create the "li" element corresponding to the file/folder located in "path"
|
// Create the "li" element corresponding to the file/folder located in "path"
|
||||||
var createElement = function (path, elPath, root, isFolder) {
|
var createElement = function (path, elPath, root, isFolder) {
|
||||||
@@ -1440,7 +1441,7 @@ define([
|
|||||||
$button.addClass('cp-app-drive-toolbar-emptytrash');
|
$button.addClass('cp-app-drive-toolbar-emptytrash');
|
||||||
$button.attr('title', Messages.fc_empty);
|
$button.attr('title', Messages.fc_empty);
|
||||||
$button.click(function () {
|
$button.click(function () {
|
||||||
Cryptpad.confirm(Messages.fm_emptyTrashDialog, function(res) {
|
UI.confirm(Messages.fm_emptyTrashDialog, function(res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.emptyTrash(refresh);
|
filesOp.emptyTrash(refresh);
|
||||||
});
|
});
|
||||||
@@ -1455,7 +1456,7 @@ define([
|
|||||||
if (type === 'contacts') { return; }
|
if (type === 'contacts') { return; }
|
||||||
if (type === 'todo') { return; }
|
if (type === 'todo') { return; }
|
||||||
if (type === 'file') { return; }
|
if (type === 'file') { return; }
|
||||||
if (!Cryptpad.isLoggedIn() && AppConfig.registeredOnlyTypes &&
|
if (!APP.loggedIn && AppConfig.registeredOnlyTypes &&
|
||||||
AppConfig.registeredOnlyTypes.indexOf(type) !== -1) {
|
AppConfig.registeredOnlyTypes.indexOf(type) !== -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1469,9 +1470,9 @@ define([
|
|||||||
var onCreated = function (err, info) {
|
var onCreated = function (err, info) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err === E_OVER_LIMIT) {
|
if (err === E_OVER_LIMIT) {
|
||||||
return void Cryptpad.alert(Messages.pinLimitDrive, null, true);
|
return void UI.alert(Messages.pinLimitDrive, null, true);
|
||||||
}
|
}
|
||||||
return void Cryptpad.alert(Messages.fm_error_cantPin);
|
return void UI.alert(Messages.fm_error_cantPin);
|
||||||
}
|
}
|
||||||
APP.newFolder = info.newPath;
|
APP.newFolder = info.newPath;
|
||||||
refresh();
|
refresh();
|
||||||
@@ -1500,7 +1501,7 @@ define([
|
|||||||
.click(function () {
|
.click(function () {
|
||||||
var type = $(this).attr('data-type') || 'pad';
|
var type = $(this).attr('data-type') || 'pad';
|
||||||
var path = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
|
var path = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
|
||||||
common.sessionStorage.put(Cryptpad.newPadPathKey, path, function () {
|
common.sessionStorage.put(Constants.newPadPathKey, path, function () {
|
||||||
common.openURL('/' + type + '/');
|
common.openURL('/' + type + '/');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1547,7 +1548,7 @@ define([
|
|||||||
options: options,
|
options: options,
|
||||||
feedback: 'DRIVE_NEWPAD_LOCALFOLDER',
|
feedback: 'DRIVE_NEWPAD_LOCALFOLDER',
|
||||||
};
|
};
|
||||||
var $block = Cryptpad.createDropdown(dropdownConfig);
|
var $block = UIElements.createDropdown(dropdownConfig);
|
||||||
|
|
||||||
// Custom style:
|
// Custom style:
|
||||||
$block.find('button').addClass('cp-app-drive-toolbar-new');
|
$block.find('button').addClass('cp-app-drive-toolbar-new');
|
||||||
@@ -1701,7 +1702,7 @@ define([
|
|||||||
var data = filesOp.getFileData(id);
|
var data = filesOp.getFileData(id);
|
||||||
if (!data) { return ''; }
|
if (!data) { return ''; }
|
||||||
if (prop === 'type') {
|
if (prop === 'type') {
|
||||||
var hrefData = Cryptpad.parsePadUrl(data.href);
|
var hrefData = Hash.parsePadUrl(data.href);
|
||||||
return hrefData.type;
|
return hrefData.type;
|
||||||
}
|
}
|
||||||
if (prop === 'atime' || prop === 'ctime') {
|
if (prop === 'atime' || prop === 'ctime') {
|
||||||
@@ -1736,7 +1737,7 @@ define([
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (prop === 'type') {
|
if (prop === 'type') {
|
||||||
var hrefData = Cryptpad.parsePadUrl(e.href);
|
var hrefData = Hash.parsePadUrl(e.href);
|
||||||
return hrefData.type;
|
return hrefData.type;
|
||||||
}
|
}
|
||||||
if (prop === 'atime' || prop === 'ctime') {
|
if (prop === 'atime' || prop === 'ctime') {
|
||||||
@@ -1797,7 +1798,7 @@ define([
|
|||||||
.text(Messages.fm_newFile));
|
.text(Messages.fm_newFile));
|
||||||
$element.attr('title', Messages.fm_newFile);
|
$element.attr('title', Messages.fm_newFile);
|
||||||
$element.click(function () {
|
$element.click(function () {
|
||||||
var $modal = Cryptpad.createModal({
|
var $modal = UIElements.createModal({
|
||||||
id: 'cp-app-drive-new-ghost-dialog',
|
id: 'cp-app-drive-new-ghost-dialog',
|
||||||
$body: $('body')
|
$body: $('body')
|
||||||
});
|
});
|
||||||
@@ -1951,7 +1952,7 @@ define([
|
|||||||
filesList.forEach(function (r) {
|
filesList.forEach(function (r) {
|
||||||
r.paths.forEach(function (path) {
|
r.paths.forEach(function (path) {
|
||||||
var href = r.data.href;
|
var href = r.data.href;
|
||||||
var parsed = Cryptpad.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var $table = $('<table>');
|
var $table = $('<table>');
|
||||||
var $icon = $('<td>', {'rowspan': '3', 'class': 'cp-app-drive-search-icon'})
|
var $icon = $('<td>', {'rowspan': '3', 'class': 'cp-app-drive-search-icon'})
|
||||||
.append(getFileIcon(href));
|
.append(getFileIcon(href));
|
||||||
@@ -2382,6 +2383,13 @@ define([
|
|||||||
if (!filesOp.comparePath(newLocation, currentPath.slice())) { displayDirectory(newLocation); }
|
if (!filesOp.comparePath(newLocation, currentPath.slice())) { displayDirectory(newLocation); }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (e.which === 27) {
|
||||||
|
$input.val('');
|
||||||
|
setSearchCursor(0);
|
||||||
|
if (search.oldLocation && search.oldLocation.length) { displayDirectory(search.oldLocation); }
|
||||||
|
else { displayDirectory([ROOT]); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (APP.mobile()) { return; }
|
if (APP.mobile()) { return; }
|
||||||
search.to = window.setTimeout(function () {
|
search.to = window.setTimeout(function () {
|
||||||
if (!isInSearchTmp) { search.oldLocation = currentPath.slice(); }
|
if (!isInSearchTmp) { search.oldLocation = currentPath.slice(); }
|
||||||
@@ -2441,13 +2449,13 @@ define([
|
|||||||
if (!filesOp.isFile(id)) { return; }
|
if (!filesOp.isFile(id)) { return; }
|
||||||
var data = filesOp.getFileData(id);
|
var data = filesOp.getFileData(id);
|
||||||
if (!data) { return; }
|
if (!data) { return; }
|
||||||
var parsed = Cryptpad.parsePadUrl(data.href);
|
var parsed = Hash.parsePadUrl(data.href);
|
||||||
if (parsed.hashData.type !== "pad") { return; }
|
if (parsed.hashData.type !== "pad") { return; }
|
||||||
var i = data.href.indexOf('#') + 1;
|
var i = data.href.indexOf('#') + 1;
|
||||||
var base = APP.origin + data.href.slice(0, i);
|
var base = data.href.slice(0, i);
|
||||||
var hrefsecret = Cryptpad.getSecrets(parsed.type, parsed.hash);
|
var hrefsecret = Hash.getSecrets(parsed.type, parsed.hash);
|
||||||
if (!hrefsecret.keys) { return; }
|
if (!hrefsecret.keys) { return; }
|
||||||
var viewHash = Cryptpad.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
|
var viewHash = Hash.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
|
||||||
return base + viewHash;
|
return base + viewHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2475,17 +2483,17 @@ define([
|
|||||||
$('<br>').appendTo($d);
|
$('<br>').appendTo($d);
|
||||||
if (!ro) {
|
if (!ro) {
|
||||||
$('<label>', {'for': 'cp-app-drive-prop-link'}).text(Messages.editShare).appendTo($d);
|
$('<label>', {'for': 'cp-app-drive-prop-link'}).text(Messages.editShare).appendTo($d);
|
||||||
$d.append(Cryptpad.dialog.selectable(base + data.href, {
|
$d.append(UI.dialog.selectable(base + data.href, {
|
||||||
id: 'cp-app-drive-prop-link',
|
id: 'cp-app-drive-prop-link',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsed = Cryptpad.parsePadUrl(data.href);
|
var parsed = Hash.parsePadUrl(data.href);
|
||||||
if (parsed.hashData && parsed.hashData.type === 'pad') {
|
if (parsed.hashData && parsed.hashData.type === 'pad') {
|
||||||
var roLink = ro ? base + data.href : getReadOnlyUrl(el);
|
var roLink = ro ? base + data.href : base + getReadOnlyUrl(el);
|
||||||
if (roLink) {
|
if (roLink) {
|
||||||
$('<label>', {'for': 'cp-app-drive-prop-rolink'}).text(Messages.viewShare).appendTo($d);
|
$('<label>', {'for': 'cp-app-drive-prop-rolink'}).text(Messages.viewShare).appendTo($d);
|
||||||
$d.append(Cryptpad.dialog.selectable(roLink, {
|
$d.append(UI.dialog.selectable(roLink, {
|
||||||
id: 'cp-app-drive-prop-rolink',
|
id: 'cp-app-drive-prop-rolink',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -2493,20 +2501,20 @@ define([
|
|||||||
|
|
||||||
if (data.tags && Array.isArray(data.tags)) {
|
if (data.tags && Array.isArray(data.tags)) {
|
||||||
$('<label>', {'for': 'cp-app-drive-prop-tags'}).text(Messages.fm_prop_tagsList).appendTo($d);
|
$('<label>', {'for': 'cp-app-drive-prop-tags'}).text(Messages.fm_prop_tagsList).appendTo($d);
|
||||||
$d.append(Cryptpad.dialog.selectable(data.tags.join(', '), {
|
$d.append(UI.dialog.selectable(data.tags.join(', '), {
|
||||||
id: 'cp-app-drive-prop-tags',
|
id: 'cp-app-drive-prop-tags',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
$('<label>', {'for': 'cp-app-drive-prop-ctime'}).text(Messages.fm_creation)
|
$('<label>', {'for': 'cp-app-drive-prop-ctime'}).text(Messages.fm_creation)
|
||||||
.appendTo($d);
|
.appendTo($d);
|
||||||
$d.append(Cryptpad.dialog.selectable(new Date(data.ctime).toLocaleString(), {
|
$d.append(UI.dialog.selectable(new Date(data.ctime).toLocaleString(), {
|
||||||
id: 'cp-app-drive-prop-ctime',
|
id: 'cp-app-drive-prop-ctime',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$('<label>', {'for': 'cp-app-drive-prop-atime'}).text(Messages.fm_lastAccess)
|
$('<label>', {'for': 'cp-app-drive-prop-atime'}).text(Messages.fm_lastAccess)
|
||||||
.appendTo($d);
|
.appendTo($d);
|
||||||
$d.append(Cryptpad.dialog.selectable(new Date(data.atime).toLocaleString(), {
|
$d.append(UI.dialog.selectable(new Date(data.atime).toLocaleString(), {
|
||||||
id: 'cp-app-drive-prop-atime',
|
id: 'cp-app-drive-prop-atime',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -2522,7 +2530,7 @@ define([
|
|||||||
|
|
||||||
return void cb(void 0, $d);
|
return void cb(void 0, $d);
|
||||||
}
|
}
|
||||||
var KB = Cryptpad.bytesToKilobytes(bytes);
|
var KB = Util.bytesToKilobytes(bytes);
|
||||||
|
|
||||||
var formatted = Messages._getKey('formattedKB', [KB]);
|
var formatted = Messages._getKey('formattedKB', [KB]);
|
||||||
$('<br>').appendTo($d);
|
$('<br>').appendTo($d);
|
||||||
@@ -2531,7 +2539,7 @@ define([
|
|||||||
'for': 'cp-app-drive-prop-size'
|
'for': 'cp-app-drive-prop-size'
|
||||||
}).text(Messages.fc_sizeInKilobytes).appendTo($d);
|
}).text(Messages.fc_sizeInKilobytes).appendTo($d);
|
||||||
|
|
||||||
$d.append(Cryptpad.dialog.selectable(formatted, {
|
$d.append(UI.dialog.selectable(formatted, {
|
||||||
id: 'cp-app-drive-prop-size',
|
id: 'cp-app-drive-prop-size',
|
||||||
}));
|
}));
|
||||||
cb(void 0, $d);
|
cb(void 0, $d);
|
||||||
@@ -2591,7 +2599,7 @@ define([
|
|||||||
el = filesOp.find(paths[0].path);
|
el = filesOp.find(paths[0].path);
|
||||||
getProperties(el, function (e, $prop) {
|
getProperties(el, function (e, $prop) {
|
||||||
if (e) { return void logError(e); }
|
if (e) { return void logError(e); }
|
||||||
Cryptpad.alert($prop[0], undefined, true);
|
UI.alert($prop[0], undefined, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if ($(this).hasClass("cp-app-drive-context-hashtag")) {
|
else if ($(this).hasClass("cp-app-drive-context-hashtag")) {
|
||||||
@@ -2637,7 +2645,7 @@ define([
|
|||||||
if (paths.length === 1) {
|
if (paths.length === 1) {
|
||||||
msg = Messages.fm_removePermanentlyDialog;
|
msg = Messages.fm_removePermanentlyDialog;
|
||||||
}
|
}
|
||||||
Cryptpad.confirm(msg, function(res) {
|
UI.confirm(msg, function(res) {
|
||||||
$(window).focus();
|
$(window).focus();
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.delete(pathsList, refresh);
|
filesOp.delete(pathsList, refresh);
|
||||||
@@ -2651,7 +2659,7 @@ define([
|
|||||||
el = filesOp.find(paths[0].path);
|
el = filesOp.find(paths[0].path);
|
||||||
getProperties(el, function (e, $prop) {
|
getProperties(el, function (e, $prop) {
|
||||||
if (e) { return void logError(e); }
|
if (e) { return void logError(e); }
|
||||||
Cryptpad.alert($prop[0], undefined, true);
|
UI.alert($prop[0], undefined, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if ($(this).hasClass("cp-app-drive-context-hashtag")) {
|
else if ($(this).hasClass("cp-app-drive-context-hashtag")) {
|
||||||
@@ -2670,10 +2678,10 @@ define([
|
|||||||
var path = $(this).data('path');
|
var path = $(this).data('path');
|
||||||
var onCreated = function (err, info) {
|
var onCreated = function (err, info) {
|
||||||
if (err === E_OVER_LIMIT) {
|
if (err === E_OVER_LIMIT) {
|
||||||
return void Cryptpad.alert(Messages.pinLimitDrive, null, true);
|
return void UI.alert(Messages.pinLimitDrive, null, true);
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
return void Cryptpad.alert(Messages.fm_error_cantPin);
|
return void UI.alert(Messages.fm_error_cantPin);
|
||||||
}
|
}
|
||||||
APP.newFolder = info.newPath;
|
APP.newFolder = info.newPath;
|
||||||
refresh();
|
refresh();
|
||||||
@@ -2683,8 +2691,10 @@ define([
|
|||||||
}
|
}
|
||||||
else if ($(this).hasClass("cp-app-drive-context-newdoc")) {
|
else if ($(this).hasClass("cp-app-drive-context-newdoc")) {
|
||||||
var type = $(this).data('type') || 'pad';
|
var type = $(this).data('type') || 'pad';
|
||||||
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
|
var path2 = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
|
||||||
window.open(APP.origin + '/' + type + '/');
|
common.sessionStorage.put(Constants.newPadPathKey, path2, function () {
|
||||||
|
common.openURL('/' + type + '/');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
APP.hideMenu();
|
APP.hideMenu();
|
||||||
});
|
});
|
||||||
@@ -2698,7 +2708,7 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($(this).hasClass("cp-app-drive-context-empty")) {
|
if ($(this).hasClass("cp-app-drive-context-empty")) {
|
||||||
Cryptpad.confirm(Messages.fm_emptyTrashDialog, function(res) {
|
UI.confirm(Messages.fm_emptyTrashDialog, function(res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.emptyTrash(refresh);
|
filesOp.emptyTrash(refresh);
|
||||||
});
|
});
|
||||||
@@ -2718,7 +2728,7 @@ define([
|
|||||||
var name = paths[0].path[paths[0].path.length - 1];
|
var name = paths[0].path[paths[0].path.length - 1];
|
||||||
if ($(this).hasClass("cp-app-drive-context-remove")) {
|
if ($(this).hasClass("cp-app-drive-context-remove")) {
|
||||||
if (paths.length === 1) {
|
if (paths.length === 1) {
|
||||||
Cryptpad.confirm(Messages.fm_removePermanentlyDialog, function(res) {
|
UI.confirm(Messages.fm_removePermanentlyDialog, function(res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.delete([path], refresh);
|
filesOp.delete([path], refresh);
|
||||||
});
|
});
|
||||||
@@ -2727,7 +2737,7 @@ define([
|
|||||||
var pathsList = [];
|
var pathsList = [];
|
||||||
paths.forEach(function (p) { pathsList.push(p.path); });
|
paths.forEach(function (p) { pathsList.push(p.path); });
|
||||||
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
||||||
Cryptpad.confirm(msg, function(res) {
|
UI.confirm(msg, function(res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.delete(pathsList, refresh);
|
filesOp.delete(pathsList, refresh);
|
||||||
});
|
});
|
||||||
@@ -2742,7 +2752,7 @@ define([
|
|||||||
name = path[1];
|
name = path[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Cryptpad.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) {
|
UI.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.restore(path, refresh);
|
filesOp.restore(path, refresh);
|
||||||
});
|
});
|
||||||
@@ -2751,7 +2761,7 @@ define([
|
|||||||
if (paths.length !== 1 || path.length !== 4) { return; }
|
if (paths.length !== 1 || path.length !== 4) { return; }
|
||||||
var element = filesOp.find(path.slice(0,3)); // element containing the oldpath
|
var element = filesOp.find(path.slice(0,3)); // element containing the oldpath
|
||||||
var sPath = stringifyPath(element.path);
|
var sPath = stringifyPath(element.path);
|
||||||
Cryptpad.alert('<strong>' + Messages.fm_originalPath + "</strong>:<br>" + sPath, undefined, true);
|
UI.alert('<strong>' + Messages.fm_originalPath + "</strong>:<br>" + sPath, undefined, true);
|
||||||
}
|
}
|
||||||
APP.hideMenu();
|
APP.hideMenu();
|
||||||
});
|
});
|
||||||
@@ -2800,7 +2810,7 @@ define([
|
|||||||
msg = Messages.fm_removePermanentlyDialog;
|
msg = Messages.fm_removePermanentlyDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cryptpad.confirm(msg, function(res) {
|
UI.confirm(msg, function(res) {
|
||||||
$(window).focus();
|
$(window).focus();
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.delete(paths, refresh);
|
filesOp.delete(paths, refresh);
|
||||||
@@ -2811,6 +2821,19 @@ define([
|
|||||||
moveElements(paths, [TRASH], false, refresh);
|
moveElements(paths, [TRASH], false, refresh);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
var isCharacterKey = function (e) {
|
||||||
|
return e.which === "undefined" /* IE */ ||
|
||||||
|
(e.which > 0 && e.which !== 13 && e.which !== 27 && !e.ctrlKey && !e.altKey);
|
||||||
|
};
|
||||||
|
$appContainer.on('keypress', function (e) {
|
||||||
|
var $searchBar = $tree.find('#cp-app-drive-tree-search-input');
|
||||||
|
if ($searchBar.is(':focus')) { return; }
|
||||||
|
if (isCharacterKey(e)) {
|
||||||
|
$searchBar.focus();
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
$appContainer.contextmenu(function () {
|
$appContainer.contextmenu(function () {
|
||||||
APP.hideMenu();
|
APP.hideMenu();
|
||||||
return false;
|
return false;
|
||||||
@@ -2882,7 +2905,7 @@ define([
|
|||||||
APP.FM = common.createFileManager(fmConfig);
|
APP.FM = common.createFileManager(fmConfig);
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
var setHistory = function (bool, update) {
|
var setHistory = function (bool, update) {
|
||||||
@@ -2900,7 +2923,7 @@ define([
|
|||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(function () {
|
$(waitFor(function () {
|
||||||
Cryptpad.addLoadingScreen();
|
UI.addLoadingScreen();
|
||||||
}));
|
}));
|
||||||
window.cryptpadStore.getAll(waitFor(function (val) {
|
window.cryptpadStore.getAll(waitFor(function (val) {
|
||||||
APP.store = JSON.parse(JSON.stringify(val));
|
APP.store = JSON.parse(JSON.stringify(val));
|
||||||
@@ -2948,7 +2971,6 @@ define([
|
|||||||
metadataMgr: metadataMgr,
|
metadataMgr: metadataMgr,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
realtime: info.realtime,
|
realtime: info.realtime,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: APP.$bar
|
$container: APP.$bar
|
||||||
};
|
};
|
||||||
@@ -2979,26 +3001,6 @@ define([
|
|||||||
$toolbar: APP.$bar,
|
$toolbar: APP.$bar,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO iframe: backup button here?
|
|
||||||
if (!readOnly && !APP.loggedIn) {
|
|
||||||
// TODO secure drive
|
|
||||||
// cryptpad-backup --> cp-toolbar-backup
|
|
||||||
var $backupButton = Cryptpad.createButton('', true).removeClass('fa').removeClass('fa-question').addClass('cryptpad-backup');
|
|
||||||
$backupButton.append($backupIcon.clone().css('marginRight', '0px'));
|
|
||||||
$backupButton.attr('title', Messages.fm_backup_title);
|
|
||||||
$backupButton.on('click', function() {
|
|
||||||
var url = window.location.origin + window.location.pathname + '#' + editHash;
|
|
||||||
var msg = Messages.fm_alert_backupUrl + '<input type="text" readonly="readonly" id="fm_backupUrl" value="'+url+'">';
|
|
||||||
Cryptpad.alert(msg, undefined, true);
|
|
||||||
$('#fm_backupUrl').val(url);
|
|
||||||
$('#fm_backupUrl').click(function () {
|
|
||||||
$(this).select();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
$userBlock.append($backupButton);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
metadataMgr.onChange(function () {
|
metadataMgr.onChange(function () {
|
||||||
var name = metadataMgr.getUserData().name || Messages.anonymous;
|
var name = metadataMgr.getUserData().name || Messages.anonymous;
|
||||||
APP.$displayName.text(name);
|
APP.$displayName.text(name);
|
||||||
@@ -3012,19 +3014,19 @@ define([
|
|||||||
APP.files = proxy;
|
APP.files = proxy;
|
||||||
if (!proxy.drive || typeof(proxy.drive) !== 'object') { proxy.drive = {}; }
|
if (!proxy.drive || typeof(proxy.drive) !== 'object') { proxy.drive = {}; }
|
||||||
andThen(common, proxy);
|
andThen(common, proxy);
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
};
|
};
|
||||||
var onDisconnect = APP.onDisconnect = function (noAlert) {
|
var onDisconnect = APP.onDisconnect = function (noAlert) {
|
||||||
setEditable(false);
|
setEditable(false);
|
||||||
if (APP.refresh) { APP.refresh(); }
|
if (APP.refresh) { APP.refresh(); }
|
||||||
APP.toolbar.failed();
|
APP.toolbar.failed();
|
||||||
if (!noAlert) { Cryptpad.alert(Messages.common_connectionLost, undefined, true); }
|
if (!noAlert) { UI.alert(Messages.common_connectionLost, undefined, true); }
|
||||||
};
|
};
|
||||||
var onReconnect = function (info) {
|
var onReconnect = function (info) {
|
||||||
setEditable(true);
|
setEditable(true);
|
||||||
if (APP.refresh) { APP.refresh(); }
|
if (APP.refresh) { APP.refresh(); }
|
||||||
APP.toolbar.reconnecting(info.myId);
|
APP.toolbar.reconnecting(info.myId);
|
||||||
Cryptpad.findOKButton().click();
|
UI.findOKButton().click();
|
||||||
};
|
};
|
||||||
|
|
||||||
proxy.on('create', function (info) {
|
proxy.on('create', function (info) {
|
||||||
@@ -3038,13 +3040,7 @@ define([
|
|||||||
proxy.on('reconnect', function (info) {
|
proxy.on('reconnect', function (info) {
|
||||||
onReconnect(info);
|
onReconnect(info);
|
||||||
});
|
});
|
||||||
|
common.onLogout(function () { setEditable(false); });
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//Cryptpad.onLogout(function () { setEditable(false); });
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
main();
|
main();
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ define([
|
|||||||
};
|
};
|
||||||
window.addEventListener('message', onMsg);
|
window.addEventListener('message', onMsg);
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
var getSecrets = function (Cryptpad) {
|
var getSecrets = function (Cryptpad, Utils) {
|
||||||
var hash = window.location.hash.slice(1) || Cryptpad.getUserHash() || localStorage.FS_hash;
|
var hash = window.location.hash.slice(1) || Cryptpad.getUserHash() || localStorage.FS_hash;
|
||||||
return Cryptpad.getSecrets('drive', hash);
|
return Utils.Hash.getSecrets('drive', hash);
|
||||||
};
|
};
|
||||||
Netflux.connect(Cryptpad.getWebsocketURL()).then(function (network) {
|
Netflux.connect(Cryptpad.getWebsocketURL()).then(function (network) {
|
||||||
SFCommonO.start({
|
SFCommonO.start({
|
||||||
|
|||||||
@@ -69,7 +69,12 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.test = function (assert) {
|
module.test = function (assert) {
|
||||||
var config = {Cryptpad: Cryptpad, workgroup: false, testMode: true};
|
var config = {
|
||||||
|
Cryptpad: Cryptpad,
|
||||||
|
workgroup: false,
|
||||||
|
testMode: true,
|
||||||
|
loggedIn: false
|
||||||
|
};
|
||||||
|
|
||||||
// MIGRATION FROM HREF TO ID
|
// MIGRATION FROM HREF TO ID
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/common/common-realtime.js',
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'/file/file-crypto.js',
|
'/file/file-crypto.js',
|
||||||
'/common/media-tag.js',
|
'/common/media-tag.js',
|
||||||
@@ -20,20 +23,20 @@ define([
|
|||||||
$,
|
$,
|
||||||
Crypto,
|
Crypto,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
CommonRealtime,
|
CommonRealtime,
|
||||||
|
Util,
|
||||||
|
Hash,
|
||||||
|
UI,
|
||||||
|
Messages,
|
||||||
FileCrypto,
|
FileCrypto,
|
||||||
MediaTag)
|
MediaTag)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
var saveAs = window.saveAs;
|
var saveAs = window.saveAs;
|
||||||
var Nacl = window.nacl;
|
var Nacl = window.nacl;
|
||||||
|
|
||||||
var APP = window.APP = {
|
var APP = window.APP = {};
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
};
|
|
||||||
|
|
||||||
var andThen = function (common) {
|
var andThen = function (common) {
|
||||||
var $appContainer = $('#cp-app-file-content');
|
var $appContainer = $('#cp-app-file-content');
|
||||||
@@ -58,9 +61,9 @@ define([
|
|||||||
if (!priv.filehash) {
|
if (!priv.filehash) {
|
||||||
uploadMode = true;
|
uploadMode = true;
|
||||||
} else {
|
} else {
|
||||||
secret = Cryptpad.getSecrets('file', priv.filehash);
|
secret = Hash.getSecrets('file', priv.filehash);
|
||||||
if (!secret.keys) { throw new Error("You need a hash"); }
|
if (!secret.keys) { throw new Error("You need a hash"); }
|
||||||
hexFileName = Cryptpad.base64ToHex(secret.channel);
|
hexFileName = Util.base64ToHex(secret.channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
var Title = common.createTitle({});
|
var Title = common.createTitle({});
|
||||||
@@ -70,7 +73,6 @@ define([
|
|||||||
}
|
}
|
||||||
var configTb = {
|
var configTb = {
|
||||||
displayed: displayed,
|
displayed: displayed,
|
||||||
common: Cryptpad,
|
|
||||||
//hideDisplayName: true,
|
//hideDisplayName: true,
|
||||||
$container: $bar,
|
$container: $bar,
|
||||||
metadataMgr: metadataMgr,
|
metadataMgr: metadataMgr,
|
||||||
@@ -84,7 +86,7 @@ define([
|
|||||||
toolbar.$rightside.html('');
|
toolbar.$rightside.html('');
|
||||||
|
|
||||||
if (!uploadMode) {
|
if (!uploadMode) {
|
||||||
var src = Cryptpad.getBlobPathFromHex(hexFileName);
|
var src = Hash.getBlobPathFromHex(hexFileName);
|
||||||
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||||
var key = Nacl.util.decodeBase64(cryptKey);
|
var key = Nacl.util.decodeBase64(cryptKey);
|
||||||
|
|
||||||
@@ -106,7 +108,7 @@ define([
|
|||||||
|
|
||||||
var $mt = $dlview.find('media-tag');
|
var $mt = $dlview.find('media-tag');
|
||||||
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||||
var hexFileName = Cryptpad.base64ToHex(secret.channel);
|
var hexFileName = Util.base64ToHex(secret.channel);
|
||||||
$mt.attr('src', '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName);
|
$mt.attr('src', '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName);
|
||||||
$mt.attr('data-crypto-key', 'cryptpad:'+cryptKey);
|
$mt.attr('data-crypto-key', 'cryptpad:'+cryptKey);
|
||||||
|
|
||||||
@@ -128,7 +130,7 @@ define([
|
|||||||
}
|
}
|
||||||
$dlButton.addClass('btn btn-success');
|
$dlButton.addClass('btn btn-success');
|
||||||
var text = Messages.download_mt_button + '<br>';
|
var text = Messages.download_mt_button + '<br>';
|
||||||
text += '<b>' + Cryptpad.fixHTML(title) + '</b><br>';
|
text += '<b>' + Util.fixHTML(title) + '</b><br>';
|
||||||
text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>';
|
text += '<em>' + Messages._getKey('formattedMB', [sizeMb]) + '</em>';
|
||||||
$dlButton.html(text);
|
$dlButton.html(text);
|
||||||
|
|
||||||
@@ -165,7 +167,7 @@ define([
|
|||||||
})
|
})
|
||||||
.on('decryptionError', function (e) {
|
.on('decryptionError', function (e) {
|
||||||
var error = e.originalEvent;
|
var error = e.originalEvent;
|
||||||
//Cryptpad.alert(error.message);
|
//UI.alert(error.message);
|
||||||
cb(error.message);
|
cb(error.message);
|
||||||
})
|
})
|
||||||
.on('decryptionProgress', function (e) {
|
.on('decryptionProgress', function (e) {
|
||||||
@@ -203,9 +205,9 @@ define([
|
|||||||
|
|
||||||
var todoBigFile = function (sizeMb) {
|
var todoBigFile = function (sizeMb) {
|
||||||
$dlform.show();
|
$dlform.show();
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
$dllabel.append($('<br>'));
|
$dllabel.append($('<br>'));
|
||||||
$dllabel.append(Cryptpad.fixHTML(metadata.name));
|
$dllabel.append(Util.fixHTML(metadata.name));
|
||||||
|
|
||||||
// don't display the size if you don't know it.
|
// don't display the size if you don't know it.
|
||||||
if (typeof(sizeM) === 'number') {
|
if (typeof(sizeM) === 'number') {
|
||||||
@@ -217,7 +219,7 @@ define([
|
|||||||
if (decrypting) { return; }
|
if (decrypting) { return; }
|
||||||
decrypting = true;
|
decrypting = true;
|
||||||
displayFile(ev, sizeMb, function (err) {
|
displayFile(ev, sizeMb, function (err) {
|
||||||
if (err) { Cryptpad.alert(err); }
|
if (err) { UI.alert(err); }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
|
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
|
||||||
@@ -226,9 +228,9 @@ define([
|
|||||||
var href = priv.origin + priv.pathname + priv.filehash;
|
var href = priv.origin + priv.pathname + priv.filehash;
|
||||||
common.getFileSize(href, function (e, data) {
|
common.getFileSize(href, function (e, data) {
|
||||||
if (e) {
|
if (e) {
|
||||||
return void Cryptpad.errorLoadingScreen(e);
|
return void UI.errorLoadingScreen(e);
|
||||||
}
|
}
|
||||||
var size = Cryptpad.bytesToMegabytes(data);
|
var size = Util.bytesToMegabytes(data);
|
||||||
return void todoBigFile(size);
|
return void todoBigFile(size);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -238,8 +240,8 @@ define([
|
|||||||
// we're in upload mode
|
// we're in upload mode
|
||||||
|
|
||||||
if (!common.isLoggedIn()) {
|
if (!common.isLoggedIn()) {
|
||||||
return Cryptpad.alert(Messages.upload_mustLogin, function () {
|
return UI.alert(Messages.upload_mustLogin, function () {
|
||||||
Cryptpad.errorLoadingScreen(Messages.upload_mustLogin);
|
UI.errorLoadingScreen(Messages.upload_mustLogin);
|
||||||
common.setLoginRedirect(function () {
|
common.setLoginRedirect(function () {
|
||||||
common.gotoURL('/login/');
|
common.gotoURL('/login/');
|
||||||
});
|
});
|
||||||
@@ -264,7 +266,7 @@ define([
|
|||||||
FM.handleFile(file);
|
FM.handleFile(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
var main = function () {
|
var main = function () {
|
||||||
@@ -272,7 +274,7 @@ define([
|
|||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(function () {
|
$(waitFor(function () {
|
||||||
Cryptpad.addLoadingScreen();
|
UI.addLoadingScreen();
|
||||||
}));
|
}));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
img {
|
img {
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
max-height: 100px;
|
max-height: 100px;
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cp-filepicker-content-element-name {
|
.cp-filepicker-content-element-name {
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-ui-elements.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
'json.sortify',
|
'json.sortify',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
@@ -12,20 +16,16 @@ define([
|
|||||||
], function (
|
], function (
|
||||||
$,
|
$,
|
||||||
Crypto,
|
Crypto,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
Sortify)
|
UI,
|
||||||
|
UIElements,
|
||||||
|
Util,
|
||||||
|
Hash,
|
||||||
|
Sortify,
|
||||||
|
Messages)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
var APP = window.APP = {};
|
||||||
|
|
||||||
var APP = window.APP = {
|
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
};
|
|
||||||
|
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var andThen = function (common) {
|
var andThen = function (common) {
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
@@ -37,10 +37,10 @@ define([
|
|||||||
sframeChan.event('EV_FILE_PICKER_CLOSE');
|
sframeChan.event('EV_FILE_PICKER_CLOSE');
|
||||||
};
|
};
|
||||||
var onFilePicked = function (data) {
|
var onFilePicked = function (data) {
|
||||||
var parsed = Cryptpad.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
hideFileDialog();
|
hideFileDialog();
|
||||||
if (parsed.type === 'file') {
|
if (parsed.type === 'file') {
|
||||||
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
sframeChan.event("EV_FILE_PICKED", {
|
sframeChan.event("EV_FILE_PICKED", {
|
||||||
type: parsed.type,
|
type: parsed.type,
|
||||||
@@ -76,7 +76,7 @@ define([
|
|||||||
var createFileDialog = function () {
|
var createFileDialog = function () {
|
||||||
var types = filters.types || [];
|
var types = filters.types || [];
|
||||||
// Create modal
|
// Create modal
|
||||||
var $blockContainer = Cryptpad.createModal({
|
var $blockContainer = UIElements.createModal({
|
||||||
id: 'cp-filepicker-dialog',
|
id: 'cp-filepicker-dialog',
|
||||||
$body: $body,
|
$body: $body,
|
||||||
onClose: hideFileDialog
|
onClose: hideFileDialog
|
||||||
@@ -128,7 +128,7 @@ define([
|
|||||||
'class': 'cp-filepicker-content-element',
|
'class': 'cp-filepicker-content-element',
|
||||||
'title': name,
|
'title': name,
|
||||||
}).appendTo($container);
|
}).appendTo($container);
|
||||||
$span.append(Cryptpad.getFileIcon(data));
|
$span.append(UI.getFileIcon(data));
|
||||||
$('<span>', {'class': 'cp-filepicker-content-element-name'}).text(name)
|
$('<span>', {'class': 'cp-filepicker-content-element-name'}).text(name)
|
||||||
.appendTo($span);
|
.appendTo($span);
|
||||||
$span.click(function () {
|
$span.click(function () {
|
||||||
@@ -145,8 +145,6 @@ define([
|
|||||||
updateContainer();
|
updateContainer();
|
||||||
};
|
};
|
||||||
sframeChan.on('EV_FILE_PICKER_REFRESH', function (newFilters) {
|
sframeChan.on('EV_FILE_PICKER_REFRESH', function (newFilters) {
|
||||||
console.log(Sortify(filters));
|
|
||||||
console.log(Sortify(newFilters));
|
|
||||||
if (Sortify(filters) !== Sortify(newFilters)) {
|
if (Sortify(filters) !== Sortify(newFilters)) {
|
||||||
$body.html('');
|
$body.html('');
|
||||||
filters = newFilters;
|
filters = newFilters;
|
||||||
@@ -156,7 +154,7 @@ define([
|
|||||||
});
|
});
|
||||||
createFileDialog();
|
createFileDialog();
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
var main = function () {
|
var main = function () {
|
||||||
@@ -164,16 +162,11 @@ define([
|
|||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(function () {
|
$(waitFor(function () {
|
||||||
Cryptpad.addLoadingScreen({hideTips: true, hideLogo: true});
|
UI.addLoadingScreen({hideTips: true, hideLogo: true});
|
||||||
}));
|
}));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (metadataMgr.getMetadataLazy() !== 'uninitialized') {
|
if (metadataMgr.getMetadataLazy() !== 'uninitialized') {
|
||||||
andThen(common);
|
andThen(common);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -38,25 +38,13 @@ define([
|
|||||||
window.addEventListener('message', onMsg);
|
window.addEventListener('message', onMsg);
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
var Cryptpad;
|
var Cryptpad;
|
||||||
var Crypto;
|
|
||||||
var Cryptget;
|
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
// Load #2, the loading screen is up so grab whatever you need...
|
Cryptpad = config.modules.Cryptpad;
|
||||||
require([
|
config.modules.SFrameChannel.create($('#sbox-filePicker-iframe')[0].contentWindow,
|
||||||
'/common/cryptpad-common.js',
|
waitFor(function (sfc) {
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
|
||||||
'/common/cryptget.js',
|
|
||||||
'/common/sframe-channel.js',
|
|
||||||
], waitFor(function (_Cryptpad, _Crypto, _Cryptget, SFrameChannel) {
|
|
||||||
Cryptpad = _Cryptpad;
|
|
||||||
Crypto = _Crypto;
|
|
||||||
Cryptget = _Cryptget;
|
|
||||||
SFrameChannel.create($('#sbox-filePicker-iframe')[0].contentWindow, waitFor(function (sfc) {
|
|
||||||
sframeChan = sfc;
|
sframeChan = sfc;
|
||||||
}));
|
}));
|
||||||
Cryptpad.ready(waitFor());
|
|
||||||
}));
|
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
var proxy = Cryptpad.getProxy();
|
var proxy = Cryptpad.getProxy();
|
||||||
var updateMeta = function () {
|
var updateMeta = function () {
|
||||||
@@ -94,29 +82,7 @@ define([
|
|||||||
sframeChan.onReg('EV_METADATA_UPDATE', updateMeta);
|
sframeChan.onReg('EV_METADATA_UPDATE', updateMeta);
|
||||||
proxy.on('change', 'settings', updateMeta);
|
proxy.on('change', 'settings', updateMeta);
|
||||||
|
|
||||||
Cryptpad.onError(function (info) {
|
config.addCommonRpc(sframeChan);
|
||||||
console.log('error');
|
|
||||||
console.log(info);
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
//onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) {
|
|
||||||
Cryptpad.anonRpcMsg(data.msg, data.content, function (err, response) {
|
|
||||||
cb({error: err, response: response});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('Q_GET_PIN_LIMIT_STATUS', function (data, cb) {
|
|
||||||
Cryptpad.isOverPinLimit(function (e, overLimit, limits) {
|
|
||||||
cb({
|
|
||||||
error: e,
|
|
||||||
overLimit: overLimit,
|
|
||||||
limits: limits
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
sframeChan.on('Q_GET_FILES_LIST', function (types, cb) {
|
sframeChan.on('Q_GET_FILES_LIST', function (types, cb) {
|
||||||
console.error("TODO: make sure Q_GET_FILES_LIST is only available from filepicker");
|
console.error("TODO: make sure Q_GET_FILES_LIST is only available from filepicker");
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
'/common/common-interface.js',
|
||||||
|
//'/common/common-hash.js',
|
||||||
|
//'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
||||||
//'/common/curve.js',
|
//'/common/curve.js',
|
||||||
'less!/invite/main.less',
|
'less!/invite/main.less',
|
||||||
], function ($, Cryptpad /*, Listmap, Curve*/) {
|
], function ($, Cryptpad, UI/*, Hash , Listmap, Curve*/) {
|
||||||
var Messages = Cryptpad.Messages;
|
var Messages = Cryptpad.Messages;
|
||||||
var comingSoon = function () {
|
var comingSoon = function () {
|
||||||
return $('<div>', {
|
return $('<div>', {
|
||||||
@@ -15,7 +17,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
console.log("wut");
|
console.log("wut");
|
||||||
$('body #mainBlock').append(comingSoon());
|
$('body #mainBlock').append(comingSoon());
|
||||||
});
|
});
|
||||||
@@ -33,12 +35,12 @@ define([
|
|||||||
var andThen = function () {
|
var andThen = function () {
|
||||||
var hash = window.location.hash.slice(1);
|
var hash = window.location.hash.slice(1);
|
||||||
|
|
||||||
var info = Cryptpad.parseTypeHash('invite', hash);
|
var info = Hash.parseTypeHash('invite', hash);
|
||||||
console.log(info);
|
console.log(info);
|
||||||
|
|
||||||
if (!info.pubkey) {
|
if (!info.pubkey) {
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
Cryptpad.alert('invalid invite');
|
UI.alert('invalid invite');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ define([
|
|||||||
var keys = Curve.deriveKeys(info.pubkey, mySecret);
|
var keys = Curve.deriveKeys(info.pubkey, mySecret);
|
||||||
var encryptor = Curve.createEncryptor(keys);
|
var encryptor = Curve.createEncryptor(keys);
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
|
|
||||||
var listmapConfig = {
|
var listmapConfig = {
|
||||||
data: {},
|
data: {},
|
||||||
@@ -72,23 +74,6 @@ define([
|
|||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
var $main = $('#mainBlock');
|
var $main = $('#mainBlock');
|
||||||
// Language selector
|
|
||||||
var $sel = $('#language-selector');
|
|
||||||
Cryptpad.createLanguageSelector(undefined, $sel);
|
|
||||||
$sel.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
$sel.show();
|
|
||||||
|
|
||||||
// User admin menu
|
|
||||||
var $userMenu = $('#user-menu');
|
|
||||||
var userMenuCfg = {
|
|
||||||
$initBlock: $userMenu
|
|
||||||
};
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
$userAdmin.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// main block is hidden in case javascript is disabled
|
// main block is hidden in case javascript is disabled
|
||||||
$main.removeClass('hidden');
|
$main.removeClass('hidden');
|
||||||
|
|||||||
@@ -2,31 +2,15 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/common/login.js',
|
'/common/login.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
], function ($, Cryptpad, Login) {
|
], function ($, Cryptpad, Login, UI, Realtime) {
|
||||||
$(function () {
|
$(function () {
|
||||||
var $main = $('#mainBlock');
|
var $main = $('#mainBlock');
|
||||||
var Messages = Cryptpad.Messages;
|
var Messages = Cryptpad.Messages;
|
||||||
|
|
||||||
// Language selector
|
|
||||||
var $sel = $('#language-selector');
|
|
||||||
Cryptpad.createLanguageSelector(undefined, $sel);
|
|
||||||
$sel.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
$sel.show();
|
|
||||||
|
|
||||||
// User admin menu
|
|
||||||
var $userMenu = $('#user-menu');
|
|
||||||
var userMenuCfg = {
|
|
||||||
$initBlock: $userMenu
|
|
||||||
};
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
$userAdmin.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// main block is hidden in case javascript is disabled
|
// main block is hidden in case javascript is disabled
|
||||||
$main.removeClass('hidden');
|
$main.removeClass('hidden');
|
||||||
|
|
||||||
@@ -74,7 +58,7 @@ define([
|
|||||||
|
|
||||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
Cryptpad.addLoadingScreen({
|
UI.addLoadingScreen({
|
||||||
loadingText: Messages.login_hashing,
|
loadingText: Messages.login_hashing,
|
||||||
hideTips: true,
|
hideTips: true,
|
||||||
});
|
});
|
||||||
@@ -100,7 +84,7 @@ define([
|
|||||||
proxy.curvePublic = result.curvePublic;
|
proxy.curvePublic = result.curvePublic;
|
||||||
|
|
||||||
Cryptpad.feedback('LOGIN', true);
|
Cryptpad.feedback('LOGIN', true);
|
||||||
Cryptpad.whenRealtimeSyncs(result.realtime, function() {
|
Realtime.whenRealtimeSyncs(result.realtime, function() {
|
||||||
Cryptpad.login(result.userHash, result.userName, function () {
|
Cryptpad.login(result.userHash, result.userName, function () {
|
||||||
hashing = false;
|
hashing = false;
|
||||||
if (sessionStorage.redirectTo) {
|
if (sessionStorage.redirectTo) {
|
||||||
@@ -120,28 +104,28 @@ define([
|
|||||||
}
|
}
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'NO_SUCH_USER':
|
case 'NO_SUCH_USER':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_noSuchUser, function () {
|
UI.alert(Messages.login_noSuchUser, function () {
|
||||||
hashing = false;
|
hashing = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'INVAL_USER':
|
case 'INVAL_USER':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_invalUser, function () {
|
UI.alert(Messages.login_invalUser, function () {
|
||||||
hashing = false;
|
hashing = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'INVAL_PASS':
|
case 'INVAL_PASS':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_invalPass, function () {
|
UI.alert(Messages.login_invalPass, function () {
|
||||||
hashing = false;
|
hashing = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default: // UNHANDLED ERROR
|
default: // UNHANDLED ERROR
|
||||||
Cryptpad.errorLoadingScreen(Messages.login_unhandledError);
|
UI.errorLoadingScreen(Messages.login_unhandledError);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html class="cp">
|
|
||||||
<!-- If this file is not called customize.dist/src/template.html, it is generated -->
|
|
||||||
<head>
|
|
||||||
<title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
|
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
||||||
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
|
|
||||||
<script async data-bootload="/customize/template.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
|
||||||
</head>
|
|
||||||
<body class="html">
|
|
||||||
<noscript>
|
|
||||||
<p><strong>OOPS</strong> In order to do encryption in your browser, Javascript is really <strong>really</strong> required.</p>
|
|
||||||
<p><strong>OUPS</strong> Afin de pouvoir réaliser le chiffrement dans votre navigateur, Javascript est <strong>vraiment</strong> nécessaire.</p>
|
|
||||||
</noscript>
|
|
||||||
</html>
|
|
||||||
@@ -1,569 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/cryptget.js',
|
|
||||||
'/common/mergeDrive.js',
|
|
||||||
'/common/toolbar2.js',
|
|
||||||
'/bower_components/file-saver/FileSaver.min.js',
|
|
||||||
|
|
||||||
'less!/customize/src/less/cryptpad.less',
|
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
|
||||||
'less!/customize/src/less/toolbar.less',
|
|
||||||
'less!/settings/main.less',
|
|
||||||
], function ($, Cryptpad, Crypt, Merge, Toolbar) {
|
|
||||||
var saveAs = window.saveAs;
|
|
||||||
|
|
||||||
var USERNAME_KEY = 'cryptpad.username';
|
|
||||||
|
|
||||||
var APP = window.APP = {
|
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
_onRefresh: []
|
|
||||||
};
|
|
||||||
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
// Manage changes in the realtime object made from another page
|
|
||||||
var onRefresh = function (h) {
|
|
||||||
if (typeof(h) !== "function") { return; }
|
|
||||||
if (APP._onRefresh.indexOf(h) !== -1) { return; }
|
|
||||||
APP._onRefresh.push(h);
|
|
||||||
};
|
|
||||||
var refresh = APP.refresh = function () {
|
|
||||||
APP._onRefresh.forEach(function (h) {
|
|
||||||
h();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var categories = {
|
|
||||||
'account': [
|
|
||||||
'infoBlock',
|
|
||||||
'displayName',
|
|
||||||
'languageSelector',
|
|
||||||
'logoutEverywhere',
|
|
||||||
'resetTips',
|
|
||||||
'thumbnails',
|
|
||||||
'userFeedback'
|
|
||||||
],
|
|
||||||
'drive': [
|
|
||||||
'backupDrive',
|
|
||||||
'importLocalPads',
|
|
||||||
'resetDrive'
|
|
||||||
],
|
|
||||||
'code': [
|
|
||||||
'indentUnit',
|
|
||||||
'indentType'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
var createInfoBlock = function (store) {
|
|
||||||
var obj = store.proxy;
|
|
||||||
var $div = $('<div>', {'class': 'infoBlock'});
|
|
||||||
|
|
||||||
var $account = $('<div>', {'class': 'element'}).appendTo($div);
|
|
||||||
var accountName = obj.login_name || localStorage[Cryptpad.userNameKey];
|
|
||||||
var $label = $('<span>', {'class': 'label'}).text(Messages.user_accountName);
|
|
||||||
var $name = $('<span>').text(accountName || '');
|
|
||||||
if (!accountName) {
|
|
||||||
$label.text('');
|
|
||||||
$name.text(Messages.settings_anonymous);
|
|
||||||
}
|
|
||||||
$account.append($label).append($name);
|
|
||||||
|
|
||||||
var publicKey = obj.edPublic;
|
|
||||||
if (publicKey) {
|
|
||||||
var $key = $('<div>', {'class': 'element'}).appendTo($div);
|
|
||||||
var userHref = Cryptpad.getUserHrefFromKeys(accountName, publicKey);
|
|
||||||
var $pubLabel = $('<span>', {'class': 'label'})
|
|
||||||
.text(Messages.settings_publicSigningKey);
|
|
||||||
$key.append($pubLabel).append(Cryptpad.dialog.selectable(userHref));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the block containing the display name field
|
|
||||||
var createDisplayNameInput = function (store) {
|
|
||||||
var obj = store.proxy;
|
|
||||||
var $div = $('<div>', {'class': 'displayName element'});
|
|
||||||
$('<label>', {'for' : 'displayName'}).text(Messages.user_displayName).appendTo($div);
|
|
||||||
var $inputBlock = $('<div>', {'class': 'inputBlock'}).appendTo($div);
|
|
||||||
var $input = $('<input>', {
|
|
||||||
'type': 'text',
|
|
||||||
'id': 'displayName',
|
|
||||||
'placeholder': Messages.anonymous}).appendTo($inputBlock);
|
|
||||||
var $save = $('<button>', {'class': 'btn btn-primary'}).text(Messages.settings_save).appendTo($inputBlock);
|
|
||||||
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved}).hide().appendTo($div);
|
|
||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div);
|
|
||||||
|
|
||||||
var displayName = obj[USERNAME_KEY] || '';
|
|
||||||
$input.val(displayName);
|
|
||||||
|
|
||||||
// When the display name is changed (enter or button clicked)
|
|
||||||
var todo = function () {
|
|
||||||
displayName = $input.val();
|
|
||||||
if (displayName === obj[USERNAME_KEY]) { return; }
|
|
||||||
obj[USERNAME_KEY] = displayName;
|
|
||||||
Cryptpad.changeDisplayName(displayName);
|
|
||||||
$spinner.show();
|
|
||||||
Cryptpad.whenRealtimeSyncs(store.info.realtime, function () {
|
|
||||||
$spinner.hide();
|
|
||||||
$ok.show();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
$input.on('keyup', function (e) {
|
|
||||||
if ($input.val() !== displayName) { $ok.hide(); }
|
|
||||||
if (e.which === 13) { todo(); }
|
|
||||||
});
|
|
||||||
$save.click(todo);
|
|
||||||
|
|
||||||
// On remote change
|
|
||||||
var onChange = function () {
|
|
||||||
if (obj[USERNAME_KEY] !== $input.val()) {
|
|
||||||
$input.val(obj[USERNAME_KEY]);
|
|
||||||
$input.focusout();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onRefresh(onChange);
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
var createIndentUnitSelector = function (obj) {
|
|
||||||
var proxy = obj.proxy;
|
|
||||||
proxy.settings = proxy.settings || {};
|
|
||||||
|
|
||||||
var $div = $('<div>', {
|
|
||||||
'class': 'indentUnit element'
|
|
||||||
});
|
|
||||||
$('<label>').text(Messages.settings_codeIndentation).appendTo($div);
|
|
||||||
|
|
||||||
var $inputBlock = $('<div>', {
|
|
||||||
'class': 'inputBlock',
|
|
||||||
}).appendTo($div);
|
|
||||||
|
|
||||||
var $input = $('<input>', {
|
|
||||||
'min': 1,
|
|
||||||
'max': 8,
|
|
||||||
type: 'number',
|
|
||||||
}).on('change', function () {
|
|
||||||
var val = parseInt($input.val());
|
|
||||||
if (typeof(val) !== 'number') { return; }
|
|
||||||
Cryptpad.setAttribute(['codemirror', 'indentUnit'], val);
|
|
||||||
}).appendTo($inputBlock);
|
|
||||||
|
|
||||||
proxy.on('change', [ 'settings', 'codemirror', 'indentUnit', ], function (o, n) {
|
|
||||||
$input.val(n);
|
|
||||||
});
|
|
||||||
|
|
||||||
Cryptpad.getAttribute(['codemirror', 'indentUnit'], function (e, val) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
if (typeof(val) !== 'number') {
|
|
||||||
$input.val(2);
|
|
||||||
} else {
|
|
||||||
$input.val(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createIndentTypeSelector = function (obj) {
|
|
||||||
var proxy = obj.proxy;
|
|
||||||
proxy.settings = proxy.settings || {};
|
|
||||||
|
|
||||||
var key = 'indentWithTabs';
|
|
||||||
|
|
||||||
var $div = $('<div>', {
|
|
||||||
'class': 'indentType element'
|
|
||||||
});
|
|
||||||
$('<label>').text(Messages.settings_codeUseTabs).appendTo($div);
|
|
||||||
|
|
||||||
var $inputBlock = $('<div>', {
|
|
||||||
'class': 'inputBlock',
|
|
||||||
}).css('flex-flow', 'column')
|
|
||||||
.appendTo($div);
|
|
||||||
|
|
||||||
var $input = $('<input>', {
|
|
||||||
type: 'checkbox',
|
|
||||||
}).on('change', function () {
|
|
||||||
var val = $input.is(':checked');
|
|
||||||
if (typeof(val) !== 'boolean') { return; }
|
|
||||||
Cryptpad.setAttribute(['codemirror', key], val);
|
|
||||||
}).appendTo($inputBlock);
|
|
||||||
|
|
||||||
$input[0].checked = !!proxy.settings[key];
|
|
||||||
proxy.on('change', ['settings', 'codemirror', key], function (o, n) {
|
|
||||||
$input[0].checked = !!n;
|
|
||||||
});
|
|
||||||
|
|
||||||
Cryptpad.getAttribute(['codemirror', key], function (e, val) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
$input[0].checked = !!val;
|
|
||||||
});
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createResetTips = function () {
|
|
||||||
var $div = $('<div>', {'class': 'resetTips element'});
|
|
||||||
$('<label>', {'for' : 'resetTips'}).text(Messages.settings_resetTips).appendTo($div);
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_resetTipsButton).appendTo($div);
|
|
||||||
var $button = $('<button>', {'id': 'resetTips', 'class': 'btn btn-primary'})
|
|
||||||
.text(Messages.settings_resetTipsAction).appendTo($div);
|
|
||||||
|
|
||||||
$button.click(function () {
|
|
||||||
Object.keys(localStorage).forEach(function (k) {
|
|
||||||
if(k.slice(0, 9) === "hide-info") {
|
|
||||||
delete localStorage[k];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Cryptpad.alert(Messages.settings_resetTipsDone);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createThumbnails = function (obj) {
|
|
||||||
var $div = $('<div>', {'class': 'thumbnails element'});
|
|
||||||
$('<label>').text(Messages.settings_thumbnails).appendTo($div);
|
|
||||||
|
|
||||||
// Disable
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_disableThumbnailsDescription).appendTo($div);
|
|
||||||
var $label = $('<label>', { 'for': 'disableThumbnails', 'class': 'noTitle' })
|
|
||||||
.text(Messages.settings_disableThumbnailsAction);
|
|
||||||
|
|
||||||
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved});
|
|
||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'});
|
|
||||||
|
|
||||||
var $checkbox = $('<input>', {
|
|
||||||
'type': 'checkbox',
|
|
||||||
id: 'disableThumbnails'
|
|
||||||
}).on('change', function () {
|
|
||||||
$spinner.show();
|
|
||||||
$ok.hide();
|
|
||||||
if (!obj.proxy.settings) { obj.proxy.settings = {}; }
|
|
||||||
if (!obj.proxy.settings.general) { obj.proxy.settings.general = {}; }
|
|
||||||
obj.proxy.settings.general.disableThumbnails = $checkbox.is(':checked') || false;
|
|
||||||
Cryptpad.whenRealtimeSyncs(obj.info.realtime, function () {
|
|
||||||
$spinner.hide();
|
|
||||||
$ok.show();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$checkbox.appendTo($div);
|
|
||||||
$label.appendTo($div);
|
|
||||||
|
|
||||||
$ok.hide().appendTo($div);
|
|
||||||
$spinner.hide().appendTo($div);
|
|
||||||
|
|
||||||
if (obj.proxy.settings && obj.proxy.settings.general
|
|
||||||
&& obj.proxy.settings.general.disableThumbnails) {
|
|
||||||
$checkbox[0].checked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset
|
|
||||||
/*$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_resetThumbnailsDescription).appendTo($div);
|
|
||||||
var $button = $('<button>', {'id': 'resetThumbnails', 'class': 'btn btn-primary'})
|
|
||||||
.text(Messages.settings_resetThumbnailsAction).appendTo($div);
|
|
||||||
|
|
||||||
$button.click(function () {
|
|
||||||
// TODO we need to have access to the sandbox localforage first...
|
|
||||||
Cryptpad.alert(Messages.settings_resetThumbnailsDone);
|
|
||||||
});*/
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createBackupDrive = function (store) {
|
|
||||||
var obj = store.proxy;
|
|
||||||
var $div = $('<div>', {'class': 'backupDrive element'});
|
|
||||||
|
|
||||||
var exportFile = function () {
|
|
||||||
var sjson = JSON.stringify(obj);
|
|
||||||
var name = obj.login_name || obj[USERNAME_KEY] || Messages.anonymous;
|
|
||||||
var suggestion = name + '-' + new Date().toDateString();
|
|
||||||
Cryptpad.prompt(Cryptpad.Messages.exportPrompt,
|
|
||||||
Cryptpad.fixFileName(suggestion) + '.json', function (filename) {
|
|
||||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
|
||||||
var blob = new Blob([sjson], {type: "application/json;charset=utf-8"});
|
|
||||||
saveAs(blob, filename);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var importFile = function (content) {
|
|
||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).appendTo($div);
|
|
||||||
Crypt.put(Cryptpad.getUserHash() || localStorage[Cryptpad.fileHashKey], content, function (e) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
$spinner.remove();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$('<label>', {'for' : 'exportDrive'}).text(Messages.settings_backupCategory).appendTo($div);
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_backupTitle).appendTo($div);
|
|
||||||
/* add an export button */
|
|
||||||
var $export = Cryptpad.createButton('export', true, {}, exportFile);
|
|
||||||
$export.attr('class', 'btn btn-success').text(Messages.settings_backup);
|
|
||||||
$div.append($export);
|
|
||||||
|
|
||||||
/* add an import button */
|
|
||||||
var $import = Cryptpad.createButton('import', true, {}, importFile);
|
|
||||||
$import.attr('class', 'btn btn-success').text(Messages.settings_restore);
|
|
||||||
$div.append($import);
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createResetDrive = function (obj) {
|
|
||||||
var $div = $('<div>', {'class': 'resetDrive element'});
|
|
||||||
$('<label>', {'for' : 'resetDrive'}).text(Messages.settings_resetNewTitle).appendTo($div);
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_reset).appendTo($div);
|
|
||||||
var $button = $('<button>', {'id': 'resetDrive', 'class': 'btn btn-danger'})
|
|
||||||
.text(Messages.settings_resetButton).appendTo($div);
|
|
||||||
|
|
||||||
$button.click(function () {
|
|
||||||
Cryptpad.prompt(Messages.settings_resetPrompt, "", function (val) {
|
|
||||||
if (val !== "I love CryptPad") {
|
|
||||||
Cryptpad.alert(Messages.settings_resetError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
obj.proxy.drive = Cryptpad.getStore().getEmptyObject();
|
|
||||||
Cryptpad.alert(Messages.settings_resetDone);
|
|
||||||
}, undefined, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUserFeedbackToggle = function (obj) {
|
|
||||||
var $div = $('<div>', { 'class': 'userFeedback element'});
|
|
||||||
|
|
||||||
$('<span>', {'class': 'label'}).text(Messages.settings_userFeedbackTitle).appendTo($div);
|
|
||||||
|
|
||||||
var $label = $('<label>', { 'for': 'userFeedback', 'class': 'noTitle' })
|
|
||||||
.text(Messages.settings_userFeedback);
|
|
||||||
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.append(Messages.settings_userFeedbackHint1)
|
|
||||||
.append(Messages.settings_userFeedbackHint2).appendTo($div);
|
|
||||||
|
|
||||||
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved});
|
|
||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'});
|
|
||||||
|
|
||||||
var $checkbox = $('<input>', {
|
|
||||||
'type': 'checkbox',
|
|
||||||
}).on('change', function () {
|
|
||||||
$spinner.show();
|
|
||||||
$ok.hide();
|
|
||||||
obj.proxy.allowUserFeedback = $checkbox.is(':checked') || false;
|
|
||||||
Cryptpad.whenRealtimeSyncs(obj.info.realtime, function () {
|
|
||||||
$spinner.hide();
|
|
||||||
$ok.show();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$checkbox.appendTo($div);
|
|
||||||
$label.appendTo($div);
|
|
||||||
|
|
||||||
$ok.hide().appendTo($div);
|
|
||||||
$spinner.hide().appendTo($div);
|
|
||||||
|
|
||||||
if (obj.proxy.allowUserFeedback) {
|
|
||||||
$checkbox[0].checked = true;
|
|
||||||
}
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createUsageButton = function () {
|
|
||||||
Cryptpad.createUsageBar(function (err, $bar) {
|
|
||||||
if (err) { return void console.error(err); }
|
|
||||||
APP.$usage.html('').append($bar);
|
|
||||||
}, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
var createLogoutEverywhere = function (obj) {
|
|
||||||
var proxy = obj.proxy;
|
|
||||||
var $div = $('<div>', { 'class': 'logoutEverywhere element'});
|
|
||||||
$('<label>', { 'for': 'logoutEverywhere'})
|
|
||||||
.text(Messages.settings_logoutEverywhereTitle).appendTo($div);
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_logoutEverywhere).appendTo($div);
|
|
||||||
var $button = $('<button>', { id: 'logoutEverywhere', 'class': 'btn btn-primary' })
|
|
||||||
.text(Messages.settings_logoutEverywhereButton)
|
|
||||||
.appendTo($div);
|
|
||||||
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved}).hide().appendTo($div);
|
|
||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div);
|
|
||||||
|
|
||||||
$button.click(function () {
|
|
||||||
var realtime = obj.info.realtime;
|
|
||||||
console.log(realtime);
|
|
||||||
|
|
||||||
Cryptpad.confirm(Messages.settings_logoutEverywhereConfirm, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
$spinner.show();
|
|
||||||
$ok.hide();
|
|
||||||
|
|
||||||
var token = Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);
|
|
||||||
localStorage.setItem('loginToken', token);
|
|
||||||
proxy.loginToken = token;
|
|
||||||
|
|
||||||
Cryptpad.whenRealtimeSyncs(realtime, function () {
|
|
||||||
$spinner.hide();
|
|
||||||
$ok.show();
|
|
||||||
window.setTimeout(function () {
|
|
||||||
$ok.fadeOut(1500);
|
|
||||||
}, 2500);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createImportLocalPads = function (obj) {
|
|
||||||
if (!Cryptpad.isLoggedIn()) { return; }
|
|
||||||
var $div = $('<div>', {'class': 'importLocalPads element'});
|
|
||||||
$('<label>', {'for' : 'importLocalPads'}).text(Messages.settings_import).appendTo($div);
|
|
||||||
$('<span>', {'class': 'description'})
|
|
||||||
.text(Messages.settings_importTitle).appendTo($div);
|
|
||||||
var $button = $('<button>', {'id': 'importLocalPads', 'class': 'btn btn-primary'})
|
|
||||||
.text(Messages.settings_import).appendTo($div);
|
|
||||||
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved}).hide().appendTo($div);
|
|
||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div);
|
|
||||||
|
|
||||||
$button.click(function () {
|
|
||||||
Cryptpad.confirm(Messages.settings_importConfirm, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
$spinner.show();
|
|
||||||
$ok.hide();
|
|
||||||
Merge.anonDriveIntoUser(obj, localStorage.FS_hash, function () {
|
|
||||||
$spinner.hide();
|
|
||||||
$ok.show();
|
|
||||||
Cryptpad.alert(Messages.settings_importDone);
|
|
||||||
});
|
|
||||||
}, undefined, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
var createLanguageSelector = function () {
|
|
||||||
var $div = $('<div>', {'class': 'languageSelector element'});
|
|
||||||
$('<label>').text(Messages.language).appendTo($div);
|
|
||||||
var $b = Cryptpad.createLanguageSelector().appendTo($div);
|
|
||||||
$b.find('button').addClass('btn btn-secondary');
|
|
||||||
return $div;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var hideCategories = function () {
|
|
||||||
APP.$rightside.find('> div').hide();
|
|
||||||
};
|
|
||||||
var showCategories = function (cat) {
|
|
||||||
hideCategories();
|
|
||||||
cat.forEach(function (c) {
|
|
||||||
APP.$rightside.find('.'+c).show();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var createLeftside = function () {
|
|
||||||
var $categories = $('<div>', {'class': 'categories'}).appendTo(APP.$leftside);
|
|
||||||
APP.$usage = $('<div>', {'class': 'usage'}).appendTo(APP.$leftside);
|
|
||||||
var active = 'account';
|
|
||||||
Object.keys(categories).forEach(function (key) {
|
|
||||||
var $category = $('<div>', {'class': 'category'}).appendTo($categories);
|
|
||||||
if (key === 'account') { $category.append($('<span>', {'class': 'fa fa-user-o'})); }
|
|
||||||
if (key === 'drive') { $category.append($('<span>', {'class': 'fa fa-hdd-o'})); }
|
|
||||||
if (key === 'code') { $category.append($('<span>', {'class': 'fa fa-file-code-o' })); }
|
|
||||||
|
|
||||||
if (key === active) {
|
|
||||||
$category.addClass('active');
|
|
||||||
}
|
|
||||||
|
|
||||||
$category.click(function () {
|
|
||||||
active = key;
|
|
||||||
$categories.find('.active').removeClass('active');
|
|
||||||
$category.addClass('active');
|
|
||||||
showCategories(categories[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
$category.append(Messages['settings_cat_'+key]);
|
|
||||||
});
|
|
||||||
showCategories(categories[active]);
|
|
||||||
};
|
|
||||||
|
|
||||||
var createToolbar = function () {
|
|
||||||
var displayed = ['useradmin', 'newpad', 'limit', 'upgrade', 'pageTitle'];
|
|
||||||
var configTb = {
|
|
||||||
displayed: displayed,
|
|
||||||
ifrw: window,
|
|
||||||
common: Cryptpad,
|
|
||||||
$container: APP.$toolbar,
|
|
||||||
pageTitle: Messages.settings_title
|
|
||||||
};
|
|
||||||
var toolbar = APP.toolbar = Toolbar.create(configTb);
|
|
||||||
toolbar.$rightside.html(''); // Remove the drawer if we don't use it to hide the toolbar
|
|
||||||
};
|
|
||||||
|
|
||||||
var andThen = function (obj) {
|
|
||||||
APP.$leftside = $('<div>', {id: 'leftSide'}).appendTo(APP.$container);
|
|
||||||
var $rightside = APP.$rightside = $('<div>', {id: 'rightSide'}).appendTo(APP.$container);
|
|
||||||
|
|
||||||
createToolbar();
|
|
||||||
|
|
||||||
//$rightside.append(createTitle());
|
|
||||||
$rightside.append(createInfoBlock(obj));
|
|
||||||
$rightside.append(createDisplayNameInput(obj));
|
|
||||||
$rightside.append(createLanguageSelector());
|
|
||||||
$rightside.append(createIndentUnitSelector(obj));
|
|
||||||
$rightside.append(createIndentTypeSelector(obj));
|
|
||||||
|
|
||||||
if (Cryptpad.isLoggedIn()) {
|
|
||||||
$rightside.append(createLogoutEverywhere(obj));
|
|
||||||
}
|
|
||||||
$rightside.append(createResetTips());
|
|
||||||
$rightside.append(createThumbnails(obj));
|
|
||||||
$rightside.append(createBackupDrive(obj));
|
|
||||||
$rightside.append(createImportLocalPads(obj));
|
|
||||||
$rightside.append(createResetDrive(obj));
|
|
||||||
$rightside.append(createUserFeedbackToggle(obj));
|
|
||||||
|
|
||||||
obj.proxy.on('change', [], refresh);
|
|
||||||
obj.proxy.on('remove', [], refresh);
|
|
||||||
Cryptpad.onDisplayNameChanged(refresh);
|
|
||||||
|
|
||||||
createLeftside();
|
|
||||||
createUsageButton();
|
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
APP.$container = $('#container');
|
|
||||||
APP.$toolbar = $('#toolbar');
|
|
||||||
|
|
||||||
Cryptpad.ready(function () {
|
|
||||||
//if (!Cryptpad.getUserHash()) { return redirectToMain(); }
|
|
||||||
|
|
||||||
var storeObj = Cryptpad.getStore().getProxy && Cryptpad.getStore().getProxy().proxy
|
|
||||||
? Cryptpad.getStore().getProxy() : undefined;
|
|
||||||
|
|
||||||
andThen(storeObj);
|
|
||||||
Cryptpad.reportAppUsage();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('storage', function (e) {
|
|
||||||
if (e.key !== Cryptpad.userHashKey) { return; }
|
|
||||||
var o = e.oldValue;
|
|
||||||
var n = e.newValue;
|
|
||||||
window.location.reload();
|
|
||||||
if (o && !n) { // disconnect
|
|
||||||
//redirectToMain();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
@import '/customize/src/less/variables.less';
|
|
||||||
@import '/customize/src/less/mixins.less';
|
|
||||||
@import '/customize/src/less/sidebar-layout.less';
|
|
||||||
|
|
||||||
.cp {
|
|
||||||
#container {
|
|
||||||
#rightSide {
|
|
||||||
.userFeedback, .thumbnails {
|
|
||||||
input[type="checkbox"] {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.languageSelector {
|
|
||||||
button.btn {
|
|
||||||
width: @button-width;
|
|
||||||
background-color: @button-alt-bg;
|
|
||||||
border-color: #adadad;
|
|
||||||
color: black;
|
|
||||||
&:hover {
|
|
||||||
background-color: darken(@button-alt-bg, 15%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.inputBlock {
|
|
||||||
input {
|
|
||||||
border-top-right-radius: 0.25em;
|
|
||||||
border-bottom-right-radius: 0.25em;
|
|
||||||
padding: 5px;
|
|
||||||
padding-left: 15px;
|
|
||||||
&[type="number"] {
|
|
||||||
border-right: 1px solid #adadad;
|
|
||||||
}
|
|
||||||
&[type="checkbox"] {
|
|
||||||
margin-right: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.infoBlock {
|
|
||||||
[type="text"] {
|
|
||||||
width: @button-width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.backupDrive {
|
|
||||||
button {
|
|
||||||
span.fa {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,10 +26,6 @@
|
|||||||
height: 28px;
|
height: 28px;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
#cke_1_top .cp-toolbar {
|
|
||||||
padding: 0;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.cke_wysiwyg_frame {
|
.cke_wysiwyg_frame {
|
||||||
min-width: 60%;
|
min-width: 60%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
'/common/cryptget.js',
|
'/common/cryptget.js',
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
@@ -13,9 +12,10 @@ define([
|
|||||||
'/poll/render.js',
|
'/poll/render.js',
|
||||||
'/common/diffMarked.js',
|
'/common/diffMarked.js',
|
||||||
'/common/sframe-common-codemirror.js',
|
'/common/sframe-common-codemirror.js',
|
||||||
'/common/sframe-common-interface.js',
|
|
||||||
'/common/common-thumbnail.js',
|
'/common/common-thumbnail.js',
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/customize/messages.js',
|
||||||
'cm/lib/codemirror',
|
'cm/lib/codemirror',
|
||||||
|
|
||||||
'cm/addon/display/placeholder',
|
'cm/addon/display/placeholder',
|
||||||
@@ -30,7 +30,6 @@ define([
|
|||||||
], function (
|
], function (
|
||||||
$,
|
$,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Cryptpad,
|
|
||||||
Util,
|
Util,
|
||||||
Cryptget,
|
Cryptget,
|
||||||
nThen,
|
nThen,
|
||||||
@@ -42,12 +41,12 @@ define([
|
|||||||
Renderer,
|
Renderer,
|
||||||
DiffMd,
|
DiffMd,
|
||||||
SframeCM,
|
SframeCM,
|
||||||
SFUI,
|
|
||||||
Thumb,
|
Thumb,
|
||||||
ChainPad,
|
ChainPad,
|
||||||
|
UI,
|
||||||
|
Messages,
|
||||||
CMeditor)
|
CMeditor)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
var saveAs = window.saveAs;
|
var saveAs = window.saveAs;
|
||||||
|
|
||||||
var APP = window.APP = {
|
var APP = window.APP = {
|
||||||
@@ -56,10 +55,9 @@ define([
|
|||||||
col: []
|
col: []
|
||||||
},
|
},
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
mobile: function () { return $('body').width() <= 600; } // Menu and content area are not inline-block anymore for mobiles
|
mobile: function () { return $('body').width() <= 600; } // Menu and content area are not inline-block anymore for mobiles
|
||||||
};
|
};
|
||||||
var Render = Renderer(Cryptpad, APP);
|
var Render = Renderer(APP);
|
||||||
|
|
||||||
var debug = $.noop; //console.log;
|
var debug = $.noop; //console.log;
|
||||||
|
|
||||||
@@ -117,8 +115,8 @@ define([
|
|||||||
var exportFile = function () {
|
var exportFile = function () {
|
||||||
var csv = getCSV();
|
var csv = getCSV();
|
||||||
var suggestion = Title.suggestTitle(Title.defaultTitle);
|
var suggestion = Title.suggestTitle(Title.defaultTitle);
|
||||||
Cryptpad.prompt(Messages.exportPrompt,
|
UI.prompt(Messages.exportPrompt,
|
||||||
Cryptpad.fixFileName(suggestion) + '.csv', function (filename) {
|
Util.fixFileName(suggestion) + '.csv', function (filename) {
|
||||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
if (!(typeof(filename) === 'string' && filename)) { return; }
|
||||||
var blob = new Blob([csv], {type: "application/csv;charset=utf-8"});
|
var blob = new Blob([csv], {type: "application/csv;charset=utf-8"});
|
||||||
saveAs(blob, filename);
|
saveAs(blob, filename);
|
||||||
@@ -331,7 +329,7 @@ define([
|
|||||||
|
|
||||||
/* Any time the realtime object changes, call this function */
|
/* Any time the realtime object changes, call this function */
|
||||||
var change = function (o, n, path, throttle, cb) {
|
var change = function (o, n, path, throttle, cb) {
|
||||||
if (path && !Cryptpad.isArray(path)) {
|
if (path && !Array.isArray(path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (path && path.join) {
|
if (path && path.join) {
|
||||||
@@ -494,7 +492,7 @@ define([
|
|||||||
var isLocked = span.className && span.className.split(' ').indexOf('fa-lock') !== -1;
|
var isLocked = span.className && span.className.split(' ').indexOf('fa-lock') !== -1;
|
||||||
if (type === 'row') {
|
if (type === 'row') {
|
||||||
if (isRemove) {
|
if (isRemove) {
|
||||||
Cryptpad.confirm(Messages.poll_removeOption, function (res) {
|
UI.confirm(Messages.poll_removeOption, function (res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
Render.removeRow(APP.proxy, id, function () {
|
Render.removeRow(APP.proxy, id, function () {
|
||||||
change();
|
change();
|
||||||
@@ -507,7 +505,7 @@ define([
|
|||||||
}
|
}
|
||||||
} else if (type === 'col') {
|
} else if (type === 'col') {
|
||||||
if (isRemove) {
|
if (isRemove) {
|
||||||
Cryptpad.confirm(Messages.poll_removeUser, function (res) {
|
UI.confirm(Messages.poll_removeUser, function (res) {
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
Render.removeColumn(APP.proxy, id, function () {
|
Render.removeColumn(APP.proxy, id, function () {
|
||||||
change();
|
change();
|
||||||
@@ -883,7 +881,7 @@ define([
|
|||||||
(proxy.metadata && typeof(proxy.metadata.type) !== 'undefined' &&
|
(proxy.metadata && typeof(proxy.metadata.type) !== 'undefined' &&
|
||||||
proxy.metadata.type !== 'poll')) {
|
proxy.metadata.type !== 'poll')) {
|
||||||
var errorText = Messages.typeError;
|
var errorText = Messages.typeError;
|
||||||
Cryptpad.errorLoadingScreen(errorText);
|
UI.errorLoadingScreen(errorText);
|
||||||
throw new Error(errorText);
|
throw new Error(errorText);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1042,7 +1040,7 @@ define([
|
|||||||
publish(true);
|
publish(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
common.openTemplatePicker();
|
common.openTemplatePicker();
|
||||||
}
|
}
|
||||||
@@ -1050,12 +1048,12 @@ define([
|
|||||||
|
|
||||||
var onDisconnect = function () {
|
var onDisconnect = function () {
|
||||||
setEditable(false);
|
setEditable(false);
|
||||||
Cryptpad.alert(Messages.common_connectionLost, undefined, true);
|
UI.alert(Messages.common_connectionLost, undefined, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onReconnect = function () {
|
var onReconnect = function () {
|
||||||
setEditable(true);
|
setEditable(true);
|
||||||
Cryptpad.findOKButton().click();
|
UI.findOKButton().click();
|
||||||
};
|
};
|
||||||
|
|
||||||
var getHeadingText = function () {
|
var getHeadingText = function () {
|
||||||
@@ -1081,7 +1079,6 @@ define([
|
|||||||
metadataMgr: metadataMgr,
|
metadataMgr: metadataMgr,
|
||||||
readOnly: APP.readOnly,
|
readOnly: APP.readOnly,
|
||||||
realtime: info.realtime,
|
realtime: info.realtime,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: APP.$bar,
|
$container: APP.$bar,
|
||||||
$contentContainer: APP.$content
|
$contentContainer: APP.$content
|
||||||
@@ -1162,7 +1159,7 @@ define([
|
|||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(function () {
|
$(waitFor(function () {
|
||||||
Cryptpad.addLoadingScreen();
|
UI.addLoadingScreen();
|
||||||
var $div = $('<div>').append(Pages['/poll/']());
|
var $div = $('<div>').append(Pages['/poll/']());
|
||||||
$('body').append($div.html());
|
$('body').append($div.html());
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
define([
|
define([
|
||||||
//'/common/cryptpad-common.js',
|
|
||||||
'jquery',
|
'jquery',
|
||||||
'/bower_components/hyperjson/hyperjson.js',
|
'/bower_components/hyperjson/hyperjson.js',
|
||||||
'/common/text-cursor.js',
|
'/common/text-cursor.js',
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'/bower_components/diff-dom/diffDOM.js'
|
'/bower_components/diff-dom/diffDOM.js'
|
||||||
], function ($, Hyperjson, TextCursor, ChainPad) {
|
], function ($, Hyperjson, TextCursor, ChainPad, Util, Messages) {
|
||||||
var DiffDOM = window.diffDOM;
|
var DiffDOM = window.diffDOM;
|
||||||
|
|
||||||
var Example = {
|
var Example = {
|
||||||
@@ -33,7 +34,7 @@ by maintaining indexes in rowsOrder and colsOrder
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var Renderer = function (Cryptpad, APP) {
|
var Renderer = function (APP) {
|
||||||
|
|
||||||
var Render = {
|
var Render = {
|
||||||
Example: Example
|
Example: Example
|
||||||
@@ -66,15 +67,15 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var getColumnValue = Render.getColumnValue = function (obj, colId) {
|
var getColumnValue = Render.getColumnValue = function (obj, colId) {
|
||||||
return Cryptpad.find(obj, ['content', 'cols'].concat([colId]));
|
return Util.find(obj, ['content', 'cols'].concat([colId]));
|
||||||
};
|
};
|
||||||
|
|
||||||
var getRowValue = Render.getRowValue = function (obj, rowId) {
|
var getRowValue = Render.getRowValue = function (obj, rowId) {
|
||||||
return Cryptpad.find(obj, ['content', 'rows'].concat([rowId]));
|
return Util.find(obj, ['content', 'rows'].concat([rowId]));
|
||||||
};
|
};
|
||||||
|
|
||||||
var getCellValue = Render.getCellValue = function (obj, cellId) {
|
var getCellValue = Render.getCellValue = function (obj, cellId) {
|
||||||
var value = Cryptpad.find(obj, ['content', 'cells'].concat([cellId]));
|
var value = Util.find(obj, ['content', 'cells'].concat([cellId]));
|
||||||
if (typeof value === 'boolean') {
|
if (typeof value === 'boolean') {
|
||||||
return (value === true ? 1 : 0);
|
return (value === true ? 1 : 0);
|
||||||
} else {
|
} else {
|
||||||
@@ -83,25 +84,25 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var setRowValue = Render.setRowValue = function (obj, rowId, value) {
|
var setRowValue = Render.setRowValue = function (obj, rowId, value) {
|
||||||
var parent = Cryptpad.find(obj, ['content', 'rows']);
|
var parent = Util.find(obj, ['content', 'rows']);
|
||||||
if (typeof(parent) === 'object') { return (parent[rowId] = value); }
|
if (typeof(parent) === 'object') { return (parent[rowId] = value); }
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
var setColumnValue = Render.setColumnValue = function (obj, colId, value) {
|
var setColumnValue = Render.setColumnValue = function (obj, colId, value) {
|
||||||
var parent = Cryptpad.find(obj, ['content', 'cols']);
|
var parent = Util.find(obj, ['content', 'cols']);
|
||||||
if (typeof(parent) === 'object') { return (parent[colId] = value); }
|
if (typeof(parent) === 'object') { return (parent[colId] = value); }
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
var setCellValue = Render.setCellValue = function (obj, cellId, value) {
|
var setCellValue = Render.setCellValue = function (obj, cellId, value) {
|
||||||
var parent = Cryptpad.find(obj, ['content', 'cells']);
|
var parent = Util.find(obj, ['content', 'cells']);
|
||||||
if (typeof(parent) === 'object') { return (parent[cellId] = value); }
|
if (typeof(parent) === 'object') { return (parent[cellId] = value); }
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
Render.createColumn = function (obj, cb, id, value) {
|
Render.createColumn = function (obj, cb, id, value) {
|
||||||
var order = Cryptpad.find(obj, ['content', 'colsOrder']);
|
var order = Util.find(obj, ['content', 'colsOrder']);
|
||||||
if (!order) { throw new Error("Uninitialized realtime object!"); }
|
if (!order) { throw new Error("Uninitialized realtime object!"); }
|
||||||
id = id || coluid();
|
id = id || coluid();
|
||||||
value = value || "";
|
value = value || "";
|
||||||
@@ -111,8 +112,8 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Render.removeColumn = function (obj, id, cb) {
|
Render.removeColumn = function (obj, id, cb) {
|
||||||
var order = Cryptpad.find(obj, ['content', 'colsOrder']);
|
var order = Util.find(obj, ['content', 'colsOrder']);
|
||||||
var parent = Cryptpad.find(obj, ['content', 'cols']);
|
var parent = Util.find(obj, ['content', 'cols']);
|
||||||
|
|
||||||
if (!(order && parent)) { throw new Error("Uninitialized realtime object!"); }
|
if (!(order && parent)) { throw new Error("Uninitialized realtime object!"); }
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Render.createRow = function (obj, cb, id, value) {
|
Render.createRow = function (obj, cb, id, value) {
|
||||||
var order = Cryptpad.find(obj, ['content', 'rowsOrder']);
|
var order = Util.find(obj, ['content', 'rowsOrder']);
|
||||||
if (!order) { throw new Error("Uninitialized realtime object!"); }
|
if (!order) { throw new Error("Uninitialized realtime object!"); }
|
||||||
id = id || rowuid();
|
id = id || rowuid();
|
||||||
value = value || "";
|
value = value || "";
|
||||||
@@ -146,8 +147,8 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Render.removeRow = function (obj, id, cb) {
|
Render.removeRow = function (obj, id, cb) {
|
||||||
var order = Cryptpad.find(obj, ['content', 'rowsOrder']);
|
var order = Util.find(obj, ['content', 'rowsOrder']);
|
||||||
var parent = Cryptpad.find(obj, ['content', 'rows']);
|
var parent = Util.find(obj, ['content', 'rows']);
|
||||||
|
|
||||||
if (!(order && parent)) { throw new Error("Uninitialized realtime object!"); }
|
if (!(order && parent)) { throw new Error("Uninitialized realtime object!"); }
|
||||||
|
|
||||||
@@ -187,15 +188,15 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var getRowIds = Render.getRowIds = function (obj) {
|
var getRowIds = Render.getRowIds = function (obj) {
|
||||||
return Cryptpad.find(obj, ['content', 'rowsOrder']);
|
return Util.find(obj, ['content', 'rowsOrder']);
|
||||||
};
|
};
|
||||||
|
|
||||||
var getColIds = Render.getColIds = function (obj) {
|
var getColIds = Render.getColIds = function (obj) {
|
||||||
return Cryptpad.find(obj, ['content', 'colsOrder']);
|
return Util.find(obj, ['content', 'colsOrder']);
|
||||||
};
|
};
|
||||||
|
|
||||||
var getCells = Render.getCells = function (obj) {
|
var getCells = Render.getCells = function (obj) {
|
||||||
return Cryptpad.find(obj, ['content', 'cells']);
|
return Util.find(obj, ['content', 'cells']);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* cellMatrix takes a proxy object, and optionally an alternate ordering
|
/* cellMatrix takes a proxy object, and optionally an alternate ordering
|
||||||
@@ -221,13 +222,13 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
'data-rt-id': col,
|
'data-rt-id': col,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
value: getColumnValue(obj, col) || "",
|
value: getColumnValue(obj, col) || "",
|
||||||
title: getColumnValue(obj, col) || Cryptpad.Messages.anonymous,
|
title: getColumnValue(obj, col) || Messages.anonymous,
|
||||||
placeholder: Cryptpad.Messages.anonymous,
|
placeholder: Messages.anonymous,
|
||||||
disabled: 'disabled'
|
disabled: 'disabled'
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
})).concat([{
|
})).concat([{
|
||||||
content: Cryptpad.Messages.poll_total
|
content: Messages.poll_total
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
if (i === rows.length) {
|
if (i === rows.length) {
|
||||||
@@ -241,9 +242,9 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
return [{
|
return [{
|
||||||
'data-rt-id': row,
|
'data-rt-id': row,
|
||||||
value: getRowValue(obj, row) || '',
|
value: getRowValue(obj, row) || '',
|
||||||
title: getRowValue(obj, row) || Cryptpad.Messages.poll_optionPlaceholder,
|
title: getRowValue(obj, row) || Messages.poll_optionPlaceholder,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
placeholder: Cryptpad.Messages.poll_optionPlaceholder,
|
placeholder: Messages.poll_optionPlaceholder,
|
||||||
disabled: 'disabled',
|
disabled: 'disabled',
|
||||||
}].concat(cols.map(function (col) {
|
}].concat(cols.map(function (col) {
|
||||||
var id = [col, rows[i-1]].join('_');
|
var id = [col, rows[i-1]].join('_');
|
||||||
@@ -271,7 +272,7 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
var makeRemoveElement = Render.makeRemoveElement = function (id) {
|
var makeRemoveElement = Render.makeRemoveElement = function (id) {
|
||||||
return ['SPAN', {
|
return ['SPAN', {
|
||||||
'data-rt-id': id,
|
'data-rt-id': id,
|
||||||
'title': Cryptpad.Messages.poll_remove,
|
'title': Messages.poll_remove,
|
||||||
class: 'cp-app-poll-table-remove',
|
class: 'cp-app-poll-table-remove',
|
||||||
}, ['✖']];
|
}, ['✖']];
|
||||||
};
|
};
|
||||||
@@ -279,7 +280,7 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
var makeEditElement = Render.makeEditElement = function (id) {
|
var makeEditElement = Render.makeEditElement = function (id) {
|
||||||
return ['SPAN', {
|
return ['SPAN', {
|
||||||
'data-rt-id': id,
|
'data-rt-id': id,
|
||||||
'title': Cryptpad.Messages.poll_edit,
|
'title': Messages.poll_edit,
|
||||||
class: 'cp-app-poll-table-edit',
|
class: 'cp-app-poll-table-edit',
|
||||||
}, ['✐']];
|
}, ['✐']];
|
||||||
};
|
};
|
||||||
@@ -287,7 +288,7 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
var makeLockElement = Render.makeLockElement = function (id) {
|
var makeLockElement = Render.makeLockElement = function (id) {
|
||||||
return ['SPAN', {
|
return ['SPAN', {
|
||||||
'data-rt-id': id,
|
'data-rt-id': id,
|
||||||
'title': Cryptpad.Messages.poll_locked,
|
'title': Messages.poll_locked,
|
||||||
class: 'cp-app-poll-table-lock fa fa-lock',
|
class: 'cp-app-poll-table-lock fa fa-lock',
|
||||||
}, []];
|
}, []];
|
||||||
};
|
};
|
||||||
@@ -295,7 +296,7 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
var makeBookmarkElement = Render.makeBookmarkElement = function (id) {
|
var makeBookmarkElement = Render.makeBookmarkElement = function (id) {
|
||||||
return ['SPAN', {
|
return ['SPAN', {
|
||||||
'data-rt-id': id,
|
'data-rt-id': id,
|
||||||
'title': Cryptpad.Messages.poll_bookmark_col,
|
'title': Messages.poll_bookmark_col,
|
||||||
'style': 'visibility: hidden;',
|
'style': 'visibility: hidden;',
|
||||||
class: 'cp-app-poll-table-bookmark fa fa-thumb-tack',
|
class: 'cp-app-poll-table-bookmark fa fa-thumb-tack',
|
||||||
}, []];
|
}, []];
|
||||||
@@ -385,13 +386,13 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var diffIsInput = Render.diffIsInput = function (info) {
|
var diffIsInput = Render.diffIsInput = function (info) {
|
||||||
var nodeName = Cryptpad.find(info, ['node', 'nodeName']);
|
var nodeName = Util.find(info, ['node', 'nodeName']);
|
||||||
if (nodeName !== 'INPUT') { return; }
|
if (nodeName !== 'INPUT') { return; }
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var getInputType = Render.getInputType = function (info) {
|
var getInputType = Render.getInputType = function (info) {
|
||||||
return Cryptpad.find(info, ['node', 'type']);
|
return Util.find(info, ['node', 'type']);
|
||||||
};
|
};
|
||||||
|
|
||||||
var preserveCursor = Render.preserveCursor = function (info) {
|
var preserveCursor = Render.preserveCursor = function (info) {
|
||||||
@@ -426,6 +427,10 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
var diffOptions = {
|
var diffOptions = {
|
||||||
preDiffApply: function (info) {
|
preDiffApply: function (info) {
|
||||||
if (!diffIsInput(info)) { return; }
|
if (!diffIsInput(info)) { return; }
|
||||||
|
if (info.diff.action === "removeAttribute" &&
|
||||||
|
(info.diff.name === "aria-describedby" || info.diff.name === "data-original-title")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (getInputType(info)) {
|
switch (getInputType(info)) {
|
||||||
case 'number':
|
case 'number':
|
||||||
//console.log('checkbox');
|
//console.log('checkbox');
|
||||||
@@ -459,14 +464,14 @@ var Renderer = function (Cryptpad, APP) {
|
|||||||
// Enable input for the userid column
|
// Enable input for the userid column
|
||||||
APP.enableColumn(userid, table);
|
APP.enableColumn(userid, table);
|
||||||
$(table).find('input[disabled="disabled"][data-rt-id^="' + userid + '"]')
|
$(table).find('input[disabled="disabled"][data-rt-id^="' + userid + '"]')
|
||||||
.attr('placeholder', Cryptpad.Messages.poll_userPlaceholder);
|
.attr('placeholder', Messages.poll_userPlaceholder);
|
||||||
$(table).find('.cp-app-poll-table-lock[data-rt-id="' + userid + '"]').remove();
|
$(table).find('.cp-app-poll-table-lock[data-rt-id="' + userid + '"]').remove();
|
||||||
$(table).find('[data-rt-id^="' + userid + '"]').closest('td')
|
$(table).find('[data-rt-id^="' + userid + '"]').closest('td')
|
||||||
.addClass("cp-app-poll-table-own");
|
.addClass("cp-app-poll-table-own");
|
||||||
$(table).find('.cp-app-poll-table-bookmark[data-rt-id="' + userid + '"]')
|
$(table).find('.cp-app-poll-table-bookmark[data-rt-id="' + userid + '"]')
|
||||||
.css('visibility', '')
|
.css('visibility', '')
|
||||||
.addClass('cp-app-poll-table-bookmark-full')
|
.addClass('cp-app-poll-table-bookmark-full')
|
||||||
.attr('title', Cryptpad.Messages.poll_bookmarked_col);
|
.attr('title', Messages.poll_bookmarked_col);
|
||||||
};
|
};
|
||||||
var styleUncommittedColumn = function (table) {
|
var styleUncommittedColumn = function (table) {
|
||||||
APP.uncommitted.content.colsOrder.forEach(function(id) {
|
APP.uncommitted.content.colsOrder.forEach(function(id) {
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ define([
|
|||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/sframe-chainpad-listmap.js',
|
'/common/sframe-chainpad-listmap.js',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/customize/messages.js',
|
||||||
'/bower_components/marked/marked.min.js',
|
'/bower_components/marked/marked.min.js',
|
||||||
'cm/lib/codemirror',
|
'cm/lib/codemirror',
|
||||||
|
|
||||||
'cm/mode/markdown/markdown',
|
'cm/mode/markdown/markdown',
|
||||||
|
|
||||||
'css!/bower_components/codemirror/lib/codemirror.css',
|
'css!/bower_components/codemirror/lib/codemirror.css',
|
||||||
@@ -21,21 +25,19 @@ define([
|
|||||||
Crypto,
|
Crypto,
|
||||||
Listmap,
|
Listmap,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
|
Util,
|
||||||
|
UI,
|
||||||
|
Realtime,
|
||||||
|
Messages,
|
||||||
Marked,
|
Marked,
|
||||||
CodeMirror
|
CodeMirror
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
var APP = window.APP = {
|
var APP = window.APP = {
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
_onRefresh: []
|
_onRefresh: []
|
||||||
};
|
};
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Decryption event for avatar mediatag (TODO not needed anymore?)
|
// Decryption event for avatar mediatag (TODO not needed anymore?)
|
||||||
$(window.document).on('decryption', function (e) {
|
$(window.document).on('decryption', function (e) {
|
||||||
@@ -44,7 +46,7 @@ define([
|
|||||||
})
|
})
|
||||||
.on('decryptionError', function (e) {
|
.on('decryptionError', function (e) {
|
||||||
var error = e.originalEvent;
|
var error = e.originalEvent;
|
||||||
Cryptpad.alert(error.message);
|
UI.alert(error.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(window).click(function () {
|
$(window).click(function () {
|
||||||
@@ -114,7 +116,7 @@ define([
|
|||||||
setValue(newVal, function (err) {
|
setValue(newVal, function (err) {
|
||||||
if (err) { return void console.error(err); }
|
if (err) { return void console.error(err); }
|
||||||
lastVal = newVal;
|
lastVal = newVal;
|
||||||
Cryptpad.log(Messages._getKey('profile_fieldSaved', [newVal || fallbackValue]));
|
UI.log(Messages._getKey('profile_fieldSaved', [newVal || fallbackValue]));
|
||||||
editing = false;
|
editing = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -135,16 +137,16 @@ define([
|
|||||||
|
|
||||||
/* jshint ignore:start */
|
/* jshint ignore:start */
|
||||||
var isFriend = function (proxy, edKey) {
|
var isFriend = function (proxy, edKey) {
|
||||||
var friends = Cryptpad.find(proxy, ['friends']);
|
var friends = Util.find(proxy, ['friends']);
|
||||||
return typeof(edKey) === 'string' && friends && (edKey in friends);
|
return typeof(edKey) === 'string' && friends && (edKey in friends);
|
||||||
};
|
};
|
||||||
|
|
||||||
var addCreateInviteLinkButton = function ($container) {
|
var addCreateInviteLinkButton = function ($container) {
|
||||||
return;
|
return;
|
||||||
var obj = APP.lm.proxy;
|
/*var obj = APP.lm.proxy;
|
||||||
|
|
||||||
var proxy = Cryptpad.getProxy();
|
var proxy = Cryptpad.getProxy();
|
||||||
var userViewHash = Cryptpad.find(proxy, ['profile', 'view']);
|
var userViewHash = Util.find(proxy, ['profile', 'view']);
|
||||||
|
|
||||||
var edKey = obj.edKey;
|
var edKey = obj.edKey;
|
||||||
var curveKey = obj.curveKey;
|
var curveKey = obj.curveKey;
|
||||||
@@ -158,7 +160,7 @@ define([
|
|||||||
|
|
||||||
var unsafeName = obj.name || '';
|
var unsafeName = obj.name || '';
|
||||||
console.log(unsafeName);
|
console.log(unsafeName);
|
||||||
var name = Cryptpad.fixHTML(unsafeName) || Messages.anonymous;
|
var name = Util.fixHTML(unsafeName) || Messages.anonymous;
|
||||||
console.log(name);
|
console.log(name);
|
||||||
|
|
||||||
console.log("Creating invite button");
|
console.log("Creating invite button");
|
||||||
@@ -169,17 +171,17 @@ define([
|
|||||||
.addClass('btn btn-success')
|
.addClass('btn btn-success')
|
||||||
.text(Messages.profile_inviteButton)
|
.text(Messages.profile_inviteButton)
|
||||||
.click(function () {
|
.click(function () {
|
||||||
Cryptpad.confirm(Messages._getKey('profile_inviteExplanation', [name]), function (yes) {
|
UI.confirm(Messages._getKey('profile_inviteExplanation', [name]), function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
console.log(obj.curveKey);
|
console.log(obj.curveKey);
|
||||||
Cryptpad.alert("TODO");
|
UI.alert("TODO");
|
||||||
// TODO create a listmap object using your curve keys
|
// TODO create a listmap object using your curve keys
|
||||||
// TODO fill the listmap object with your invite data
|
// TODO fill the listmap object with your invite data
|
||||||
// TODO generate link to invite object
|
// TODO generate link to invite object
|
||||||
// TODO copy invite link to clipboard
|
// TODO copy invite link to clipboard
|
||||||
}, null, true);
|
}, null, true);
|
||||||
})
|
})
|
||||||
.appendTo($container);
|
.appendTo($container);*/
|
||||||
};
|
};
|
||||||
/* jshint ignore:end */
|
/* jshint ignore:end */
|
||||||
|
|
||||||
@@ -221,7 +223,7 @@ define([
|
|||||||
}
|
}
|
||||||
var setValue = function (value, cb) {
|
var setValue = function (value, cb) {
|
||||||
APP.lm.proxy.name = value;
|
APP.lm.proxy.name = value;
|
||||||
Cryptpad.whenRealtimeSyncs(APP.lm.realtime, cb);
|
Realtime.whenRealtimeSyncs(APP.lm.realtime, cb);
|
||||||
};
|
};
|
||||||
createEditableInput($block, DISPLAYNAME_ID, placeholder, getValue, setValue, Messages.anonymous);
|
createEditableInput($block, DISPLAYNAME_ID, placeholder, getValue, setValue, Messages.anonymous);
|
||||||
};
|
};
|
||||||
@@ -247,16 +249,21 @@ define([
|
|||||||
}
|
}
|
||||||
var setValue = function (value, cb) {
|
var setValue = function (value, cb) {
|
||||||
APP.lm.proxy.url = value;
|
APP.lm.proxy.url = value;
|
||||||
Cryptpad.whenRealtimeSyncs(APP.lm.realtime, cb);
|
Realtime.whenRealtimeSyncs(APP.lm.realtime, cb);
|
||||||
};
|
};
|
||||||
var placeholder = Messages.profile_urlPlaceholder;
|
var placeholder = Messages.profile_urlPlaceholder;
|
||||||
createEditableInput($block, LINK_ID, placeholder, getValue, setValue);
|
createEditableInput($block, LINK_ID, placeholder, getValue, setValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var allowedMediaTypes = [
|
||||||
|
'image/png',
|
||||||
|
'image/jpeg',
|
||||||
|
'image/jpg',
|
||||||
|
'image/gif',
|
||||||
|
];
|
||||||
var addAvatar = function ($container) {
|
var addAvatar = function ($container) {
|
||||||
var $block = $('<div>', {id: AVATAR_ID}).appendTo($container);
|
var $block = $('<div>', {id: AVATAR_ID}).appendTo($container);
|
||||||
var $span = $('<span>').appendTo($block);
|
var $span = $('<span>').appendTo($block);
|
||||||
var allowedMediaTypes = Cryptpad.avatarAllowedTypes;
|
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
var displayAvatar = function () {
|
var displayAvatar = function () {
|
||||||
$span.html('');
|
$span.html('');
|
||||||
@@ -280,7 +287,7 @@ define([
|
|||||||
$delButton.click(function () {
|
$delButton.click(function () {
|
||||||
var old = common.getMetadataMgr().getUserData().avatar;
|
var old = common.getMetadataMgr().getUserData().avatar;
|
||||||
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
|
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
|
||||||
if (err || err2) { return void Cryptpad.log(err || err2); }
|
if (err || err2) { return void UI.log(err || err2); }
|
||||||
delete APP.lm.proxy.avatar;
|
delete APP.lm.proxy.avatar;
|
||||||
displayAvatar();
|
displayAvatar();
|
||||||
});
|
});
|
||||||
@@ -297,14 +304,14 @@ define([
|
|||||||
var old = common.getMetadataMgr().getUserData().avatar;
|
var old = common.getMetadataMgr().getUserData().avatar;
|
||||||
var todo = function () {
|
var todo = function () {
|
||||||
sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) {
|
sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) {
|
||||||
if (err || err2) { return void Cryptpad.log(err || err2); }
|
if (err || err2) { return void UI.log(err || err2); }
|
||||||
APP.lm.proxy.avatar = data.url;
|
APP.lm.proxy.avatar = data.url;
|
||||||
displayAvatar();
|
displayAvatar();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if (old) {
|
if (old) {
|
||||||
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
|
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
|
||||||
if (err || err2) { return void Cryptpad.log(err || err2); }
|
if (err || err2) { return void UI.log(err || err2); }
|
||||||
todo();
|
todo();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -316,7 +323,7 @@ define([
|
|||||||
var data = {
|
var data = {
|
||||||
FM: APP.FM,
|
FM: APP.FM,
|
||||||
filter: function (file) {
|
filter: function (file) {
|
||||||
var sizeMB = Cryptpad.bytesToMegabytes(file.size);
|
var sizeMB = Util.bytesToMegabytes(file.size);
|
||||||
var type = file.type;
|
var type = file.type;
|
||||||
return sizeMB <= 0.5 && allowedMediaTypes.indexOf(type) !== -1;
|
return sizeMB <= 0.5 && allowedMediaTypes.indexOf(type) !== -1;
|
||||||
},
|
},
|
||||||
@@ -361,7 +368,7 @@ define([
|
|||||||
$spinner.show();
|
$spinner.show();
|
||||||
var val = editor.getValue();
|
var val = editor.getValue();
|
||||||
APP.lm.proxy.description = val;
|
APP.lm.proxy.description = val;
|
||||||
Cryptpad.whenRealtimeSyncs(APP.lm.realtime, function () {
|
Realtime.whenRealtimeSyncs(APP.lm.realtime, function () {
|
||||||
$ok.show();
|
$ok.show();
|
||||||
$spinner.hide();
|
$spinner.hide();
|
||||||
});
|
});
|
||||||
@@ -386,14 +393,14 @@ define([
|
|||||||
var onReady = function () {
|
var onReady = function () {
|
||||||
APP.$container.find('#'+CREATE_ID).remove();
|
APP.$container.find('#'+CREATE_ID).remove();
|
||||||
|
|
||||||
var obj = APP.lm && APP.lm.proxy;
|
/*var obj = APP.lm && APP.lm.proxy;
|
||||||
if (!APP.readOnly) {
|
if (!APP.readOnly) {
|
||||||
var pubKeys = Cryptpad.getPublicKeys();
|
var pubKeys = Cryptpad.getPublicKeys();
|
||||||
if (pubKeys && pubKeys.curve) {
|
if (pubKeys && pubKeys.curve) {
|
||||||
obj.curveKey = pubKeys.curve;
|
obj.curveKey = pubKeys.curve;
|
||||||
obj.edKey = pubKeys.ed;
|
obj.edKey = pubKeys.ed;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (!APP.initialized) {
|
if (!APP.initialized) {
|
||||||
var $header = $('<div>', {id: HEADER_ID}).appendTo(APP.$rightside);
|
var $header = $('<div>', {id: HEADER_ID}).appendTo(APP.$rightside);
|
||||||
@@ -408,14 +415,13 @@ define([
|
|||||||
createLeftside();
|
createLeftside();
|
||||||
}
|
}
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
var createToolbar = function () {
|
var createToolbar = function () {
|
||||||
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
||||||
var configTb = {
|
var configTb = {
|
||||||
displayed: displayed,
|
displayed: displayed,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: APP.$toolbar,
|
$container: APP.$toolbar,
|
||||||
pageTitle: Messages.profileButton,
|
pageTitle: Messages.profileButton,
|
||||||
@@ -426,7 +432,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(Cryptpad.addLoadingScreen));
|
$(waitFor(UI.addLoadingScreen));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
APP.$container = $('#cp-sidebarlayout-container');
|
APP.$container = $('#cp-sidebarlayout-container');
|
||||||
@@ -436,12 +442,6 @@ define([
|
|||||||
sFrameChan = common.getSframeChannel();
|
sFrameChan = common.getSframeChannel();
|
||||||
sFrameChan.onReady(waitFor());
|
sFrameChan.onReady(waitFor());
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
createToolbar();
|
createToolbar();
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
var privateData = metadataMgr.getPrivateData();
|
var privateData = metadataMgr.getPrivateData();
|
||||||
@@ -451,7 +451,7 @@ define([
|
|||||||
|
|
||||||
// If not logged in, you can only view other users's profile
|
// If not logged in, you can only view other users's profile
|
||||||
if (!privateData.readOnly && !common.isLoggedIn()) {
|
if (!privateData.readOnly && !common.isLoggedIn()) {
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
|
|
||||||
var $p = $('<p>', {id: CREATE_ID}).append(Messages.profile_register);
|
var $p = $('<p>', {id: CREATE_ID}).append(Messages.profile_register);
|
||||||
var $a = $('<a>', {
|
var $a = $('<a>', {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ define([
|
|||||||
'/api/config',
|
'/api/config',
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/requireconfig.js',
|
'/common/requireconfig.js',
|
||||||
'/common/sframe-common-outer.js'
|
'/common/sframe-common-outer.js',
|
||||||
], function (nThen, ApiConfig, $, RequireConfig, SFCommonO) {
|
], function (nThen, ApiConfig, $, RequireConfig, SFCommonO) {
|
||||||
var requireConfig = RequireConfig();
|
var requireConfig = RequireConfig();
|
||||||
|
|
||||||
@@ -36,49 +36,50 @@ define([
|
|||||||
};
|
};
|
||||||
window.addEventListener('message', onMsg);
|
window.addEventListener('message', onMsg);
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
var getSecrets = function (Cryptpad) {
|
var getSecrets = function (Cryptpad, Utils) {
|
||||||
|
var Hash = Utils.Hash;
|
||||||
// 1st case: visiting someone else's profile with hash in the URL
|
// 1st case: visiting someone else's profile with hash in the URL
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
return Cryptpad.getSecrets('profile', window.location.hash.slice(1));
|
return Hash.getSecrets('profile', window.location.hash.slice(1));
|
||||||
}
|
}
|
||||||
// 2nd case: visiting our own existing profile
|
// 2nd case: visiting our own existing profile
|
||||||
var obj = Cryptpad.getProxy();
|
var obj = Cryptpad.getProxy();
|
||||||
if (obj.profile && obj.profile.view && obj.profile.edit) {
|
if (obj.profile && obj.profile.view && obj.profile.edit) {
|
||||||
return Cryptpad.getSecrets('profile', obj.profile.edit);
|
return Hash.getSecrets('profile', obj.profile.edit);
|
||||||
}
|
}
|
||||||
// 3rd case: profile creation (create a new random hash, store it later if needed)
|
// 3rd case: profile creation (create a new random hash, store it later if needed)
|
||||||
if (!Cryptpad.isLoggedIn()) { return; }
|
if (!Cryptpad.isLoggedIn()) { return; }
|
||||||
var hash = Cryptpad.createRandomHash();
|
var hash = Hash.createRandomHash();
|
||||||
var secret = Cryptpad.getSecrets('profile', hash);
|
var secret = Hash.getSecrets('profile', hash);
|
||||||
Cryptpad.pinPads([secret.channel], function (e) {
|
Cryptpad.pinPads([secret.channel], function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
if (e === 'E_OVER_LIMIT') {
|
if (e === 'E_OVER_LIMIT') {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
//return void Cryptpad.log(Messages._getKey('profile_error', [e])) // TODO
|
//return void UI.log(Messages._getKey('profile_error', [e])) // TODO
|
||||||
}
|
}
|
||||||
obj.profile = {};
|
obj.profile = {};
|
||||||
obj.profile.edit = Cryptpad.getEditHashFromKeys(secret.channel, secret.keys);
|
obj.profile.edit = Utils.Hash.getEditHashFromKeys(secret.channel, secret.keys);
|
||||||
obj.profile.view = Cryptpad.getViewHashFromKeys(secret.channel, secret.keys);
|
obj.profile.view = Utils.Hash.getViewHashFromKeys(secret.channel, secret.keys);
|
||||||
});
|
});
|
||||||
return secret;
|
return secret;
|
||||||
};
|
};
|
||||||
var addRpc = function (sframeChan, Cryptpad) {
|
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
||||||
// Adding a new avatar from the profile: pin it and store it in the object
|
// Adding a new avatar from the profile: pin it and store it in the object
|
||||||
sframeChan.on('Q_PROFILE_AVATAR_ADD', function (data, cb) {
|
sframeChan.on('Q_PROFILE_AVATAR_ADD', function (data, cb) {
|
||||||
var chanId = Cryptpad.hrefToHexChannelId(data);
|
var chanId = Utils.Hash.hrefToHexChannelId(data);
|
||||||
Cryptpad.pinPads([chanId], function (e) {
|
Cryptpad.pinPads([chanId], function (e) {
|
||||||
if (e) { return void cb(e); }
|
if (e) { return void cb(e); }
|
||||||
Cryptpad.getProxy().profile.avatar = data;
|
Cryptpad.getProxy().profile.avatar = data;
|
||||||
Cryptpad.whenRealtimeSyncs(Cryptpad.getRealtime(), function () {
|
Utils.Realtime.whenRealtimeSyncs(Cryptpad.getRealtime(), function () {
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Removing the avatar from the profile: unpin it
|
// Removing the avatar from the profile: unpin it
|
||||||
sframeChan.on('Q_PROFILE_AVATAR_REMOVE', function (data, cb) {
|
sframeChan.on('Q_PROFILE_AVATAR_REMOVE', function (data, cb) {
|
||||||
var chanId = Cryptpad.hrefToHexChannelId(data);
|
var chanId = Utils.Hash.hrefToHexChannelId(data);
|
||||||
Cryptpad.unpinPads([chanId], function (e) {
|
Cryptpad.unpinPads([chanId], function (e) {
|
||||||
delete Cryptpad.getProxy().profile.avatar;
|
delete Cryptpad.getProxy().profile.avatar;
|
||||||
cb(e);
|
cb(e);
|
||||||
|
|||||||
@@ -4,32 +4,18 @@ define([
|
|||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/common/test.js',
|
'/common/test.js',
|
||||||
'/common/credential.js', // preloaded for login.js
|
'/common/credential.js', // preloaded for login.js
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
], function ($, Login, Cryptpad, Test, Cred) {
|
], function ($, Login, Cryptpad, Test, Cred, UI, Util, Realtime, Constants) {
|
||||||
var Messages = Cryptpad.Messages;
|
var Messages = Cryptpad.Messages;
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
var $main = $('#mainBlock');
|
var $main = $('#mainBlock');
|
||||||
|
|
||||||
// Language selector
|
|
||||||
var $sel = $('#language-selector');
|
|
||||||
Cryptpad.createLanguageSelector(undefined, $sel);
|
|
||||||
$sel.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
$sel.show();
|
|
||||||
|
|
||||||
// User admin menu
|
|
||||||
var $userMenu = $('#user-menu');
|
|
||||||
var userMenuCfg = {
|
|
||||||
$initBlock: $userMenu
|
|
||||||
};
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
$userAdmin.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// main block is hidden in case javascript is disabled
|
// main block is hidden in case javascript is disabled
|
||||||
$main.removeClass('hidden');
|
$main.removeClass('hidden');
|
||||||
|
|
||||||
@@ -82,7 +68,7 @@ define([
|
|||||||
|
|
||||||
Cryptpad.feedback('REGISTRATION', true);
|
Cryptpad.feedback('REGISTRATION', true);
|
||||||
|
|
||||||
Cryptpad.whenRealtimeSyncs(result.realtime, function () {
|
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
||||||
Cryptpad.login(result.userHash, result.userName, function () {
|
Cryptpad.login(result.userHash, result.userName, function () {
|
||||||
registering = false;
|
registering = false;
|
||||||
if (sessionStorage.redirectTo) {
|
if (sessionStorage.redirectTo) {
|
||||||
@@ -118,28 +104,28 @@ define([
|
|||||||
var warning = Messages._getKey('register_passwordTooShort', [
|
var warning = Messages._getKey('register_passwordTooShort', [
|
||||||
Cred.MINIMUM_PASSWORD_LENGTH
|
Cred.MINIMUM_PASSWORD_LENGTH
|
||||||
]);
|
]);
|
||||||
return void Cryptpad.alert(warning, function () {
|
return void UI.alert(warning, function () {
|
||||||
registering = false;
|
registering = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passwd !== confirmPassword) { // do their passwords match?
|
if (passwd !== confirmPassword) { // do their passwords match?
|
||||||
return void Cryptpad.alert(Messages.register_passwordsDontMatch);
|
return void UI.alert(Messages.register_passwordsDontMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doesAccept) { // do they accept the terms of service?
|
if (!doesAccept) { // do they accept the terms of service?
|
||||||
return void Cryptpad.alert(Messages.register_mustAcceptTerms);
|
return void UI.alert(Messages.register_mustAcceptTerms);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
Cryptpad.confirm("<h2 class='bright msg'>" + Messages.register_warning + "</h2>",
|
UI.confirm("<h2 class='bright msg'>" + Messages.register_warning + "</h2>",
|
||||||
function (yes) {
|
function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
|
|
||||||
registering = true;
|
registering = true;
|
||||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
Cryptpad.addLoadingScreen({
|
UI.addLoadingScreen({
|
||||||
loadingText: Messages.login_hashing,
|
loadingText: Messages.login_hashing,
|
||||||
hideTips: true,
|
hideTips: true,
|
||||||
});
|
});
|
||||||
@@ -152,45 +138,45 @@ define([
|
|||||||
if (err) {
|
if (err) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'NO_SUCH_USER':
|
case 'NO_SUCH_USER':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_noSuchUser, function () {
|
UI.alert(Messages.login_noSuchUser, function () {
|
||||||
registering = false;
|
registering = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'INVAL_USER':
|
case 'INVAL_USER':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_invalUser, function () {
|
UI.alert(Messages.login_invalUser, function () {
|
||||||
registering = false;
|
registering = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'INVAL_PASS':
|
case 'INVAL_PASS':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.alert(Messages.login_invalPass, function () {
|
UI.alert(Messages.login_invalPass, function () {
|
||||||
registering = false;
|
registering = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'PASS_TOO_SHORT':
|
case 'PASS_TOO_SHORT':
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
var warning = Messages._getKey('register_passwordTooShort', [
|
var warning = Messages._getKey('register_passwordTooShort', [
|
||||||
Cred.MINIMUM_PASSWORD_LENGTH
|
Cred.MINIMUM_PASSWORD_LENGTH
|
||||||
]);
|
]);
|
||||||
Cryptpad.alert(warning, function () {
|
UI.alert(warning, function () {
|
||||||
registering = false;
|
registering = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'ALREADY_REGISTERED':
|
case 'ALREADY_REGISTERED':
|
||||||
// logMeIn should reset registering = false
|
// logMeIn should reset registering = false
|
||||||
Cryptpad.removeLoadingScreen(function () {
|
UI.removeLoadingScreen(function () {
|
||||||
Cryptpad.confirm(Messages.register_alreadyRegistered, function (yes) {
|
UI.confirm(Messages.register_alreadyRegistered, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
proxy.login_name = uname;
|
proxy.login_name = uname;
|
||||||
|
|
||||||
if (!proxy[Cryptpad.displayNameKey]) {
|
if (!proxy[Constants.displayNameKey]) {
|
||||||
proxy[Cryptpad.displayNameKey] = uname;
|
proxy[Constants.displayNameKey] = uname;
|
||||||
}
|
}
|
||||||
Cryptpad.eraseTempSessionValues();
|
Cryptpad.eraseTempSessionValues();
|
||||||
logMeIn(result);
|
logMeIn(result);
|
||||||
@@ -199,7 +185,7 @@ define([
|
|||||||
break;
|
break;
|
||||||
default: // UNHANDLED ERROR
|
default: // UNHANDLED ERROR
|
||||||
registering = false;
|
registering = false;
|
||||||
Cryptpad.errorLoadingScreen(Messages.login_unhandledError);
|
UI.errorLoadingScreen(Messages.login_unhandledError);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -212,7 +198,7 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
proxy.login_name = uname;
|
proxy.login_name = uname;
|
||||||
proxy[Cryptpad.displayNameKey] = uname;
|
proxy[Constants.displayNameKey] = uname;
|
||||||
sessionStorage.createReadme = 1;
|
sessionStorage.createReadme = 1;
|
||||||
|
|
||||||
logMeIn(result);
|
logMeIn(result);
|
||||||
@@ -232,7 +218,7 @@ define([
|
|||||||
}, 150);
|
}, 150);
|
||||||
});
|
});
|
||||||
|
|
||||||
var clickRegister = Cryptpad.notAgainForAnother(function () {
|
var clickRegister = Util.notAgainForAnother(function () {
|
||||||
$register.click();
|
$register.click();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
@@ -258,7 +244,7 @@ define([
|
|||||||
$register.click();
|
$register.click();
|
||||||
|
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
Cryptpad.findOKButton().click();
|
UI.findOKButton().click();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'/bower_components/file-saver/FileSaver.min.js',
|
'/bower_components/file-saver/FileSaver.min.js',
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
@@ -12,19 +15,16 @@ define([
|
|||||||
], function (
|
], function (
|
||||||
$,
|
$,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon
|
SFCommon,
|
||||||
|
UI,
|
||||||
|
Util,
|
||||||
|
Hash,
|
||||||
|
Messages
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var saveAs = window.saveAs;
|
var saveAs = window.saveAs;
|
||||||
var Messages = Cryptpad.Messages;
|
var APP = window.APP = {};
|
||||||
var APP = window.APP = {
|
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
};
|
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var common;
|
var common;
|
||||||
var metadataMgr;
|
var metadataMgr;
|
||||||
@@ -68,10 +68,10 @@ define([
|
|||||||
var publicKey = privateData.edPublic;
|
var publicKey = privateData.edPublic;
|
||||||
if (publicKey) {
|
if (publicKey) {
|
||||||
var $key = $('<div>', {'class': 'cp-sidebarlayout-element'}).appendTo($div);
|
var $key = $('<div>', {'class': 'cp-sidebarlayout-element'}).appendTo($div);
|
||||||
var userHref = Cryptpad.getUserHrefFromKeys(accountName, publicKey);
|
var userHref = Hash.getUserHrefFromKeys(privateData.origin, accountName, publicKey);
|
||||||
var $pubLabel = $('<span>', {'class': 'label'})
|
var $pubLabel = $('<span>', {'class': 'label'})
|
||||||
.text(Messages.settings_publicSigningKey);
|
.text(Messages.settings_publicSigningKey);
|
||||||
$key.append($pubLabel).append(Cryptpad.dialog.selectable(userHref));
|
$key.append($pubLabel).append(UI.dialog.selectable(userHref));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $div;
|
return $div;
|
||||||
@@ -198,7 +198,7 @@ define([
|
|||||||
localStore.put(k, undefined);
|
localStore.put(k, undefined);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Cryptpad.alert(Messages.settings_resetTipsDone);
|
UI.alert(Messages.settings_resetTipsDone);
|
||||||
});
|
});
|
||||||
|
|
||||||
return $div;
|
return $div;
|
||||||
@@ -249,7 +249,7 @@ define([
|
|||||||
$button.click(function () {
|
$button.click(function () {
|
||||||
sframeChan.query("Q_THUMBNAIL_CLEAR", null, function (err) {
|
sframeChan.query("Q_THUMBNAIL_CLEAR", null, function (err) {
|
||||||
if (err) { return void console.error("Cannot clear localForage"); }
|
if (err) { return void console.error("Cannot clear localForage"); }
|
||||||
Cryptpad.alert(Messages.settings_resetThumbnailsDone);
|
UI.alert(Messages.settings_resetThumbnailsDone);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -268,8 +268,8 @@ define([
|
|||||||
var sjson = JSON.stringify(data);
|
var sjson = JSON.stringify(data);
|
||||||
var name = displayName || accountName || Messages.anonymous;
|
var name = displayName || accountName || Messages.anonymous;
|
||||||
var suggestion = name + '-' + new Date().toDateString();
|
var suggestion = name + '-' + new Date().toDateString();
|
||||||
Cryptpad.prompt(Cryptpad.Messages.exportPrompt,
|
UI.prompt(Messages.exportPrompt,
|
||||||
Cryptpad.fixFileName(suggestion) + '.json', function (filename) {
|
Util.fixFileName(suggestion) + '.json', function (filename) {
|
||||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
if (!(typeof(filename) === 'string' && filename)) { return; }
|
||||||
var blob = new Blob([sjson], {type: "application/json;charset=utf-8"});
|
var blob = new Blob([sjson], {type: "application/json;charset=utf-8"});
|
||||||
saveAs(blob, filename);
|
saveAs(blob, filename);
|
||||||
@@ -314,14 +314,14 @@ define([
|
|||||||
.text(Messages.settings_resetButton).appendTo($div);
|
.text(Messages.settings_resetButton).appendTo($div);
|
||||||
|
|
||||||
$button.click(function () {
|
$button.click(function () {
|
||||||
Cryptpad.prompt(Messages.settings_resetPrompt, "", function (val) {
|
UI.prompt(Messages.settings_resetPrompt, "", function (val) {
|
||||||
if (val !== "I love CryptPad") {
|
if (val !== "I love CryptPad") {
|
||||||
Cryptpad.alert(Messages.settings_resetError);
|
UI.alert(Messages.settings_resetError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sframeChan.query("Q_SETTINGS_DRIVE_RESET", null, function (err) {
|
sframeChan.query("Q_SETTINGS_DRIVE_RESET", null, function (err) {
|
||||||
if (err) { return void console.error(err); }
|
if (err) { return void console.error(err); }
|
||||||
Cryptpad.alert(Messages.settings_resetDone);
|
UI.alert(Messages.settings_resetDone);
|
||||||
});
|
});
|
||||||
}, undefined, true);
|
}, undefined, true);
|
||||||
});
|
});
|
||||||
@@ -392,7 +392,7 @@ define([
|
|||||||
|
|
||||||
$button.click(function () {
|
$button.click(function () {
|
||||||
|
|
||||||
Cryptpad.confirm(Messages.settings_logoutEverywhereConfirm, function (yes) {
|
UI.confirm(Messages.settings_logoutEverywhereConfirm, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
$spinner.show();
|
$spinner.show();
|
||||||
$ok.hide();
|
$ok.hide();
|
||||||
@@ -424,14 +424,14 @@ define([
|
|||||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div);
|
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide().appendTo($div);
|
||||||
|
|
||||||
$button.click(function () {
|
$button.click(function () {
|
||||||
Cryptpad.confirm(Messages.settings_importConfirm, function (yes) {
|
UI.confirm(Messages.settings_importConfirm, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
$spinner.show();
|
$spinner.show();
|
||||||
$ok.hide();
|
$ok.hide();
|
||||||
sframeChan.query('Q_SETTINGS_IMPORT_LOCAL', null, function () {
|
sframeChan.query('Q_SETTINGS_IMPORT_LOCAL', null, function () {
|
||||||
$spinner.hide();
|
$spinner.hide();
|
||||||
$ok.show();
|
$ok.show();
|
||||||
Cryptpad.alert(Messages.settings_importDone);
|
UI.alert(Messages.settings_importDone);
|
||||||
});
|
});
|
||||||
}, undefined, true);
|
}, undefined, true);
|
||||||
});
|
});
|
||||||
@@ -488,7 +488,7 @@ define([
|
|||||||
|
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(Cryptpad.addLoadingScreen));
|
$(waitFor(UI.addLoadingScreen));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
APP.$container = $('#cp-sidebarlayout-container');
|
APP.$container = $('#cp-sidebarlayout-container');
|
||||||
@@ -498,12 +498,6 @@ define([
|
|||||||
sframeChan = common.getSframeChannel();
|
sframeChan = common.getSframeChannel();
|
||||||
sframeChan.onReady(waitFor());
|
sframeChan.onReady(waitFor());
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
metadataMgr = common.getMetadataMgr();
|
metadataMgr = common.getMetadataMgr();
|
||||||
privateData = metadataMgr.getPrivateData();
|
privateData = metadataMgr.getPrivateData();
|
||||||
|
|
||||||
@@ -511,7 +505,6 @@ define([
|
|||||||
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
||||||
var configTb = {
|
var configTb = {
|
||||||
displayed: displayed,
|
displayed: displayed,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: APP.$toolbar,
|
$container: APP.$toolbar,
|
||||||
pageTitle: Messages.settings_title,
|
pageTitle: Messages.settings_title,
|
||||||
@@ -546,6 +539,6 @@ define([
|
|||||||
createLeftside();
|
createLeftside();
|
||||||
createUsageButton();
|
createUsageButton();
|
||||||
|
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,18 +36,7 @@ define([
|
|||||||
};
|
};
|
||||||
window.addEventListener('message', onMsg);
|
window.addEventListener('message', onMsg);
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
/* TODO
|
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
||||||
window.addEventListener('storage', function (e) {
|
|
||||||
if (e.key !== Cryptpad.userHashKey) { return; }
|
|
||||||
var o = e.oldValue;
|
|
||||||
var n = e.newValue;
|
|
||||||
window.location.reload();
|
|
||||||
if (o && !n) { // disconnect
|
|
||||||
//redirectToMain();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
var addRpc = function (sframeChan, Cryptpad) {
|
|
||||||
sframeChan.on('Q_THUMBNAIL_CLEAR', function (d, cb) {
|
sframeChan.on('Q_THUMBNAIL_CLEAR', function (d, cb) {
|
||||||
Cryptpad.clearThumbnail(function (err, data) {
|
Cryptpad.clearThumbnail(function (err, data) {
|
||||||
cb({err:err, data:data});
|
cb({err:err, data:data});
|
||||||
@@ -58,8 +47,11 @@ define([
|
|||||||
});
|
});
|
||||||
sframeChan.on('Q_SETTINGS_DRIVE_SET', function (data, cb) {
|
sframeChan.on('Q_SETTINGS_DRIVE_SET', function (data, cb) {
|
||||||
var sjson = JSON.stringify(data);
|
var sjson = JSON.stringify(data);
|
||||||
var k = Cryptpad.getUserHash() || localStorage[Cryptpad.fileHashKey];
|
require([
|
||||||
require(['/common/cryptget.js'], function (Crypt) {
|
'/common/cryptget.js',
|
||||||
|
'/common/common-constants.js'
|
||||||
|
], function (Crypt, Constants) {
|
||||||
|
var k = Cryptpad.getUserHash() || localStorage[Constants.fileHashKey];
|
||||||
Crypt.put(k, sjson, function (err) {
|
Crypt.put(k, sjson, function (err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
});
|
});
|
||||||
@@ -69,7 +61,7 @@ define([
|
|||||||
var proxy = Cryptpad.getProxy();
|
var proxy = Cryptpad.getProxy();
|
||||||
var realtime = Cryptpad.getRealtime();
|
var realtime = Cryptpad.getRealtime();
|
||||||
proxy.drive = Cryptpad.getStore().getEmptyObject();
|
proxy.drive = Cryptpad.getStore().getEmptyObject();
|
||||||
Cryptpad.whenRealtimeSyncs(realtime, cb);
|
Utils.Realtime.whenRealtimeSyncs(realtime, cb);
|
||||||
});
|
});
|
||||||
sframeChan.on('Q_SETTINGS_LOGOUT', function (data, cb) {
|
sframeChan.on('Q_SETTINGS_LOGOUT', function (data, cb) {
|
||||||
var proxy = Cryptpad.getProxy();
|
var proxy = Cryptpad.getProxy();
|
||||||
@@ -77,12 +69,15 @@ define([
|
|||||||
var token = Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);
|
var token = Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);
|
||||||
localStorage.setItem('loginToken', token);
|
localStorage.setItem('loginToken', token);
|
||||||
proxy.loginToken = token;
|
proxy.loginToken = token;
|
||||||
Cryptpad.whenRealtimeSyncs(realtime, cb);
|
Utils.Realtime.whenRealtimeSyncs(realtime, cb);
|
||||||
});
|
});
|
||||||
sframeChan.on('Q_SETTINGS_IMPORT_LOCAL', function (data, cb) {
|
sframeChan.on('Q_SETTINGS_IMPORT_LOCAL', function (data, cb) {
|
||||||
var proxyData = Cryptpad.getStore().getProxy();
|
var proxyData = Cryptpad.getStore().getProxy();
|
||||||
require(['/common/mergeDrive.js'], function (Merge) {
|
require([
|
||||||
Merge.anonDriveIntoUser(proxyData, localStorage.FS_hash, cb);
|
'/common/mergeDrive.js',
|
||||||
|
'/common/common-constants.js'
|
||||||
|
], function (Merge, Constants) {
|
||||||
|
Merge.anonDriveIntoUser(proxyData, localStorage[Constants.fileHashKey], cb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,528 +0,0 @@
|
|||||||
define([
|
|
||||||
'jquery',
|
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/hyperscript.js',
|
|
||||||
'/bower_components/marked/marked.min.js',
|
|
||||||
'/common/media-tag.js',
|
|
||||||
], function ($, Cryptpad, h, Marked, MediaTag) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var UI = {};
|
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var m = function (md) {
|
|
||||||
var d = h('div.cp-app-contacts-content');
|
|
||||||
try {
|
|
||||||
d.innerHTML = Marked(md || '');
|
|
||||||
var $d = $(d);
|
|
||||||
// remove potentially malicious elements
|
|
||||||
$d.find('script, iframe, object, applet, video, audio').remove();
|
|
||||||
|
|
||||||
// activate media-tags
|
|
||||||
$d.find('media-tag').each(function (i, e) { MediaTag(e); });
|
|
||||||
} catch (e) {
|
|
||||||
console.error(md);
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
};
|
|
||||||
|
|
||||||
var dataQuery = function (curvePublic) {
|
|
||||||
return '[data-key="' + curvePublic + '"]';
|
|
||||||
};
|
|
||||||
|
|
||||||
var initChannel = function (state, curvePublic, info) {
|
|
||||||
console.log('initializing channel for [%s]', curvePublic);
|
|
||||||
state.channels[curvePublic] = {
|
|
||||||
messages: [],
|
|
||||||
HEAD: info.lastKnownHash,
|
|
||||||
TAIL: null,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
UI.create = function (messenger, $userlist, $messages, common) {
|
|
||||||
var origin = common.getMetadataMgr().getPrivateData().origin;
|
|
||||||
|
|
||||||
var state = window.state = {
|
|
||||||
active: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
state.channels = {};
|
|
||||||
var displayNames = state.displayNames = {};
|
|
||||||
|
|
||||||
var avatars = state.avatars = {};
|
|
||||||
var setActive = function (curvePublic) {
|
|
||||||
state.active = curvePublic;
|
|
||||||
};
|
|
||||||
var isActive = function (curvePublic) {
|
|
||||||
return curvePublic === state.active;
|
|
||||||
};
|
|
||||||
|
|
||||||
var find = {};
|
|
||||||
find.inList = function (curvePublic) {
|
|
||||||
return $userlist.find(dataQuery(curvePublic));
|
|
||||||
};
|
|
||||||
|
|
||||||
var notify = function (curvePublic) {
|
|
||||||
find.inList(curvePublic).addClass('cp-app-contacts-notify');
|
|
||||||
};
|
|
||||||
var unnotify = function (curvePublic) {
|
|
||||||
find.inList(curvePublic).removeClass('cp-app-contacts-notify');
|
|
||||||
};
|
|
||||||
|
|
||||||
var markup = {};
|
|
||||||
markup.message = function (msg) {
|
|
||||||
var curvePublic = msg.author;
|
|
||||||
var name = displayNames[msg.author];
|
|
||||||
return h('div.cp-app-contacts-message', {
|
|
||||||
title: msg.time? new Date(msg.time).toLocaleString(): '?',
|
|
||||||
'data-key': curvePublic,
|
|
||||||
}, [
|
|
||||||
name? h('div.cp-app-contacts-sender', name): undefined,
|
|
||||||
m(msg.text),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
var getChat = function (curvePublic) {
|
|
||||||
return $messages.find(dataQuery(curvePublic));
|
|
||||||
};
|
|
||||||
|
|
||||||
var normalizeLabels = function ($messagebox) {
|
|
||||||
$messagebox.find('div.cp-app-contacts-message').toArray().reduce(function (a, b) {
|
|
||||||
var $b = $(b);
|
|
||||||
if ($(a).data('key') === $b.data('key')) {
|
|
||||||
$b.find('.cp-app-contacts-sender').hide();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
markup.chatbox = function (curvePublic, data) {
|
|
||||||
var moreHistory = h('span.cp-app-contacts-more-history.fa.fa-history', {
|
|
||||||
title: Messages.contacts_fetchHistory,
|
|
||||||
});
|
|
||||||
var displayName = data.displayName;
|
|
||||||
|
|
||||||
var fetching = false;
|
|
||||||
var $moreHistory = $(moreHistory).click(function () {
|
|
||||||
if (fetching) { return; }
|
|
||||||
|
|
||||||
// get oldest known message...
|
|
||||||
var channel = state.channels[curvePublic];
|
|
||||||
|
|
||||||
if (channel.exhausted) {
|
|
||||||
return void $moreHistory.addClass('cp-app-contacts-faded');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('getting history');
|
|
||||||
var sig = channel.TAIL || channel.HEAD;
|
|
||||||
|
|
||||||
fetching = true;
|
|
||||||
var $messagebox = $(getChat(curvePublic)).find('.cp-app-contacts-messages');
|
|
||||||
messenger.getMoreHistory(curvePublic, sig, 10, function (e, history) {
|
|
||||||
fetching = false;
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
|
|
||||||
if (history.length === 0) {
|
|
||||||
channel.exhausted = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
history.forEach(function (msg) {
|
|
||||||
if (channel.exhausted) { return; }
|
|
||||||
if (msg.sig) {
|
|
||||||
if (msg.sig === channel.TAIL) {
|
|
||||||
console.error('No more messages to fetch');
|
|
||||||
channel.exhausted = true;
|
|
||||||
console.log(channel);
|
|
||||||
return void $moreHistory.addClass('cp-app-contacts-faded');
|
|
||||||
} else {
|
|
||||||
channel.TAIL = msg.sig;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return void console.error('expected signature');
|
|
||||||
}
|
|
||||||
if (msg.type !== 'MSG') { return; }
|
|
||||||
|
|
||||||
// FIXME Schlameil the painter (performance does not scale well)
|
|
||||||
if (channel.messages.some(function (old) {
|
|
||||||
return msg.sig === old.sig;
|
|
||||||
})) { return; }
|
|
||||||
|
|
||||||
channel.messages.unshift(msg);
|
|
||||||
var el_message = markup.message(msg);
|
|
||||||
$messagebox.prepend(el_message);
|
|
||||||
});
|
|
||||||
normalizeLabels($messagebox);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var removeHistory = h('span.cp-app-contacts-remove-history.fa.fa-eraser', {
|
|
||||||
title: Messages.contacts_removeHistoryTitle
|
|
||||||
});
|
|
||||||
|
|
||||||
$(removeHistory).click(function () {
|
|
||||||
Cryptpad.confirm(Messages.contacts_confirmRemoveHistory, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
Cryptpad.clearOwnedChannel(data.channel, function (e) {
|
|
||||||
if (e) {
|
|
||||||
console.error(e);
|
|
||||||
Cryptpad.alert(Messages.contacts_removeHistoryServerError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var avatar = h('div.cp-avatar');
|
|
||||||
var header = h('div.cp-app-contacts-header', [
|
|
||||||
avatar,
|
|
||||||
moreHistory,
|
|
||||||
removeHistory,
|
|
||||||
]);
|
|
||||||
var messages = h('div.cp-app-contacts-messages');
|
|
||||||
var input = h('textarea', {
|
|
||||||
placeholder: Messages.contacts_typeHere
|
|
||||||
});
|
|
||||||
var sendButton = h('button.btn.btn-primary.fa.fa-paper-plane', {
|
|
||||||
title: Messages.contacts_send,
|
|
||||||
});
|
|
||||||
|
|
||||||
var rightCol = h('span.cp-app-contacts-right-col', [
|
|
||||||
h('span.cp-app-contacts-name', displayName),
|
|
||||||
]);
|
|
||||||
|
|
||||||
var $avatar = $(avatar);
|
|
||||||
if (data.avatar && avatars[data.avatar]) {
|
|
||||||
$avatar.append(avatars[data.avatar]).append(rightCol);
|
|
||||||
} else {
|
|
||||||
common.displayAvatar($avatar, data.avatar, data.displayName, function ($img) {
|
|
||||||
if (data.avatar && $img) {
|
|
||||||
avatars[data.avatar] = $img[0].outerHTML;
|
|
||||||
}
|
|
||||||
$(rightCol).insertAfter($avatar);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var sending = false;
|
|
||||||
var send = function (content) {
|
|
||||||
if (typeof(content) !== 'string' || !content.trim()) { return; }
|
|
||||||
if (sending) { return false; }
|
|
||||||
sending = true;
|
|
||||||
messenger.sendMessage(curvePublic, content, function (e) {
|
|
||||||
if (e) {
|
|
||||||
// failed to send
|
|
||||||
return void console.error('failed to send');
|
|
||||||
}
|
|
||||||
input.value = '';
|
|
||||||
sending = false;
|
|
||||||
console.log('sent successfully');
|
|
||||||
var $messagebox = $(messages);
|
|
||||||
|
|
||||||
var height = $messagebox[0].scrollHeight;
|
|
||||||
$messagebox.scrollTop(height);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var onKeyDown = function (e) {
|
|
||||||
// ignore anything that isn't 'enter'
|
|
||||||
if (e.keyCode !== 13) { return; }
|
|
||||||
// send unless they're holding a ctrl-key or shift
|
|
||||||
if (!e.ctrlKey && !e.shiftKey) {
|
|
||||||
send(this.value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert a newline if they're holding either
|
|
||||||
var val = this.value;
|
|
||||||
var start = this.selectionState;
|
|
||||||
var end = this.selectionEnd;
|
|
||||||
|
|
||||||
if (![start,end].some(function (x) {
|
|
||||||
return typeof(x) !== 'number';
|
|
||||||
})) {
|
|
||||||
this.value = val.slice(0, start) + '\n' + val.slice(end);
|
|
||||||
this.selectionStart = this.selectionEnd = start + 1;
|
|
||||||
} else if (document.selection && document.selection.createRange) {
|
|
||||||
this.focus();
|
|
||||||
var range = document.selection.createRange();
|
|
||||||
range.text = '\r\n';
|
|
||||||
range.collapse(false);
|
|
||||||
range.select();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
$(input).on('keydown', onKeyDown);
|
|
||||||
$(sendButton).click(function () { send(input.value); });
|
|
||||||
|
|
||||||
return h('div.cp-app-contacts-chat', {
|
|
||||||
'data-key': curvePublic,
|
|
||||||
}, [
|
|
||||||
header,
|
|
||||||
messages,
|
|
||||||
h('div.cp-app-contacts-input', [
|
|
||||||
input,
|
|
||||||
sendButton,
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
var hideInfo = function () {
|
|
||||||
$messages.find('.cp-app-contacts-info').hide();
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateStatus = function (curvePublic) {
|
|
||||||
var $status = find.inList(curvePublic).find('.cp-app-contacts-status');
|
|
||||||
// FIXME this stopped working :(
|
|
||||||
messenger.getStatus(curvePublic, function (e, online) {
|
|
||||||
// if error maybe you shouldn't display this friend...
|
|
||||||
if (e) {
|
|
||||||
find.inList(curvePublic).hide();
|
|
||||||
getChat(curvePublic).hide();
|
|
||||||
|
|
||||||
return void console.error(curvePublic, e);
|
|
||||||
}
|
|
||||||
if (online) {
|
|
||||||
return void $status
|
|
||||||
.removeClass('cp-app-contacts-offline').addClass('cp-app-contacts-online');
|
|
||||||
}
|
|
||||||
$status.removeClass('cp-app-contacts-online').addClass('cp-app-contacts-offline');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var display = function (curvePublic) {
|
|
||||||
var channel = state.channels[curvePublic];
|
|
||||||
var lastMsg = channel.messages.slice(-1)[0];
|
|
||||||
|
|
||||||
if (lastMsg) {
|
|
||||||
channel.HEAD = lastMsg.sig;
|
|
||||||
messenger.setChannelHead(curvePublic, channel.HEAD, function (e) {
|
|
||||||
if (e) { console.error(e); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setActive(curvePublic);
|
|
||||||
unnotify(curvePublic);
|
|
||||||
var $chat = getChat(curvePublic);
|
|
||||||
hideInfo();
|
|
||||||
$messages.find('div.cp-app-contacts-chat[data-key]').hide();
|
|
||||||
if ($chat.length) {
|
|
||||||
var $chat_messages = $chat.find('div.cp-app-contacts-message');
|
|
||||||
if (!$chat_messages.length) {
|
|
||||||
var $more = $chat.find('.cp-app-contacts-more-history');
|
|
||||||
$more.click();
|
|
||||||
}
|
|
||||||
return void $chat.show();
|
|
||||||
}
|
|
||||||
messenger.getFriendInfo(curvePublic, function (e, info) {
|
|
||||||
if (e) { return void console.error(e); } // FIXME
|
|
||||||
var chatbox = markup.chatbox(curvePublic, info);
|
|
||||||
$messages.append(chatbox);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var removeFriend = function (curvePublic) {
|
|
||||||
messenger.removeFriend(curvePublic, function (e /*, removed */) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
find.inList(curvePublic).remove();
|
|
||||||
//console.log(removed);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
markup.friend = function (data) {
|
|
||||||
var curvePublic = data.curvePublic;
|
|
||||||
var friend = h('div.cp-app-contacts-friend.cp-avatar', {
|
|
||||||
'data-key': curvePublic,
|
|
||||||
});
|
|
||||||
|
|
||||||
var remove = h('span.cp-app-contacts-remove.fa.fa-user-times', {
|
|
||||||
title: Messages.contacts_remove
|
|
||||||
});
|
|
||||||
var status = h('span.cp-app-contacts-status');
|
|
||||||
var rightCol = h('span.cp-app-contacts-right-col', [
|
|
||||||
h('span.cp-app-contacts-name', [data.displayName]),
|
|
||||||
remove,
|
|
||||||
]);
|
|
||||||
|
|
||||||
var $friend = $(friend)
|
|
||||||
.click(function () {
|
|
||||||
display(curvePublic);
|
|
||||||
})
|
|
||||||
.dblclick(function () {
|
|
||||||
if (data.profile) { window.open(origin + '/profile/#' + data.profile); }
|
|
||||||
});
|
|
||||||
|
|
||||||
$(remove).click(function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
Cryptpad.confirm(Messages._getKey('contacts_confirmRemove', [
|
|
||||||
Cryptpad.fixHTML(data.displayName)
|
|
||||||
]), function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
removeFriend(curvePublic, function (e) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
});
|
|
||||||
// TODO remove friend from userlist ui
|
|
||||||
// FIXME seems to trigger EJOINED from netflux-websocket (from server);
|
|
||||||
// (tried to join a channel in which you were already present)
|
|
||||||
}, undefined, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.avatar && avatars[data.avatar]) {
|
|
||||||
$friend.append(avatars[data.avatar]);
|
|
||||||
$friend.append(rightCol);
|
|
||||||
} else {
|
|
||||||
common.displayAvatar($friend, data.avatar, data.displayName, function ($img) {
|
|
||||||
if (data.avatar && $img) {
|
|
||||||
avatars[data.avatar] = $img[0].outerHTML;
|
|
||||||
}
|
|
||||||
$friend.append(rightCol);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$friend.append(status);
|
|
||||||
return $friend;
|
|
||||||
};
|
|
||||||
|
|
||||||
var isBottomedOut = function ($elem) {
|
|
||||||
return ($elem[0].scrollHeight - $elem.scrollTop() === $elem.outerHeight());
|
|
||||||
};
|
|
||||||
|
|
||||||
var initializing = true;
|
|
||||||
messenger.on('message', function (message) {
|
|
||||||
if (!initializing) { Cryptpad.notify(); }
|
|
||||||
var curvePublic = message.curve;
|
|
||||||
|
|
||||||
var name = displayNames[curvePublic];
|
|
||||||
var chat = getChat(curvePublic, name);
|
|
||||||
|
|
||||||
console.log(message);
|
|
||||||
|
|
||||||
var el_message = markup.message(message);
|
|
||||||
|
|
||||||
state.channels[curvePublic].messages.push(message);
|
|
||||||
|
|
||||||
var $chat = $(chat);
|
|
||||||
|
|
||||||
if (!$chat.length) {
|
|
||||||
console.error("Got a message but the chat isn't open");
|
|
||||||
}
|
|
||||||
|
|
||||||
var $messagebox = $chat.find('.cp-app-contacts-messages');
|
|
||||||
var shouldScroll = isBottomedOut($messagebox);
|
|
||||||
|
|
||||||
$messagebox.append(el_message);
|
|
||||||
|
|
||||||
if (shouldScroll) {
|
|
||||||
$messagebox.scrollTop($messagebox.outerHeight());
|
|
||||||
}
|
|
||||||
normalizeLabels($messagebox);
|
|
||||||
|
|
||||||
var channel = state.channels[curvePublic];
|
|
||||||
if (!channel) {
|
|
||||||
console.error('expected channel [%s] to be open', curvePublic);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isActive(curvePublic)) {
|
|
||||||
channel.HEAD = message.sig;
|
|
||||||
messenger.setChannelHead(curvePublic, message.sig, function (e) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lastMsg = channel.messages.slice(-1)[0];
|
|
||||||
if (lastMsg.sig !== channel.HEAD) {
|
|
||||||
return void notify(curvePublic);
|
|
||||||
}
|
|
||||||
unnotify(curvePublic);
|
|
||||||
});
|
|
||||||
|
|
||||||
messenger.on('join', function (curvePublic, channel) {
|
|
||||||
channel = channel;
|
|
||||||
updateStatus(curvePublic);
|
|
||||||
});
|
|
||||||
messenger.on('leave', function (curvePublic, channel) {
|
|
||||||
channel = channel;
|
|
||||||
updateStatus(curvePublic);
|
|
||||||
});
|
|
||||||
|
|
||||||
// change in your friend list
|
|
||||||
messenger.on('update', function (info, curvePublic) {
|
|
||||||
var name = displayNames[curvePublic] = info.displayName;
|
|
||||||
|
|
||||||
// update label in friend list
|
|
||||||
find.inList(curvePublic).find('.cp-app-contacts-name').text(name);
|
|
||||||
|
|
||||||
// update title bar and messages
|
|
||||||
$messages.find(dataQuery(curvePublic) + ' .cp-app-contacts-header ' +
|
|
||||||
'.cp-app-contacts-name, div.cp-app-contacts-message'+
|
|
||||||
dataQuery(curvePublic) + ' div.cp-app-contacts-sender').text(name).text(name);
|
|
||||||
});
|
|
||||||
|
|
||||||
var connectToFriend = function (curvePublic, cb) {
|
|
||||||
messenger.getFriendInfo(curvePublic, function (e, info) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
var name = displayNames[curvePublic] = info.displayName;
|
|
||||||
initChannel(state, curvePublic, info);
|
|
||||||
|
|
||||||
var chatbox = markup.chatbox(curvePublic, info);
|
|
||||||
$(chatbox).hide();
|
|
||||||
$messages.append(chatbox);
|
|
||||||
|
|
||||||
var friend = markup.friend(info, name);
|
|
||||||
$userlist.append(friend);
|
|
||||||
messenger.openFriendChannel(curvePublic, function (e) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
cb();
|
|
||||||
updateStatus(curvePublic);
|
|
||||||
// don't add friends that are already in your userlist
|
|
||||||
//if (friendExistsInUserList(k)) { return; }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
messenger.on('friend', function (curvePublic) {
|
|
||||||
console.log('new friend: ', curvePublic);
|
|
||||||
//console.error("TODO redraw user list");
|
|
||||||
//console.error("TODO connect to new friend");
|
|
||||||
// FIXME this doesn't work right now because the friend hasn't been fully added?
|
|
||||||
connectToFriend(curvePublic, function () {
|
|
||||||
//console.error('connected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
messenger.on('unfriend', function (curvePublic) {
|
|
||||||
console.log('unfriend', curvePublic);
|
|
||||||
find.inList(curvePublic).remove();
|
|
||||||
console.error('TODO remove chatbox');
|
|
||||||
console.error('TODO show something if that chatbox was active');
|
|
||||||
});
|
|
||||||
|
|
||||||
Cryptpad.onDisplayNameChanged(function () {
|
|
||||||
//messenger.checkNewFriends();
|
|
||||||
messenger.updateMyData();
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME dirty hack
|
|
||||||
messenger.getMyInfo(function (e, info) {
|
|
||||||
displayNames[info.curvePublic] = info.displayName;
|
|
||||||
});
|
|
||||||
|
|
||||||
messenger.getFriendList(function (e, keys) {
|
|
||||||
var count = keys.length + 1;
|
|
||||||
var ready = function () {
|
|
||||||
count--;
|
|
||||||
if (count === 0) {
|
|
||||||
initializing = false;
|
|
||||||
Cryptpad.removeLoadingScreen();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ready();
|
|
||||||
keys.forEach(function (curvePublic) {
|
|
||||||
connectToFriend(curvePublic, ready);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return UI;
|
|
||||||
});
|
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
define([
|
define([
|
||||||
'jquery',
|
'jquery',
|
||||||
'json.sortify',
|
'json.sortify',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/slide/slide.js',
|
'/slide/slide.js',
|
||||||
'/common/sframe-app-framework.js',
|
'/common/sframe-app-framework.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/customize/messages.js',
|
||||||
'cm/lib/codemirror',
|
'cm/lib/codemirror',
|
||||||
|
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
@@ -42,16 +44,17 @@ define([
|
|||||||
], function (
|
], function (
|
||||||
$,
|
$,
|
||||||
JSONSortify,
|
JSONSortify,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
Slide,
|
Slide,
|
||||||
Framework,
|
Framework,
|
||||||
Util,
|
Util,
|
||||||
|
Hash,
|
||||||
|
UI,
|
||||||
|
Messages,
|
||||||
CMeditor)
|
CMeditor)
|
||||||
{
|
{
|
||||||
window.CodeMirror = CMeditor;
|
window.CodeMirror = CMeditor;
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var SLIDE_BACKCOLOR_ID = "cp-app-slide-toolbar-backcolor";
|
var SLIDE_BACKCOLOR_ID = "cp-app-slide-toolbar-backcolor";
|
||||||
var SLIDE_COLOR_ID = "cp-app-slide-toolbar-color";
|
var SLIDE_COLOR_ID = "cp-app-slide-toolbar-color";
|
||||||
@@ -104,7 +107,7 @@ define([
|
|||||||
Slide.update(editor.getValue(), true);
|
Slide.update(editor.getValue(), true);
|
||||||
$print.html($content.html());
|
$print.html($content.html());
|
||||||
// TODO use translation key
|
// TODO use translation key
|
||||||
Cryptpad.confirm("Are you sure you want to print?", function (yes) {
|
UI.confirm("Are you sure you want to print?", function (yes) {
|
||||||
if (yes) {
|
if (yes) {
|
||||||
window.focus();
|
window.focus();
|
||||||
window.print();
|
window.print();
|
||||||
@@ -224,7 +227,7 @@ define([
|
|||||||
slideOptionsTmp.style = '';
|
slideOptionsTmp.style = '';
|
||||||
parseLess(mkLess(less), function (err, css) {
|
parseLess(mkLess(less), function (err, css) {
|
||||||
if (err) {
|
if (err) {
|
||||||
Cryptpad.alert(
|
UI.alert(
|
||||||
'<strong>' + Messages.slide_invalidLess + '</strong>' +
|
'<strong>' + Messages.slide_invalidLess + '</strong>' +
|
||||||
'<br>' +
|
'<br>' +
|
||||||
'<pre class="cp-slide-css-error">' + Util.fixHTML(
|
'<pre class="cp-slide-css-error">' + Util.fixHTML(
|
||||||
@@ -245,14 +248,14 @@ define([
|
|||||||
updateLocalOptions(slideOptionsTmp);
|
updateLocalOptions(slideOptionsTmp);
|
||||||
}
|
}
|
||||||
$container.remove();
|
$container.remove();
|
||||||
Cryptpad.stopListening(h);
|
UI.stopListening(h);
|
||||||
};
|
};
|
||||||
var todoCancel = function () {
|
var todoCancel = function () {
|
||||||
$container.remove();
|
$container.remove();
|
||||||
Cryptpad.stopListening(h);
|
UI.stopListening(h);
|
||||||
};
|
};
|
||||||
|
|
||||||
h = Cryptpad.listenForKeys(todo, todoCancel);
|
h = UI.listenForKeys(todo, todoCancel);
|
||||||
|
|
||||||
var $nav = $('<nav>').appendTo($div);
|
var $nav = $('<nav>').appendTo($div);
|
||||||
$('<button>', {'class': 'cancel'}).text(Messages.cancelButton).appendTo($nav).click(todoCancel);
|
$('<button>', {'class': 'cancel'}).text(Messages.cancelButton).appendTo($nav).click(todoCancel);
|
||||||
@@ -436,8 +439,8 @@ define([
|
|||||||
//var cursor = editor.getCursor();
|
//var cursor = editor.getCursor();
|
||||||
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
||||||
//var text = '';
|
//var text = '';
|
||||||
var parsed = Cryptpad.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '"></media-tag>';
|
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '"></media-tag>';
|
||||||
editor.replaceSelection(mt);
|
editor.replaceSelection(mt);
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ define([
|
|||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/sframe-chainpad-listmap.js',
|
'/common/sframe-chainpad-listmap.js',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-hash.js',
|
||||||
'/todo/todo.js',
|
'/todo/todo.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
@@ -16,38 +18,30 @@ define([
|
|||||||
Crypto,
|
Crypto,
|
||||||
Listmap,
|
Listmap,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Cryptpad,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
Todo
|
UI,
|
||||||
|
Hash,
|
||||||
|
Todo,
|
||||||
|
Messages
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
var APP = window.APP = {};
|
var APP = window.APP = {};
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var common;
|
var common;
|
||||||
var sFrameChan;
|
var sFrameChan;
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(Cryptpad.addLoadingScreen));
|
$(waitFor(UI.addLoadingScreen));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
sFrameChan = common.getSframeChannel();
|
sFrameChan = common.getSframeChannel();
|
||||||
sFrameChan.onReady(waitFor());
|
sFrameChan.onReady(waitFor());
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var $body = $('body');
|
var $body = $('body');
|
||||||
var $list = $('#cp-app-todo-taskslist');
|
var $list = $('#cp-app-todo-taskslist');
|
||||||
|
|
||||||
var removeTips = function () {
|
var removeTips = function () {
|
||||||
Cryptpad.clearTooltips();
|
UI.clearTooltips();
|
||||||
};
|
};
|
||||||
|
|
||||||
var onReady = function () {
|
var onReady = function () {
|
||||||
@@ -163,7 +157,7 @@ define([
|
|||||||
"mtime": +new Date()
|
"mtime": +new Date()
|
||||||
};
|
};
|
||||||
|
|
||||||
var id = Cryptpad.createChannelId();
|
var id = Hash.createChannelId();
|
||||||
todo.add(id, obj);
|
todo.add(id, obj);
|
||||||
|
|
||||||
$input.val("");
|
$input.val("");
|
||||||
@@ -188,12 +182,10 @@ define([
|
|||||||
editTask = editTask;
|
editTask = editTask;
|
||||||
|
|
||||||
display();
|
display();
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
var onInit = function () {
|
var onInit = function () {
|
||||||
Cryptpad.addLoadingScreen();
|
|
||||||
|
|
||||||
$body.on('dragover', function (e) { e.preventDefault(); });
|
$body.on('dragover', function (e) { e.preventDefault(); });
|
||||||
$body.on('drop', function (e) { e.preventDefault(); });
|
$body.on('drop', function (e) { e.preventDefault(); });
|
||||||
|
|
||||||
@@ -202,7 +194,6 @@ define([
|
|||||||
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle'];
|
||||||
var configTb = {
|
var configTb = {
|
||||||
displayed: displayed,
|
displayed: displayed,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: $bar,
|
$container: $bar,
|
||||||
pageTitle: Messages.todo_title,
|
pageTitle: Messages.todo_title,
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ define([
|
|||||||
};
|
};
|
||||||
window.addEventListener('message', onMsg);
|
window.addEventListener('message', onMsg);
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
var getSecrets = function (Cryptpad) {
|
var getSecrets = function (Cryptpad, Utils) {
|
||||||
var proxy = Cryptpad.getProxy();
|
var proxy = Cryptpad.getProxy();
|
||||||
var hash = proxy.todo || Cryptpad.createRandomHash();
|
var hash = proxy.todo || Utils.Hash.createRandomHash();
|
||||||
return Cryptpad.getSecrets('todo', hash);
|
return Utils.Hash.getSecrets('todo', hash);
|
||||||
};
|
};
|
||||||
SFCommonO.start({
|
SFCommonO.start({
|
||||||
getSecrets: getSecrets,
|
getSecrets: getSecrets,
|
||||||
|
|||||||
@@ -26,23 +26,6 @@ define([
|
|||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
var $main = $('#mainBlock');
|
var $main = $('#mainBlock');
|
||||||
// Language selector
|
|
||||||
var $sel = $('#language-selector');
|
|
||||||
Cryptpad.createLanguageSelector(undefined, $sel);
|
|
||||||
$sel.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
$sel.show();
|
|
||||||
|
|
||||||
// User admin menu
|
|
||||||
var $userMenu = $('#user-menu');
|
|
||||||
var userMenuCfg = {
|
|
||||||
$initBlock: $userMenu
|
|
||||||
};
|
|
||||||
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
|
|
||||||
$userAdmin.find('button').addClass('btn').addClass('btn-secondary');
|
|
||||||
|
|
||||||
$(window).click(function () {
|
|
||||||
$('.cp-dropdown-content').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// main block is hidden in case javascript is disabled
|
// main block is hidden in case javascript is disabled
|
||||||
$main.removeClass('hidden');
|
$main.removeClass('hidden');
|
||||||
|
|||||||
@@ -3,15 +3,14 @@ define([
|
|||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'json.sortify',
|
'json.sortify',
|
||||||
'/common/cryptpad-common.js',
|
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
'/common/cryptget.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/common/sframe-common-interface.js',
|
'/common/common-interface.js',
|
||||||
'/api/config',
|
'/api/config',
|
||||||
'/common/common-realtime.js',
|
'/common/common-realtime.js',
|
||||||
'/customize/pages.js',
|
'/customize/pages.js',
|
||||||
|
'/customize/messages.js',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/common/common-thumbnail.js',
|
'/common/common-thumbnail.js',
|
||||||
'/whiteboard/colors.js',
|
'/whiteboard/colors.js',
|
||||||
@@ -28,25 +27,22 @@ define([
|
|||||||
Crypto,
|
Crypto,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
JSONSortify,
|
JSONSortify,
|
||||||
Cryptpad,
|
|
||||||
Util,
|
Util,
|
||||||
Cryptget,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
SFUI,
|
UI,
|
||||||
ApiConfig,
|
ApiConfig,
|
||||||
CommonRealtime,
|
CommonRealtime,
|
||||||
Pages,
|
Pages,
|
||||||
|
Messages,
|
||||||
AppConfig,
|
AppConfig,
|
||||||
Thumb,
|
Thumb,
|
||||||
Colors,
|
Colors,
|
||||||
ChainPad)
|
ChainPad)
|
||||||
{
|
{
|
||||||
var saveAs = window.saveAs;
|
var saveAs = window.saveAs;
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
var APP = window.APP = {
|
var APP = window.APP = {
|
||||||
Cryptpad: Cryptpad,
|
|
||||||
$: $
|
$: $
|
||||||
};
|
};
|
||||||
var Fabric = APP.Fabric = window.fabric;
|
var Fabric = APP.Fabric = window.fabric;
|
||||||
@@ -57,10 +53,6 @@ define([
|
|||||||
|
|
||||||
var toolbar;
|
var toolbar;
|
||||||
|
|
||||||
var onConnectError = function () {
|
|
||||||
Cryptpad.errorLoadingScreen(Messages.websocketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
var andThen = function (common) {
|
var andThen = function (common) {
|
||||||
var config = {};
|
var config = {};
|
||||||
/* Initialize Fabric */
|
/* Initialize Fabric */
|
||||||
@@ -126,7 +118,7 @@ define([
|
|||||||
var updateBrushWidth = function () {
|
var updateBrushWidth = function () {
|
||||||
var val = $width.val();
|
var val = $width.val();
|
||||||
canvas.freeDrawingBrush.width = Number(val);
|
canvas.freeDrawingBrush.width = Number(val);
|
||||||
$widthLabel.text(Cryptpad.Messages._getKey("canvas_widthLabel", [val]));
|
$widthLabel.text(Messages._getKey("canvas_widthLabel", [val]));
|
||||||
$('#cp-app-whiteboard-width-val').text(val + 'px');
|
$('#cp-app-whiteboard-width-val').text(val + 'px');
|
||||||
createCursor();
|
createCursor();
|
||||||
};
|
};
|
||||||
@@ -137,7 +129,7 @@ define([
|
|||||||
var val = $opacity.val();
|
var val = $opacity.val();
|
||||||
brush.opacity = Number(val);
|
brush.opacity = Number(val);
|
||||||
canvas.freeDrawingBrush.color = Colors.hex2rgba(brush.color, brush.opacity);
|
canvas.freeDrawingBrush.color = Colors.hex2rgba(brush.color, brush.opacity);
|
||||||
$opacityLabel.text(Cryptpad.Messages._getKey("canvas_opacityLabel", [val]));
|
$opacityLabel.text(Messages._getKey("canvas_opacityLabel", [val]));
|
||||||
$('#cp-app-whiteboard-opacity-val').text((Number(val) * 100) + '%');
|
$('#cp-app-whiteboard-opacity-val').text((Number(val) * 100) + '%');
|
||||||
createCursor();
|
createCursor();
|
||||||
};
|
};
|
||||||
@@ -225,7 +217,7 @@ define([
|
|||||||
|
|
||||||
var saveImage = APP.saveImage = function () {
|
var saveImage = APP.saveImage = function () {
|
||||||
var defaultName = "pretty-picture.png";
|
var defaultName = "pretty-picture.png";
|
||||||
Cryptpad.prompt(Messages.exportPrompt, defaultName, function (filename) {
|
UI.prompt(Messages.exportPrompt, defaultName, function (filename) {
|
||||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
if (!(typeof(filename) === 'string' && filename)) { return; }
|
||||||
$canvas[0].toBlob(function (blob) {
|
$canvas[0].toBlob(function (blob) {
|
||||||
saveAs(blob, filename);
|
saveAs(blob, filename);
|
||||||
@@ -406,7 +398,6 @@ define([
|
|||||||
metadataMgr: metadataMgr,
|
metadataMgr: metadataMgr,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
realtime: info.realtime,
|
realtime: info.realtime,
|
||||||
common: Cryptpad,
|
|
||||||
sfCommon: common,
|
sfCommon: common,
|
||||||
$container: $bar,
|
$container: $bar,
|
||||||
$contentContainer: $('#cp-app-whiteboard-canvas-area')
|
$contentContainer: $('#cp-app-whiteboard-canvas-area')
|
||||||
@@ -433,7 +424,7 @@ define([
|
|||||||
if (common.isLoggedIn()) {
|
if (common.isLoggedIn()) {
|
||||||
common.createButton('savetodrive', true, {}, function () {})
|
common.createButton('savetodrive', true, {}, function () {})
|
||||||
.click(function () {
|
.click(function () {
|
||||||
Cryptpad.prompt(Messages.exportPrompt, document.title + '.png',
|
UI.prompt(Messages.exportPrompt, document.title + '.png',
|
||||||
function (name) {
|
function (name) {
|
||||||
if (name === null || !name.trim()) { return; }
|
if (name === null || !name.trim()) { return; }
|
||||||
APP.upload(name);
|
APP.upload(name);
|
||||||
@@ -512,7 +503,7 @@ define([
|
|||||||
|
|
||||||
config.onReady = function (info) {
|
config.onReady = function (info) {
|
||||||
if (APP.realtime !== info.realtime) {
|
if (APP.realtime !== info.realtime) {
|
||||||
var realtime = APP.realtime = info.realtime;
|
APP.realtime = info.realtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userDoc = APP.realtime.getUserDoc();
|
var userDoc = APP.realtime.getUserDoc();
|
||||||
@@ -530,12 +521,12 @@ define([
|
|||||||
(hjson.metadata && typeof(hjson.metadata.type) !== 'undefined' &&
|
(hjson.metadata && typeof(hjson.metadata.type) !== 'undefined' &&
|
||||||
hjson.metadata.type !== 'whiteboard')) {
|
hjson.metadata.type !== 'whiteboard')) {
|
||||||
var errorText = Messages.typeError;
|
var errorText = Messages.typeError;
|
||||||
Cryptpad.errorLoadingScreen(errorText);
|
UI.errorLoadingScreen(errorText);
|
||||||
throw new Error(errorText);
|
throw new Error(errorText);
|
||||||
}
|
}
|
||||||
newDoc = hjson.content;
|
newDoc = hjson.content;
|
||||||
} else {
|
} else {
|
||||||
Title.updateTitle(Cryptpad.initialName || Title.defaultTitle);
|
Title.updateTitle(Title.defaultTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
@@ -549,7 +540,7 @@ define([
|
|||||||
setEditable(!readOnly);
|
setEditable(!readOnly);
|
||||||
initializing = false;
|
initializing = false;
|
||||||
config.onLocal();
|
config.onLocal();
|
||||||
Cryptpad.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
|
|
||||||
initThumbnails();
|
initThumbnails();
|
||||||
|
|
||||||
@@ -585,27 +576,25 @@ define([
|
|||||||
// inform of network disconnect
|
// inform of network disconnect
|
||||||
setEditable(false);
|
setEditable(false);
|
||||||
toolbar.failed();
|
toolbar.failed();
|
||||||
Cryptpad.alert(Messages.common_connectionLost, undefined, true);
|
UI.alert(Messages.common_connectionLost, undefined, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
config.onConnectionChange = function (info) {
|
config.onConnectionChange = function (info) {
|
||||||
setEditable(info.state);
|
setEditable(info.state);
|
||||||
if (info.state) {
|
if (info.state) {
|
||||||
initializing = true;
|
initializing = true;
|
||||||
Cryptpad.findOKButton().click();
|
UI.findOKButton().click();
|
||||||
} else {
|
} else {
|
||||||
Cryptpad.alert(Messages.common_connectionLost, undefined, true);
|
UI.alert(Messages.common_connectionLost, undefined, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
config.onError = onConnectError;
|
|
||||||
|
|
||||||
cpNfInner = common.startRealtime(config);
|
cpNfInner = common.startRealtime(config);
|
||||||
metadataMgr = cpNfInner.metadataMgr;
|
metadataMgr = cpNfInner.metadataMgr;
|
||||||
|
|
||||||
cpNfInner.onInfiniteSpinner(function () {
|
cpNfInner.onInfiniteSpinner(function () {
|
||||||
setEditable(false);
|
setEditable(false);
|
||||||
Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
common.gotoURL();
|
common.gotoURL();
|
||||||
});
|
});
|
||||||
@@ -622,7 +611,7 @@ define([
|
|||||||
saveImage();
|
saveImage();
|
||||||
});
|
});
|
||||||
|
|
||||||
Cryptpad.onLogout(function () { setEditable(false); });
|
common.onLogout(function () { setEditable(false); });
|
||||||
};
|
};
|
||||||
|
|
||||||
var main = function () {
|
var main = function () {
|
||||||
@@ -630,17 +619,12 @@ define([
|
|||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
$(waitFor(function () {
|
$(waitFor(function () {
|
||||||
Cryptpad.addLoadingScreen();
|
UI.addLoadingScreen();
|
||||||
var $div = $('<div>').append(Pages['/whiteboard/']());
|
var $div = $('<div>').append(Pages['/whiteboard/']());
|
||||||
$('body').append($div.html());
|
$('body').append($div.html());
|
||||||
}));
|
}));
|
||||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
Cryptpad.onError(function (info) {
|
|
||||||
if (info && info.type === "store") {
|
|
||||||
onConnectError();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
andThen(common);
|
andThen(common);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user