diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 715ab1e91..cc11f1be2 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -728,7 +728,7 @@ define([ Pages['/profile/'] = Pages['/profile/index.html'] = function () { return [ - h('div#toolbar'), + h('div#cp-toolbar'), h('div#container'), loadingScreen() ]; diff --git a/customize.dist/src/less/variables.less b/customize.dist/src/less/variables.less index 4d804abea..1d3415d89 100644 --- a/customize.dist/src/less/variables.less +++ b/customize.dist/src/less/variables.less @@ -102,9 +102,9 @@ @category-bg: #f4f4f4; -@button-bg: #3066e5; -@button-alt-bg: #fff; -@button-red-bg: #e54e4e; +@button-bg: @colortheme_sidebar-button-bg; +@button-alt-bg: @colortheme_sidebar-button-alt-bg; +@button-red-bg: @colortheme_sidebar-button-red-bg; .unselectable () { -webkit-touch-callout: none; diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index d3db9e7cd..4893f5fa2 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -79,7 +79,7 @@ @colortheme_todo-bg: #7bccd1; @colortheme_todo-color: #000; -// Sidebar layout +// Sidebar layout (profile / settings) @colortheme_sidebar-active: #fff; @colortheme_sidebar-left-bg: #eee; @colortheme_sidebar-left-fg: #000; @@ -87,7 +87,9 @@ @colortheme_sidebar-right-bg: #fff; @colortheme_sidebar-right-fg: #000; @colortheme_sidebar-description: #777; - +@colortheme_sidebar-button-bg: #3066e5; +@colortheme_sidebar-button-red-bg: #e54e4e; +@colortheme_sidebar-button-alt-bg: #fff; @cryptpad_color_blue: #4591C4; @cryptpad_color_grey: #999999; diff --git a/customize.dist/src/less2/include/sidebar-layout.less b/customize.dist/src/less2/include/sidebar-layout.less new file mode 100644 index 000000000..e0bec9dcf --- /dev/null +++ b/customize.dist/src/less2/include/sidebar-layout.less @@ -0,0 +1,99 @@ +@import (once) "/customize/src/less2/include/colortheme.less"; +@import (once) "/customize/src/less2/include/leftside-menu.less"; + +@leftside-bg: @colortheme_sidebar-left-bg; +@leftside-color: @colortheme_sidebar-left-fg; +@rightside-color: @colortheme_sidebar-right-fg; +@description-color: @colortheme_sidebar-description; + +@button-width: 400px; + + +.sidebar-layout_main() { + input[type="text"] { + padding-left: 10px; + } + #cp-sidebarlayout-container { + font-size: 16px; + display: flex; + flex: 1; + min-height: 0; + #cp-sidebarlayout-leftside { + color: @leftside-color; + width: 250px; + background: @leftside-bg; + display: flex; + flex-flow: column; + .cp-sidebarlayout-categories { + flex: 1; + .cp-sidebarlayout-category { + .leftside-menu-category_main(); + } + } + } + #cp-sidebarlayout-rightside { + flex: 1; + padding: 5px 20px; + color: @rightside-color; + overflow: auto; + + // Following rules are only in settings + .element { + label:not(.noTitle), .label { + display: block; + font-weight: bold; + margin-bottom: 0; + } + .description { + display: block; + color: @description-color; + margin-bottom: 5px; + } + margin-bottom: 20px; + } + [type="text"], button { + vertical-align: middle; + height: 40px; + box-sizing: border-box; + } + .inputBlock { + display: inline-flex; + width: @button-width; + input { + flex: 1; + border-radius: 0.25em 0 0 0.25em; + border: 1px solid #adadad; + border-right: 0px; + } + button { + border-radius: 0 0.25em 0.25em 0; + //border: 1px solid #adadad; + border-left: 0px; + } + } + &>div { + margin: 10px 0; + } + button.btn { + @button-bg: @colortheme_sidebar-button-bg; + @button-red-bg: @colortheme_sidebar-button-red-bg; + background-color: @button-bg; + border-color: darken(@button-bg, 10%); + color: white; + &:hover { + background-color: darken(@button-bg, 10%); + } + &.btn-danger { + background-color: @button-red-bg; + border-color: darken(@button-red-bg, 10%); + color: white; + &:hover { + background-color: darken(@button-red-bg, 10%); + } + } + } + } + } +} + + diff --git a/customize.dist/src/less2/main.less b/customize.dist/src/less2/main.less index c000248ba..38c242b10 100644 --- a/customize.dist/src/less2/main.less +++ b/customize.dist/src/less2/main.less @@ -34,4 +34,5 @@ body.cp-app-contacts { @import "../../../contacts/app-contacts.less"; } body.cp-app-poll { @import "../../../poll/app-poll.less"; } body.cp-app-whiteboard { @import "../../../whiteboard/app-whiteboard.less"; } body.cp-app-todo { @import "../../../todo/app-todo.less"; } +body.cp-app-profile { @import "../../../profile/app-profile.less"; } diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 06fb7f13b..9c330f651 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -44,6 +44,7 @@ define(function () { out.typing = "Édition"; out.initializing = "Initialisation..."; out.forgotten = 'Déplacé vers la corbeille'; + out.errorState = 'Erreur critique : {0}'; out.lag = 'Latence'; out.readonly = 'Lecture seule'; out.anonymous = "Anonyme"; @@ -56,6 +57,7 @@ define(function () { out.viewers = "lecteurs"; out.editor = "éditeur"; out.editors = "éditeurs"; + out.userlist_offline = "Vous êtes actuellement hors-ligne, la liste des utilisateurs n'est pas disponible."; out.language = "Langue"; @@ -486,6 +488,13 @@ define(function () { out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive"; out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles."; + out.settings_thumbnails = "Vignettes"; + out.settings_disableThumbnailsAction = "Désactiver la création de vignettes 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_resetThumbnailsAction = "Nettoyer"; + out.settings_resetThumbnailsDescription = "Nettoyer toutes les vignettes stockées dans votre navigateur."; + out.settings_resetThumbnailsDone = "Toutes les vignettes ont été effacées."; + out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive"; out.settings_import = "Importer"; out.settings_importConfirm = "Êtes-vous sûr de vouloir importer les pads récents de ce navigateur dans le CryptDrive de votre compte utilisateur ?"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 9e9531627..fbd7cdbbf 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -43,9 +43,10 @@ define(function () { out.disconnected = 'Disconnected'; out.synchronizing = 'Synchronizing'; out.reconnecting = 'Reconnecting...'; - out.typing = "Typing"; + out.typing = "Editing"; out.initializing = "Initializing..."; out.forgotten = 'Moved to the trash'; + out.errorState = 'Critical error: {0}'; out.lag = 'Lag'; out.readonly = 'Read only'; out.anonymous = "Anonymous"; @@ -58,6 +59,7 @@ define(function () { out.viewers = "viewers"; out.editor = "editor"; out.editors = "editors"; + out.userlist_offline = "You're currently offline, the user list is not available."; out.language = "Language"; @@ -491,6 +493,13 @@ define(function () { out.settings_resetTipsButton = "Reset the available tips in CryptDrive"; out.settings_resetTipsDone = "All the tips are now visible again."; + out.settings_thumbnails = "Thumbnails"; + out.settings_disableThumbnailsAction = "Disable thumbnails creation in your CryptDrive"; + out.settings_disableThumbnailsDescription = "Thumbnails are automatically created and stored in your browser when you visit a new pad. You can disable this feature here."; + out.settings_resetThumbnailsAction = "Clean"; + out.settings_resetThumbnailsDescription = "Clean all the pads thumbnails stored in your browser."; + out.settings_resetThumbnailsDone = "All the thumbnails have been erased."; + out.settings_importTitle = "Import this browser's recent pads in your CryptDrive"; out.settings_import = "Import"; out.settings_importConfirm = "Are you sure you want to import recent pads from this browser to your user account's CryptDrive?"; diff --git a/www/code/inner.js b/www/code/inner.js index 7296d07d3..5f2cf3df1 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -7,7 +7,6 @@ define([ '/common/sframe-common.js', '/common/sframe-app-framework.js', '/common/common-util.js', - '/common/common-thumbnail.js', '/common/modes.js', 'cm/lib/codemirror', @@ -46,7 +45,6 @@ define([ SFCommon, Framework, Util, - Thumb, Modes, CMeditor) { diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js index fb7edafc4..dd8e37ec0 100644 --- a/www/common/common-thumbnail.js +++ b/www/common/common-thumbnail.js @@ -1,11 +1,17 @@ define([ + '/common/common-util.js', + '/common/visible.js', + '/common/common-hash.js', + '/file/file-crypto.js', + '/bower_components/localforage/dist/localforage.min.js', '/bower_components/tweetnacl/nacl-fast.min.js', -], function () { +], function (Util, Visible, Hash, FileCrypto, localForage) { var Nacl = window.nacl; var Thumb = { dimension: 100, padDimension: 200, - UPDATE_INTERVAL: 5000 + UPDATE_INTERVAL: 60000, + UPDATE_FIRST: 5000 }; var supportedTypes = [ @@ -189,5 +195,82 @@ define([ require(['/bower_components/html2canvas/build/html2canvas.min.js'], todo); }; + Thumb.initPadThumbnails = function (opts) { + if (!opts.href || !opts.getContent) { + throw new Error("href and getContent are needed for thumbnails"); + } + var oldThumbnailState; + var mkThumbnail = function () { + var content = opts.getContent(); + if (content === oldThumbnailState) { return; } + Thumb.fromDOM(opts, function (err, b64) { + oldThumbnailState = content; + Thumb.setPadThumbnail(opts.href, b64); + }); + }; + var nafa = Util.notAgainForAnother(mkThumbnail, Thumb.UPDATE_INTERVAL); + var to; + var tUntil; + var interval = function () { + tUntil = nafa(); + if (tUntil) { + window.clearTimeout(to); + to = window.setTimeout(interval, tUntil+1); + return; + } + to = window.setTimeout(interval, Thumb.UPDATE_INTERVAL+1); + }; + Visible.onChange(function (v) { + if (v) { + window.clearTimeout(to); + return; + } + interval(); + }); + if (!Visible.currently()) { to = window.setTimeout(interval, Thumb.UPDATE_FIRST); } + }; + + var addThumbnail = function (err, thumb, $span, cb) { + var img = new Image(); + img.src = thumb.slice(0,5) === 'data:' ? thumb : 'data:;base64,'+thumb; + $span.find('.cp-icon').hide(); + $span.prepend(img); + cb($(img)); + }; + Thumb.setPadThumbnail = function (href, b64, cb) { + cb = cb || function () {}; + var k ='thumbnail-' + href; + localForage.setItem(k, b64, cb); + }; + Thumb.displayThumbnail = function (href, $container, cb) { + cb = cb || function () {}; + var parsed = Hash.parsePadUrl(href); + var k ='thumbnail-' + href; + var whenNewThumb = function () { + var secret = Hash.getSecrets('file', parsed.hash); + var hexFileName = Util.base64ToHex(secret.channel); + var src = Hash.getBlobPathFromHex(hexFileName); + var cryptKey = secret.keys && secret.keys.fileKeyStr; + var key = Nacl.util.decodeBase64(cryptKey); + FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) { + if (!metadata.thumbnail) { + return void localForage.setItem(k, 'EMPTY'); + } + localForage.setItem(k, metadata.thumbnail, function (err) { + addThumbnail(err, metadata.thumbnail, $container, cb); + }); + }); + }; + localForage.getItem(k, function (err, v) { + if (!v && parsed.type === 'file') { + // We can only create thumbnails for files here since we can't easily decrypt pads + return void whenNewThumb(); + } + if (!v) { return; } + if (v === 'EMPTY') { return; } + addThumbnail(err, v, $container, cb); + }); + }; + return Thumb; }); diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index bf446fe37..3820f3125 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -129,6 +129,7 @@ define([ var domFromHTML = function (html) { var Dom = new DOMParser().parseFromString(html, "text/html"); + Dom.normalize(); removeForbiddenTags(Dom.body); removeListeners(Dom.body); return Dom; @@ -179,6 +180,7 @@ define([ var $div = $('
', {id: id}).append(safe_newHtmlFixed); var Dom = domFromHTML($('
').append($div).html()); + $content[0].normalize(); var oldDom = domFromHTML($content[0].outerHTML); var patch = makeDiff(oldDom, Dom, id); if (typeof(patch) === 'string') { diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index 87ba6ee2c..ae0d3f3b6 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -8,7 +8,6 @@ define([ '/common/cryptpad-common.js', '/bower_components/nthen/index.js', '/common/sframe-common.js', - '/common/sframe-common-interface.js', '/customize/messages.js', '/common/common-util.js', '/common/common-thumbnail.js', @@ -27,7 +26,6 @@ define([ Cryptpad, nThen, SFCommon, - SFUI, Messages, Util, Thumb, @@ -268,24 +266,18 @@ define([ Cryptpad.removeLoadingScreen(emitResize); - if (options.thumbnail) { - var oldThumbnailState; - var privateDat = cpNfInner.metadataMgr.getPrivateData(); + var privateDat = cpNfInner.metadataMgr.getPrivateData(); + if (options.thumbnail && privateDat.thumbnails) { var hash = privateDat.availableHashes.editHash || privateDat.availableHashes.viewHash; - var href = privateDat.pathname + '#' + hash; - var mkThumbnail = function () { - if (!hash) { return; } - if (state !== STATE.READY) { return; } - if (!cpNfInner.chainpad) { return; } - var content = cpNfInner.chainpad.getUserDoc(); - if (content === oldThumbnailState) { return; } - Thumb.fromDOM(options.thumbnail, function (err, b64) { - oldThumbnailState = content; - SFUI.setPadThumbnail(href, b64); - }); - }; - window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL); + if (hash) { + options.thumbnail.href = privateDat.pathname + '#' + hash; + options.thumbnail.getContent = function () { + if (!cpNfInner.chainpad) { return; } + return cpNfInner.chainpad.getUserDoc(); + }; + Thumb.initPadThumbnails(options.thumbnail); + } } if (newPad) { @@ -422,6 +414,7 @@ define([ textPatcher = TextPatcher.create({ realtime: cpNfInner.chainpad }); + var infiniteSpinnerModal = false; window.setInterval(function () { if (state === STATE.DISCONNECTED) { return; } var l; @@ -432,13 +425,15 @@ define([ } if (l.lag < badStateTimeout) { return; } - if (state === STATE.INFINITE_SPINNER) { return; } + if (infiniteSpinnerModal) { return; } + infiniteSpinnerModal = true; stateChange(STATE.INFINITE_SPINNER); Cryptpad.confirm(Messages.realtime_unrecoverableError, function (yes) { if (!yes) { return; } common.gotoURL(); }); cpNfInner.chainpad.onSettle(function () { + infiniteSpinnerModal = false; Cryptpad.findCancelButton().click(); stateChange(STATE.READY); onRemote(); diff --git a/www/common/sframe-common-interface.js b/www/common/sframe-common-interface.js index e023e8f11..0438c896e 100644 --- a/www/common/sframe-common-interface.js +++ b/www/common/sframe-common-interface.js @@ -3,16 +3,13 @@ define([ '/api/config', '/common/cryptpad-common.js', '/common/common-util.js', - '/common/common-hash.js', '/common/media-tag.js', '/common/tippy.min.js', '/customize/application_config.js', - '/file/file-crypto.js', - '/bower_components/localforage/dist/localforage.min.js', '/bower_components/tweetnacl/nacl-fast.min.js', 'css!/common/tippy.css', -], function ($, Config, Cryptpad, Util, Hash, MediaTag, Tippy, AppConfig, FileCrypto, localForage) { +], function ($, Config, Cryptpad, Util, MediaTag, Tippy, AppConfig) { var UI = {}; var Messages = Cryptpad.Messages; var Nacl = window.nacl; @@ -33,49 +30,6 @@ define([ * - createDropdown */ - var addThumbnail = function (err, thumb, $span, cb) { - var img = new Image(); - img.src = thumb.slice(0,5) === 'data:' ? thumb : 'data:;base64,'+thumb; - $span.find('.cp-icon').hide(); - $span.prepend(img); - cb($(img)); - }; - UI.setPadThumbnail = function (href, b64, cb) { - cb = cb || $.noop; - var k ='thumbnail-' + href; - localForage.setItem(k, b64, cb); - }; - localForage.removeItem('thumbnail-/1/edit/lqg6RRnynI76LV0sR8F0YA/Nh1SNXxB5U2UjaADvODfvI5l/'); - UI.displayThumbnail = function (href, $container, cb) { - cb = cb || $.noop; - var parsed = Hash.parsePadUrl(href); - var k ='thumbnail-' + href; - var whenNewThumb = function () { - var secret = Hash.getSecrets('file', parsed.hash); - var hexFileName = Util.base64ToHex(secret.channel); - var src = Hash.getBlobPathFromHex(hexFileName); - var cryptKey = secret.keys && secret.keys.fileKeyStr; - var key = Nacl.util.decodeBase64(cryptKey); - FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) { - if (!metadata.thumbnail) { - return void localForage.setItem(k, 'EMPTY'); - } - localForage.setItem(k, metadata.thumbnail, function (err) { - addThumbnail(err, metadata.thumbnail, $container, cb); - }); - }); - }; - localForage.getItem(k, function (err, v) { - if (!v && parsed.type === 'file') { - // We can only create thumbnails for files here since we can't easily decrypt pads - return void whenNewThumb(); - } - if (!v) { return; } - if (v === 'EMPTY') { return; } - addThumbnail(err, v, $container, cb); - }); - }; - UI.updateTags = function (common, href) { var sframeChan = common.getSframeChannel(); sframeChan.query('Q_TAGS_GET', href || null, function (err, res) { @@ -339,6 +293,7 @@ define([ $img.attr('src', src); $img.attr('data-crypto-key', 'cryptpad:' + cryptKey); UI.displayMediatagImage(Common, $img, function (err, $image, img) { + if (err) { return void console.error(err); } var w = img.width; var h = img.height; if (w>h) { diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index e1ca45c3c..0f07ac8a3 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -130,6 +130,7 @@ define([ settings: proxy.settings || {}, isPresent: parsed.hashData && parsed.hashData.present, isEmbed: parsed.hashData && parsed.hashData.embed, + thumbnails: !((proxy.settings || {}).general || {}).disableThumbnails, accounts: { donateURL: Cryptpad.donateURL, upgradeURL: Cryptpad.upgradeURL diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index 19506e038..2a539e88e 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -14,7 +14,8 @@ define([ '/customize/application_config.js', '/common/cryptpad-common.js', '/common/common-realtime.js', - '/common/common-util.js' + '/common/common-util.js', + '/common/common-thumbnail.js' ], function ( $, nThen, @@ -30,7 +31,8 @@ define([ AppConfig, Cryptpad, CommonRealtime, - Util + Util, + Thumb ) { // Chainpad Netflux Inner @@ -80,7 +82,9 @@ define([ funcs.createButton = callWithCommon(UI.createButton); funcs.createUsageBar = callWithCommon(UI.createUsageBar); funcs.updateTags = callWithCommon(UI.updateTags); - funcs.displayThumbnail = UI.displayThumbnail; + + // Thumb + funcs.displayThumbnail = Thumb.displayThumbnail; // History funcs.getHistory = callWithCommon(History.create); diff --git a/www/common/sframe-protocol.js b/www/common/sframe-protocol.js index d568592ed..846502120 100644 --- a/www/common/sframe-protocol.js +++ b/www/common/sframe-protocol.js @@ -168,4 +168,8 @@ define({ // in the drive at registration. 'Q_MERGE_ANON_DRIVE': true, + // Add or remove the avatar from the profile. + // We have to pin/unpin the avatar and store/remove the value from the user object + 'Q_PROFILE_AVATAR_ADD': true, + 'Q_PROFILE_AVATAR_REMOVE': true }); diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js index be8e6399f..0b48799d2 100644 --- a/www/common/toolbar3.js +++ b/www/common/toolbar3.js @@ -154,6 +154,7 @@ define([ var $userlistContent = toolbar.userlistContent; var metadataMgr = config.metadataMgr; + var online = metadataMgr.isConnected(); var userData = metadataMgr.getMetadata().users; var viewers = metadataMgr.getViewers(); var priv = metadataMgr.getPrivateData(); @@ -184,7 +185,23 @@ define([ // Update the userlist var $editUsers = $userlistContent.find('.' + USERLIST_CLS).html(''); - var $editUsersList = $('
', {'class': 'cp-toolbar-userlist-others'}); + var $editUsersList = $('
', {'class': 'cp-toolbar-userlist-others'}) + .appendTo($editUsers); + + if (!online) { + $('').text(Messages.userlist_offline).appendTo($editUsersList); + numberOfEditUsers = '?'; + numberOfViewUsers = '?'; + } + + // Update the buttons + var fa_editusers = ''; + var fa_viewusers = ''; + var $spansmall = $('').html(fa_editusers + ' ' + numberOfEditUsers + '   ' + fa_viewusers + ' ' + numberOfViewUsers); + $userButtons.find('.cp-dropdown-button-title').html('').append($spansmall); + + if (!online) { return; } + // Display the userlist // Editors var pendingFriends = Common.getPendingFriends(); @@ -237,7 +254,6 @@ define([ $span.data('uid', data.uid); $editUsersList.append($span); }); - $editUsers.append($editUsersList); // Viewers if (numberOfViewUsers > 0) { @@ -246,12 +262,6 @@ define([ viewText += numberOfViewUsers + ' ' + viewerText + '
'; $editUsers.append(viewText); } - - // Update the buttons - var fa_editusers = ''; - var fa_viewusers = ''; - var $spansmall = $('').html(fa_editusers + ' ' + numberOfEditUsers + '   ' + fa_viewusers + ' ' + numberOfViewUsers); - $userButtons.find('.cp-dropdown-button-title').html('').append($spansmall); }; var initUserList = function (toolbar, config) { @@ -691,6 +701,7 @@ define([ var typing = -1; var kickSpinner = function (toolbar, config/*, local*/) { if (!toolbar.spinner) { return; } + if (toolbar.isErrorState) { return; } var $spin = toolbar.spinner; if (typing === -1) { @@ -1050,6 +1061,17 @@ define([ } }; + toolbar.errorState = function (state, error) { + toolbar.isErrorState = state; + if (toolbar.spinner) { + if (!state) { + return void kickSpinner(toolbar, config); + } + var txt = Messages._getKey('errorState', [error]); + toolbar.spinner.text(txt); + } + }; + // When the pad is moved to the trash (forget button) toolbar.forgotten = function (/*userId*/) { toolbar.connected = false; diff --git a/www/filepicker/app-filepicker.less b/www/filepicker/app-filepicker.less index 69e92d69d..a28ec8008 100644 --- a/www/filepicker/app-filepicker.less +++ b/www/filepicker/app-filepicker.less @@ -47,6 +47,11 @@ align-items: center; + img { + max-width: 100px; + max-height: 100px; + } + .cp-filepicker-content-element-name { overflow: hidden; text-overflow: ellipsis; diff --git a/www/oldprofile/index.html b/www/oldprofile/index.html new file mode 100644 index 000000000..5200564ce --- /dev/null +++ b/www/oldprofile/index.html @@ -0,0 +1,20 @@ + + + + + CryptPad: Zero Knowledge, Collaborative Real Time Editing + + + + + + + + + + + + diff --git a/www/oldprofile/main.js b/www/oldprofile/main.js new file mode 100644 index 000000000..ef2ac9a81 --- /dev/null +++ b/www/oldprofile/main.js @@ -0,0 +1,532 @@ +require.config({ + paths: { + cm: '/bower_components/codemirror' + } +}); +define([ + 'jquery', + '/common/cryptpad-common.js', + '/bower_components/chainpad-listmap/chainpad-listmap.js', + '/bower_components/chainpad-crypto/crypto.js', + '/bower_components/marked/marked.min.js', + '/common/toolbar2.js', + 'cm/lib/codemirror', + 'cm/mode/markdown/markdown', + 'less!/profile/main.less', + 'less!/customize/src/less/toolbar.less', + 'less!/customize/src/less/cryptpad.less', + 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', +], function ($, Cryptpad, Listmap, Crypto, Marked, Toolbar, CodeMirror) { + + var APP = window.APP = { + Cryptpad: Cryptpad, + _onRefresh: [] + }; + + $(window.document).on('decryption', function (e) { + var decrypted = e.originalEvent; + if (decrypted.callback) { decrypted.callback(); } + }) + .on('decryptionError', function (e) { + var error = e.originalEvent; + Cryptpad.alert(error.message); + }); + + // Marked + var renderer = new Marked.Renderer(); + Marked.setOptions({ + renderer: renderer, + sanitize: true + }); + // Tasks list + var checkedTaskItemPtn = /^\s*\[x\]\s*/; + var uncheckedTaskItemPtn = /^\s*\[ \]\s*/; + renderer.listitem = function (text) { + var isCheckedTaskItem = checkedTaskItemPtn.test(text); + var isUncheckedTaskItem = uncheckedTaskItemPtn.test(text); + if (isCheckedTaskItem) { + text = text.replace(checkedTaskItemPtn, + ' ') + '\n'; + } + if (isUncheckedTaskItem) { + text = text.replace(uncheckedTaskItemPtn, + ' ') + '\n'; + } + var cls = (isCheckedTaskItem || isUncheckedTaskItem) ? ' class="todo-list-item"' : ''; + return '' + text + '\n'; + }; + /*renderer.image = function (href, title, text) { + if (href.slice(0,6) === '/file/') { + var parsed = Cryptpad.parsePadUrl(href); + var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel); + var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName; + var mt = ''; + mt += ''; + return mt; + } + var out = '' + text + '' : '>'; + return out; + };*/ + + var Messages = Cryptpad.Messages; + + var DISPLAYNAME_ID = "displayName"; + var LINK_ID = "link"; + var AVATAR_ID = "avatar"; + var DESCRIPTION_ID = "description"; + var PUBKEY_ID = "pubKey"; + var CREATE_ID = "createProfile"; + var HEADER_ID = "header"; + var HEADER_RIGHT_ID = "rightside"; + var CREATE_INVITE_BUTTON = 'inviteButton'; /* jshint ignore: line */ + var VIEW_PROFILE_BUTTON = 'viewProfileButton'; + + var createEditableInput = function ($block, name, ph, getValue, setValue, realtime, fallbackValue) { + fallbackValue = fallbackValue || ''; // don't ever display 'null' or 'undefined' + var lastVal; + getValue(function (value) { + lastVal = value; + var $input = $('', { + 'id': name+'Input', + placeholder: ph + }).val(value); + var $icon = $('', {'class': 'fa fa-pencil edit'}); + var editing = false; + var todo = function () { + if (editing) { return; } + editing = true; + + var newVal = $input.val().trim(); + + if (newVal === lastVal) { + editing = false; + return; + } + + setValue(newVal, function (err) { + if (err) { return void console.error(err); } + Cryptpad.whenRealtimeSyncs(realtime, function () { + lastVal = newVal; + Cryptpad.log(Messages._getKey('profile_fieldSaved', [newVal || fallbackValue])); + editing = false; + }); + }); + }; + $input.on('keyup', function (e) { + if (e.which === 13) { return void todo(); } + if (e.which === 27) { + $input.val(lastVal); + } + }); + $icon.click(function () { $input.focus(); }); + $input.focus(function () { + $input.width(''); + }); + $input.focusout(todo); + $block.append($input).append($icon); + }); + }; + +/* jshint ignore:start */ + var isFriend = function (proxy, edKey) { + var friends = Cryptpad.find(proxy, ['friends']); + return typeof(edKey) === 'string' && friends && (edKey in friends); + }; + + var addCreateInviteLinkButton = function ($container) { + return; + var obj = APP.lm.proxy; + + var proxy = Cryptpad.getProxy(); + var userViewHash = Cryptpad.find(proxy, ['profile', 'view']); + + var edKey = obj.edKey; + var curveKey = obj.curveKey; + + if (!APP.readOnly || !curveKey || !edKey || userViewHash === window.location.hash.slice(1) || isFriend(proxy, edKey)) { + //console.log("edit mode or missing curve key, or you're viewing your own profile"); + return; + } + + // sanitize user inputs + + var unsafeName = obj.name || ''; + console.log(unsafeName); + var name = Cryptpad.fixHTML(unsafeName) || Messages.anonymous; + console.log(name); + + console.log("Creating invite button"); + $("