Manual merge of notify.js
This commit is contained in:
commit
2ad9fcee17
13 files changed
+84
-47
No files matched your search
@@ -600,6 +600,7 @@ noscript {
|
||||
width: ~"calc(100% - 6px)";
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
overflow: hidden;
|
||||
.usage {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
|
||||
@@ -685,13 +685,13 @@ define(function () {
|
||||
|
||||
// Tips
|
||||
out.tips = {};
|
||||
out.tips.lag = "The green icon in the upper right shows the quality of your internet connection to the CryptPad server.";
|
||||
out.tips.shortcuts = "`ctrl+b`, `ctrl+i` and `ctrl+u` are quick shortcuts for bold, italic and underline.";
|
||||
out.tips.indent = "In numbered and bulleted lists, you can use tab or shift+tab to quickly increase or decrease indentation.";
|
||||
out.tips.title = "You can set the title of your pad by clicking the top center.";
|
||||
out.tips.store = "Every time you visit a pad, if you're logged in it will be saved to your CryptDrive.";
|
||||
out.tips.marker = "You can highlight text in a pad using the \"marker\" item in the styles dropdown menu.";
|
||||
out.tips.driveUpload = "Registered users can upload encrypted files by dragging and dropping them into their CryptDrive.";
|
||||
out.tips.filenames = "You can rename files in your CryptDrive, this name is just for you.";
|
||||
out.tips.drive = "Logged in users can organize their files in their CryptDrive, accessible from the CryptPad icon at the top left of all pads.";
|
||||
|
||||
out.feedback_about = "If you're reading this, you were probably curious why CryptPad is requesting web pages when you perform certain actions";
|
||||
out.feedback_privacy = "We care about your privacy, and at the same time we want CryptPad to be very easy to use. We use this file to figure out which UI features matter to our users, by requesting it along with a parameter specifying which action was taken.";
|
||||
|
||||
@@ -256,7 +256,7 @@ define([
|
||||
var $friend = ui.getFriend(curvePublic);
|
||||
var $chat = ui.getChannel(curvePublic);
|
||||
$friend.remove();
|
||||
$chat.remove();
|
||||
if ($chat) { $chat.remove(); }
|
||||
ui.showInfo();
|
||||
};
|
||||
|
||||
@@ -892,7 +892,7 @@ define([
|
||||
var addToFriendList = Msg.addToFriendList = function (common, data, cb) {
|
||||
var proxy = common.getProxy();
|
||||
var friends = getFriendList(proxy);
|
||||
var pubKey = data.curvePublic;
|
||||
var pubKey = data.curvePublic; // todo validata data
|
||||
|
||||
if (pubKey === proxy.curvePublic) { return void cb("E_MYKEY"); }
|
||||
|
||||
@@ -938,7 +938,7 @@ define([
|
||||
var todo = function (yes) {
|
||||
if (yes) {
|
||||
pending[sender] = msgData;
|
||||
msg = ["FRIEND_REQ_OK", chan, createData(common, msgData.channel)];
|
||||
msg = ["FRIEND_REQ_OK", chan, createData(proxy, msgData.channel)];
|
||||
}
|
||||
msgStr = Crypto.encrypt(JSON.stringify(msg), key);
|
||||
network.sendto(sender, msgStr);
|
||||
@@ -1005,7 +1005,7 @@ define([
|
||||
if (!parsed.hashData) { return; }
|
||||
// Message
|
||||
var chan = parsed.hashData.channel;
|
||||
var myData = createData(common);
|
||||
var myData = createData(common.getProxy());
|
||||
var msg = ["FRIEND_REQ", chan, myData];
|
||||
// Encryption
|
||||
var keyStr = parsed.hashData.key;
|
||||
|
||||
@@ -8,6 +8,8 @@ define([
|
||||
var BAD_STATE_TIMEOUT = typeof(AppConfig.badStateTimeout) === 'number'?
|
||||
AppConfig.badStateTimeout: 30000;
|
||||
|
||||
var connected = false;
|
||||
|
||||
/*
|
||||
TODO make this not blow up when disconnected or lagging...
|
||||
*/
|
||||
@@ -20,6 +22,7 @@ define([
|
||||
}
|
||||
|
||||
var to = setTimeout(function () {
|
||||
if (!connected) { return; }
|
||||
realtime.abort();
|
||||
// don't launch more than one popup
|
||||
if (common.infiniteSpinnerDetected) { return; }
|
||||
@@ -38,5 +41,10 @@ define([
|
||||
}, 0);
|
||||
};
|
||||
|
||||
common.setConnectionState = function (bool) {
|
||||
if (typeof(bool) !== 'boolean') { return; }
|
||||
connected = bool;
|
||||
};
|
||||
|
||||
return common;
|
||||
});
|
||||
@@ -581,6 +581,7 @@ define([
|
||||
_onDisplayNameChanged.forEach(function (h) {
|
||||
h(newName, isLocal);
|
||||
});
|
||||
common.clearTooltips();
|
||||
};
|
||||
|
||||
// STORAGE
|
||||
@@ -1905,12 +1906,18 @@ define([
|
||||
|
||||
Store.ready(function (err, storeObj) {
|
||||
store = common.store = env.store = storeObj;
|
||||
|
||||
common.addDirectMessageHandler(common);
|
||||
|
||||
var proxy = getProxy();
|
||||
var network = getNetwork();
|
||||
|
||||
network.on('disconnect', function () {
|
||||
Realtime.setConnectionState(false);
|
||||
});
|
||||
network.on('reconnect', function () {
|
||||
Realtime.setConnectionState(true);
|
||||
});
|
||||
|
||||
if (Object.keys(proxy).length === 1) {
|
||||
feedback("FIRST_APP_USE", true);
|
||||
}
|
||||
|
||||
+23
-13
@@ -50,25 +50,35 @@ define([
|
||||
};
|
||||
|
||||
Curve.deriveKeys = function (theirs, mine) {
|
||||
var pub = decodeBase64(theirs);
|
||||
var secret = decodeBase64(mine);
|
||||
try {
|
||||
var pub = decodeBase64(theirs);
|
||||
var secret = decodeBase64(mine);
|
||||
|
||||
var sharedSecret = Nacl.box.before(pub, secret);
|
||||
var salt = decodeUTF8('CryptPad.signingKeyGenerationSalt');
|
||||
var sharedSecret = Nacl.box.before(pub, secret);
|
||||
var salt = decodeUTF8('CryptPad.signingKeyGenerationSalt');
|
||||
|
||||
// 64 uint8s
|
||||
var hash = Nacl.hash(concatenateUint8s([salt, sharedSecret]));
|
||||
var signKp = Nacl.sign.keyPair.fromSeed(hash.subarray(0, 32));
|
||||
var cryptKey = hash.subarray(32, 64);
|
||||
// 64 uint8s
|
||||
var hash = Nacl.hash(concatenateUint8s([salt, sharedSecret]));
|
||||
var signKp = Nacl.sign.keyPair.fromSeed(hash.subarray(0, 32));
|
||||
var cryptKey = hash.subarray(32, 64);
|
||||
|
||||
return {
|
||||
cryptKey: encodeBase64(cryptKey),
|
||||
signKey: encodeBase64(signKp.secretKey),
|
||||
validateKey: encodeBase64(signKp.publicKey)
|
||||
};
|
||||
return {
|
||||
cryptKey: encodeBase64(cryptKey),
|
||||
signKey: encodeBase64(signKp.secretKey),
|
||||
validateKey: encodeBase64(signKp.publicKey)
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('invalid keys or other problem deriving keys');
|
||||
console.error(e);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
Curve.createEncryptor = function (keys) {
|
||||
if (!keys || typeof(keys) !== 'object') {
|
||||
return void console.error("invalid input for createEncryptor");
|
||||
}
|
||||
|
||||
var cryptKey = decodeBase64(keys.cryptKey);
|
||||
var signKey = decodeBase64(keys.signKey);
|
||||
var validateKey = decodeBase64(keys.validateKey);
|
||||
|
||||
@@ -1 +1 @@
|
||||
(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory();else if(typeof define==="function"&&define.amd)define([],factory);else if(typeof exports==="object")exports["MediaTag"]=factory();else root["MediaTag"]=factory()})(this,function(){return function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.i=function(value){return value};__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{configurable:false,enumerable:true,get:getter})}};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module["default"]}:function getModuleExports(){return module};__webpack_require__.d(getter,"a",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p="";return __webpack_require__(__webpack_require__.s=95)}([function(module,exports,__webpack_require__){"use strict";var Identifier={IMAGE:"image",AUDIO:"audio",VIDEO:"video",PDF:"pdf",DASH:"dash",DOWNLOAD:"download",CRYPTO:"crypto",CLEAR_KEY:"clear-key",MEDIA_OBJECT:"media-object"};module.exports=Identifier},function(module,exports,__webpack_require__){"use strict";var Type={MATCHER:"matcher",RENDERER:"renderer",FILTER:"filter",SANITIZER:"sanitizer"};module.exports=Type},function(module,exports,__webpack_require__){"use strict";var ProcessingEngine=__webpack_require__(34);var MatchingEngine=__webpack_require__(33);var PluginStore=__webpack_require__(53);var UriStore=__webpack_require__(54);var MediaTag=__webpack_require__(31);function MediaTagAPI(elements){if(elements instanceof Array){var mediaObjects=[];elements.forEach(function(element){if(element.mediaObject){mediaObjects.push(element.mediaObject)}else{var _mediaTag=new MediaTag(element,MediaTagAPI.processingEngine);_mediaTag.mediaObjects.forEach(function(mediaObject){mediaObjects.push(MediaTagAPI.processingEngine.start(mediaObject))})}});return mediaObjects}var element=elements;var mediaTag=new MediaTag(element,MediaTagAPI.processingEngine);mediaTag.mediaObjects.forEach(function(mediaObject){MediaTagAPI.processingEngine.start(mediaObject)})}MediaTagAPI.pluginStore=MediaTagAPI.pluginStore||new PluginStore;MediaTagAPI.uriStore=MediaTagAPI.uriStore||new UriStore("../plugins");MediaTagAPI.processingEngine=MediaTagAPI.processingEngine||new ProcessingEngine(MediaTagAPI.pluginStore);MediaTagAPI.matchingEngine=MediaTagAPI.matchingEngine||new MatchingEngine(MediaTagAPI.pluginStore,MediaTagAPI.uriStore);MediaTagAPI.loadingEngine=null;module.exports=MediaTagAPI},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor}}();function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return call&&(typeof call==="object"||typeof call==="function")?call:self}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass)}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass}var Type=__webpack_require__(1);var Occurrence=__webpack_require__(5);var Plugin=__webpack_require__(6);var Matcher=function(_Plugin){_inherits(Matcher,_Plugin);function Matcher(identifier,targetType){_classCallCheck(this,Matcher);var _this=_possibleConstructorReturn(this,(Matcher.__proto__||Object.getPrototypeOf(Matcher)).call(this,identifier,Type.MATCHER,Occurrence.ANY));_this.targetType=targetType;return _this}_createClass(Matcher,[{key:"getTargetType",value:function getTargetType(){return this.targetType}}]);return Matcher}(Plugin);module.exports=Matcher},funcLine truncated
|
||||
(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory();else if(typeof define==="function"&&define.amd)define([],factory);else if(typeof exports==="object")exports["MediaTag"]=factory();else root["MediaTag"]=factory()})(this,function(){return function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{configurable:false,enumerable:true,get:getter})}};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module["default"]}:function getModuleExports(){return module};__webpack_require__.d(getter,"a",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p="";return __webpack_require__(__webpack_require__.s=63)}([function(module,exports,__webpack_require__){"use strict";var Identifier={IMAGE:"image",AUDIO:"audio",VIDEO:"video",PDF:"pdf",DASH:"dash",DOWNLOAD:"download",CRYPTO:"crypto",CLEAR_KEY:"clear-key",MEDIA_OBJECT:"media-object"};module.exports=Identifier},function(module,exports,__webpack_require__){"use strict";var Type={MATCHER:"matcher",RENDERER:"renderer",FILTER:"filter",SANITIZER:"sanitizer"};module.exports=Type},function(module,exports,__webpack_require__){"use strict";var ProcessingEngine=__webpack_require__(31);var MatchingEngine=__webpack_require__(33);var PluginStore=__webpack_require__(34);var UriStore=__webpack_require__(35);var MediaTag=__webpack_require__(36);function MediaTagAPI(elements){if(elements instanceof Array){var mediaObjects=[];elements.forEach(function(element){if(element.mediaObject){mediaObjects.push(element.mediaObject)}else{var _mediaTag=new MediaTag(element,MediaTagAPI.processingEngine);_mediaTag.mediaObjects.forEach(function(mediaObject){mediaObjects.push(MediaTagAPI.processingEngine.start(mediaObject))})}});return mediaObjects}var element=elements;var mediaTag=new MediaTag(element,MediaTagAPI.processingEngine);mediaTag.mediaObjects.forEach(function(mediaObject){MediaTagAPI.processingEngine.start(mediaObject)})}MediaTagAPI.pluginStore=MediaTagAPI.pluginStore||new PluginStore;MediaTagAPI.uriStore=MediaTagAPI.uriStore||new UriStore("../plugins");MediaTagAPI.processingEngine=MediaTagAPI.processingEngine||new ProcessingEngine(MediaTagAPI.pluginStore);MediaTagAPI.matchingEngine=MediaTagAPI.matchingEngine||new MatchingEngine(MediaTagAPI.pluginStore,MediaTagAPI.uriStore);MediaTagAPI.loadingEngine=null;module.exports=MediaTagAPI},function(module,exports,__webpack_require__){"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor}}();function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return call&&(typeof call==="object"||typeof call==="function")?call:self}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass)}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass}var Type=__webpack_require__(1);var Occurrence=__webpack_require__(5);var Plugin=__webpack_require__(6);var Matcher=function(_Plugin){_inherits(Matcher,_Plugin);function Matcher(identifier,targetType){_classCallCheck(this,Matcher);var _this=_possibleConstructorReturn(this,(Matcher.__proto__||Object.getPrototypeOf(Matcher)).call(this,identifier,Type.MATCHER,Occurrence.ANY));_this.targetType=targetType;return _this}_createClass(Matcher,[{key:"getTargetType",value:function getTargetType(){return this.targetType}}]);return Matcher}(Plugin);module.exports=Matcher},function(module,exports,__webpack_require__){"use stricLine truncated
|
||||
@@ -110,6 +110,8 @@ define(['/api/config'], function (ApiConfig) {
|
||||
cancel: cancel,
|
||||
};
|
||||
};
|
||||
return Module;
|
||||
};
|
||||
|
||||
return Module;
|
||||
});
|
||||
@@ -341,25 +341,14 @@ function isDataSchema(url) {
|
||||
return url.substr(i, 5).toLowerCase() === 'data:';
|
||||
}
|
||||
function getPDFFileNameFromURL(url) {
|
||||
var defaultFilename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'document.pdf';
|
||||
|
||||
if (isDataSchema(url)) {
|
||||
console.warn('getPDFFileNameFromURL: ' + 'ignoring "data:" URL for performance reasons.');
|
||||
return defaultFilename;
|
||||
var query;
|
||||
var title;
|
||||
if (/\#/.test(url)) {
|
||||
url.replace(/\#(.*)$/, function (all, t) {
|
||||
title = t;
|
||||
});
|
||||
}
|
||||
var reURI = /^(?:(?:[^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
|
||||
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
|
||||
var splitURI = reURI.exec(url);
|
||||
var suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
|
||||
if (suggestedFilename) {
|
||||
suggestedFilename = suggestedFilename[0];
|
||||
if (suggestedFilename.indexOf('%') !== -1) {
|
||||
try {
|
||||
suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
return suggestedFilename || defaultFilename;
|
||||
return title || 'document.pdf';
|
||||
}
|
||||
function normalizeWheelEventDelta(evt) {
|
||||
var delta = Math.sqrt(evt.deltaX * evt.deltaX + evt.deltaY * evt.deltaY);
|
||||
@@ -1192,11 +1181,13 @@ var PDFViewerApplication = {
|
||||
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
||||
this.url = url;
|
||||
this.baseUrl = url.split('#')[0];
|
||||
var title = (0, _ui_utils.getPDFFileNameFromURL)(url, '');
|
||||
|
||||
var title = _ui_utils.getPDFFileNameFromURL(url);
|
||||
if (!title) {
|
||||
try {
|
||||
title = decodeURIComponent((0, _pdfjsLib.getFilenameFromUrl)(url)) || url;
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
title = url;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ body {
|
||||
}
|
||||
|
||||
#app.ready {
|
||||
background: url('/customize/bg3.jpg') no-repeat center center;
|
||||
//background: url('/customize/bg3.jpg') no-repeat center center;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
+22
-4
@@ -91,7 +91,14 @@ define([
|
||||
Title.updateTitle(title || Title.defaultTitle);
|
||||
toolbar.addElement(['pageTitle'], {pageTitle: title});
|
||||
|
||||
var displayFile = function (ev, sizeMb) {
|
||||
var displayFile = function (ev, sizeMb, CB) {
|
||||
var called_back;
|
||||
var cb = function (e) {
|
||||
if (called_back) { return; }
|
||||
called_back = true;
|
||||
if (CB) { CB(e); }
|
||||
};
|
||||
|
||||
var $mt = $dlview.find('media-tag');
|
||||
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||
var hexFileName = Cryptpad.base64ToHex(secret.channel);
|
||||
@@ -127,7 +134,7 @@ define([
|
||||
|
||||
// make pdfs big
|
||||
var toolbarHeight = $iframe.find('#toolbar').height();
|
||||
$iframe.find('media-tag iframe').css({
|
||||
var $another_iframe = $iframe.find('media-tag iframe').css({
|
||||
'height': 'calc(100vh - ' + toolbarHeight + 'px)',
|
||||
'width': '100vw',
|
||||
'position': 'absolute',
|
||||
@@ -135,10 +142,19 @@ define([
|
||||
'left': 0,
|
||||
'border': 0
|
||||
});
|
||||
|
||||
if ($another_iframe.length) {
|
||||
$another_iframe.load(function () {
|
||||
cb();
|
||||
});
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
})
|
||||
.on('decryptionError', function (e) {
|
||||
var error = e.originalEvent;
|
||||
Cryptpad.alert(error.message);
|
||||
//Cryptpad.alert(error.message);
|
||||
cb(error.message);
|
||||
})
|
||||
.on('decryptionProgress', function (e) {
|
||||
var progress = e.originalEvent;
|
||||
@@ -188,7 +204,9 @@ define([
|
||||
var onClick = function (ev) {
|
||||
if (decrypting) { return; }
|
||||
decrypting = true;
|
||||
displayFile(ev, sizeMb);
|
||||
displayFile(ev, sizeMb, function (err) {
|
||||
if (err) { Cryptpad.alert(err); }
|
||||
});
|
||||
};
|
||||
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
|
||||
$dlform.find('#dl, #progress').click(onClick);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<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>
|
||||
<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"/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<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>
|
||||
<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"/>
|
||||
|
||||
Reference in new issue
Block a user