diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index ac51611e2..e82df349f 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -76,9 +76,11 @@ define(function () { out.backgroundButtonTitle = 'Changer la couleur de fond de la présentation'; out.colorButtonTitle = 'Changer la couleur du texte en mode présentation'; - out.editShare = "Partager le lien d'édition"; + out.editShare = "Lien d'édition"; out.editShareTitle = "Copier le lien d'édition dans le presse-papiers"; - out.viewShare = "Partager lien de lecture-seule"; + out.editOpen = "Éditer dans un nouvel onglet"; + out.editOpenTitle = "Ouvrir le lien d'édition dans un nouvel onglet"; + out.viewShare = "Lien de lecture-seule"; out.viewShareTitle = "Copier lien d'accès en lecture seule dans le presse-papiers"; out.viewOpen = "Voir dans un nouvel onglet"; out.viewOpenTitle = "Ouvrir le lien en lecture seule dans un nouvel onglet"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index d04b3d015..2b604b662 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -80,9 +80,11 @@ define(function () { out.editShare = "Editing link"; out.editShareTitle = "Copy the editing link to clipboard"; + out.editOpen = "Open editing link in a new tab"; + out.editOpenTitle = "Open this pad in editing mode in a new tab"; out.viewShare = "Read-only link"; out.viewShareTitle = "Copy the read-only link to clipboard"; - out.viewOpen = "Open read-only link in new tab"; + out.viewOpen = "Open read-only link in a new tab"; out.viewOpenTitle = "Open this pad in read-only mode in a new tab"; out.notifyJoined = "{0} has joined the collaborative session"; diff --git a/www/code/main.js b/www/code/main.js index 9a8e57ccc..6ed315e82 100644 --- a/www/code/main.js +++ b/www/code/main.js @@ -374,6 +374,10 @@ define([ userData: userData, readOnly: readOnly, ifrw: ifrw, + share: { + secret: secret, + channel: info.channel + }, title: { onRename: renameCb, defaultName: defaultName, @@ -386,8 +390,6 @@ define([ var $rightside = $bar.find('.' + Toolbar.constants.rightside); var $userBlock = $bar.find('.' + Toolbar.constants.username); - var $editShare = $bar.find('.' + Toolbar.constants.editShare); - var $viewShare = $bar.find('.' + Toolbar.constants.viewShare); var $usernameButton = module.$userNameButton = $($bar.find('.' + Toolbar.constants.changeUsername)); var editHash; @@ -419,17 +421,6 @@ define([ var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb); $rightside.append($forgetPad); - if (!readOnly) { - $editShare.append(Cryptpad.createButton('editshare', false, {editHash: editHash})); - } - if (viewHash) { - /* add a 'links' button */ - $viewShare.append(Cryptpad.createButton('viewshare', false, {viewHash: viewHash})); - if (!readOnly) { - $viewShare.append(Cryptpad.createButton('viewopen', false, {viewHash: viewHash})); - } - } - var configureLanguage = function (cb) { // FIXME this is async so make it happen as early as possible var options = []; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 255d95653..eddebd105 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -22,6 +22,7 @@ define([ var common = window.Cryptpad = { Messages: Messages, Alertify: Alertify, + Clipboard: Clipboard }; var store; @@ -223,6 +224,7 @@ define([ if (typeof keys === 'string') { return chanKey + keys; } + if (!keys.editKeyStr) { return; } return '/1/edit/' + hexToBase64(chanKey) + '/' + Crypto.b64RemoveSlashes(keys.editKeyStr); }; var getViewHashFromKeys = common.getViewHashFromKeys = function (chanKey, keys) { @@ -304,6 +306,18 @@ define([ return secret; }; + var getHashes = common.getHashes = function (channel, secret) { + var hashes = {}; + if (secret.keys.editKeyStr) { + hashes.editHash = getEditHashFromKeys(channel, secret.keys); + } + if (secret.keys.viewKeyStr) { + hashes.viewHash = getViewHashFromKeys(channel, secret.keys); + } + return hashes; + }; + + var uint8ArrayToHex = common.uint8ArrayToHex = function (a) { // call slice so Uint8Arrays work as expected return Array.prototype.slice.call(a).map(function (e, i) { @@ -607,22 +621,30 @@ define([ }; // STORAGE - var isNotStrongestStored = common.isNotStrongestStored = function (href, recents) { - var parsed = parsePadUrl(href); + var findStronger = common.findStronger = function (href, recents) { + var rHref = href || getRelativeHref(window.location.href); + var parsed = parsePadUrl(rHref); if (!parsed.hash) { return false; } - return recents.some(function (pad) { + var stronger; + recents.some(function (pad) { var p = parsePadUrl(pad.href); - if (p.type !== parsed.type) { return false; } // Not the same type - if (p.hash === parsed.hash) { return false; } // Same hash, not stronger + if (p.type !== parsed.type) { return; } // Not the same type + if (p.hash === parsed.hash) { return; } // Same hash, not stronger var pHash = parseHash(p.hash); var parsedHash = parseHash(parsed.hash); if (!parsedHash || !pHash) { return; } - if (pHash.version !== parsedHash.version) { return false; } - if (pHash.channel !== parsedHash.channel) { return false; } - if (pHash.mode === 'edit' && parsedHash.mode === 'view') { return true; } - if (pHash.mode === parsedHash.mode && parsedHash.present) { return true; } - return false; + if (pHash.version !== parsedHash.version) { return; } + if (pHash.channel !== parsedHash.channel) { return; } + if (pHash.mode === 'edit' && parsedHash.mode === 'view') { + stronger = pad.href; + return true; + } + return; }); + return stronger; + }; + var isNotStrongestStored = common.isNotStrongestStored = function (href, recents) { + return findStronger(href, recents); }; var setPadTitle = common.setPadTitle = function (name, cb) { var href = window.location.href; @@ -986,6 +1008,7 @@ define([ }); } break; + // TODO remove editshare, viewshare, and viewopen case 'editshare': button = $('', { title: Messages.editShareTitle, diff --git a/www/common/toolbar.js b/www/common/toolbar.js index ac68e27eb..9f99e1046 100644 --- a/www/common/toolbar.js +++ b/www/common/toolbar.js @@ -123,16 +123,89 @@ define([ // Share button if (config.displayed.indexOf('share') !== -1) { - var $shareIcon = $('', {'class': 'fa fa-share-alt'}); - var $span = $('', {'class': 'large'}).append(' ' +Messages.shareButton); - var dropdownConfigShare = { - text: $('
').append($shareIcon).append($span).html(), - 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); + 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 = $('', {'class': 'fa fa-share-alt'}); + var $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: ' ' + 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: ' ' + Messages.editOpen + }); + } + options.push({tag: 'hr'}); + } + if (hashes.viewHash) { + options.push({ + tag: 'a', + attributes: {title: Messages.viewShareTitle, 'class': 'viewShare'}, + content: ' ' + 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: ' ' + Messages.viewOpen + }); + } + } + var dropdownConfigShare = { + text: $('
').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); } + }); + } + }); } }; diff --git a/www/pad/main.js b/www/pad/main.js index c72ef815e..4e04c8c2e 100644 --- a/www/pad/main.js +++ b/www/pad/main.js @@ -561,6 +561,10 @@ define([ userData: userData, readOnly: readOnly, ifrw: ifrw, + share: { + secret: secret, + channel: info.channel + }, title: { onRename: renameCb, defaultName: defaultName, @@ -573,8 +577,6 @@ define([ var $rightside = $bar.find('.' + Toolbar.constants.rightside); var $userBlock = $bar.find('.' + Toolbar.constants.username); - var $editShare = $bar.find('.' + Toolbar.constants.editShare); - var $viewShare = $bar.find('.' + Toolbar.constants.viewShare); var $usernameButton = module.$userNameButton = $($bar.find('.' + Toolbar.constants.changeUsername)); var editHash; @@ -625,20 +627,6 @@ define([ var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb); $rightside.append($forgetPad); - if (!readOnly) { - $editShare.append(Cryptpad.createButton('editshare', false, {editHash: editHash})); - if (viewHash) { - $editShare.append($('
')); - } - } - if (viewHash) { - /* add a 'links' button */ - $viewShare.append(Cryptpad.createButton('viewshare', false, {viewHash: viewHash})); - if (!readOnly) { - $viewShare.append(Cryptpad.createButton('viewopen', false, {viewHash: viewHash})); - } - } - // set the hash if (!readOnly) { Cryptpad.replaceHash(editHash); } diff --git a/www/poll/main.js b/www/poll/main.js index 98f5ea9ba..237581713 100644 --- a/www/poll/main.js +++ b/www/poll/main.js @@ -687,6 +687,10 @@ define([ displayed: ['useradmin', 'language', 'spinner', 'lag', 'state', 'share', 'userlist', 'newpad'], userData: userData, readOnly: readOnly, + share: { + secret: secret, + channel: info.channel + }, title: { onRename: renameCb, defaultName: defaultName, @@ -712,17 +716,6 @@ define([ var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb); $rightside.append($forgetPad); - if (!readOnly) { - $editShare.append(Cryptpad.createButton('editshare', false, {editHash: editHash})); - } - if (viewHash) { - /* add a 'links' button */ - $viewShare.append(Cryptpad.createButton('viewshare', false, {viewHash: viewHash})); - if (!readOnly) { - $viewShare.append(Cryptpad.createButton('viewopen', false, {viewHash: viewHash})); - } - } - // set the hash if (!readOnly) { Cryptpad.replaceHash(editHash); } diff --git a/www/slide/main.js b/www/slide/main.js index 7127a38bf..bc3defec6 100644 --- a/www/slide/main.js +++ b/www/slide/main.js @@ -417,6 +417,10 @@ define([ userData: userData, readOnly: readOnly, ifrw: ifrw, + share: { + secret: secret, + channel: info.channel + }, title: { onRename: renameCb, defaultName: defaultName, @@ -429,8 +433,6 @@ define([ var $rightside = $bar.find('.' + Toolbar.constants.rightside); var $userBlock = $bar.find('.' + Toolbar.constants.username); - var $editShare = $bar.find('.' + Toolbar.constants.editShare); - var $viewShare = $bar.find('.' + Toolbar.constants.viewShare); var $usernameButton = module.$userNameButton = $($bar.find('.' + Toolbar.constants.changeUsername)); var editHash; @@ -462,17 +464,6 @@ define([ var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb); $rightside.append($forgetPad); - if (!readOnly) { - $editShare.append(Cryptpad.createButton('editshare', false, {editHash: editHash})); - } - if (viewHash) { - /* add a 'links' button */ - $viewShare.append(Cryptpad.createButton('viewshare', false, {viewHash: viewHash + '/present'})); - if (!readOnly) { - $viewShare.append(Cryptpad.createButton('viewopen', false, {viewHash: viewHash + '/present'})); - } - } - var $present = Cryptpad.createButton('present', true) .click(function () { enterPresentationMode(true);