diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 9cd904c45..4bd5e298b 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -159,6 +159,9 @@ margin-bottom: @alertify_padding-base; margin: 0; overflow: auto; + :last-child { + margin-bottom: 0; + } } .alertify-tabs { max-height: 100%; @@ -222,14 +225,22 @@ background-color: @alertify-input-fg; color: @cryptpad_text_col; border: 1px solid @alertify-input-bg; - margin-bottom: 15px; + margin-bottom: @alertify_padding-base; width: 100%; font-size: 100%; padding: @alertify_padding-base; &[readonly] { background-color: @alertify-light-bg; color: @cryptpad_text_col; - border-color: @alertify-input-fg; + border-color: @alertify-light-bg; + } + } + + textarea { + overflow: hidden; + padding: 8px; + &[readonly] { + resize: none; } } @@ -509,5 +520,33 @@ overflow-x: auto; } } + // Bootstrap Alerts + .alert { + margin: 0px 0px @alertify_padding-base 0px; + font-size: 12px; + padding: 5px; + border-radius: 0px; + i { + margin-right: 10px; + } + &.alert-primary { + background-color: @alertify-base; + color: @alertify-fg; + border-color: @alertify-fg; + a { + color: @alertify-fg; + text-decoration: underline; + } + } + &.dismissable { + display: flex; + align-items: center; + span.fa-times { + font-size: @colortheme_app-font-size; + margin-left: 20px; + cursor: pointer; + } + } + } } diff --git a/customize.dist/src/less2/include/avatar.less b/customize.dist/src/less2/include/avatar.less index 87b4a3a32..c85c34877 100644 --- a/customize.dist/src/less2/include/avatar.less +++ b/customize.dist/src/less2/include/avatar.less @@ -1,9 +1,12 @@ @import (reference) "./tools.less"; +@import (reference) "./colortheme-all.less"; .avatar_vars( @width: 30px ) { @avatar-width: @width; @avatar-font-size: @width / 1.2; + @avatar-default-bg: #D9D8D8; + @avatar-default-fg: darken(@avatar-default-bg, 40%); } .avatar_main(@width: 30px) { --LessLoader_require: LessLoader_currentFile(); @@ -30,16 +33,16 @@ justify-content: center; align-items: center; - border-radius: 4px; overflow: hidden; box-sizing: content-box; } .cp-avatar-default { .tools_unselectable(); - background: white; - color: black; + background: @avatar-default-bg; + color: @avatar-default-fg; font-size: @avatar-font-size; font-size: var(--avatar-font-size); + text-transform: capitalize; } media-tag { min-height: @avatar-width; diff --git a/customize.dist/src/less2/include/modals-ui-elements.less b/customize.dist/src/less2/include/modals-ui-elements.less index 6e3921781..21707eab8 100644 --- a/customize.dist/src/less2/include/modals-ui-elements.less +++ b/customize.dist/src/less2/include/modals-ui-elements.less @@ -1,12 +1,16 @@ @import (reference) "./colortheme-all.less"; - +@import (reference) "./variables.less"; .modals-ui-elements_main() { --LessLoader_require: LessLoader_currentFile(); } & { + .cp-spacer { + height: @variables_padding; + } // Share modal .msg.cp-inline-radio-group { overflow: unset !important; + padding: 0px @variables_padding; .radio-group { display: flex; flex-direction: row; diff --git a/customize.dist/src/less2/include/password-input.less b/customize.dist/src/less2/include/password-input.less index 79824bac7..0f476390a 100644 --- a/customize.dist/src/less2/include/password-input.less +++ b/customize.dist/src/less2/include/password-input.less @@ -1,3 +1,4 @@ +@import (reference) "./colortheme-all.less"; .password_main() { --LessLoader_require: LessLoader_currentFile(); } @@ -17,7 +18,7 @@ justify-content: center; cursor: pointer; &:hover { - background-color: rgba(0,0,0,0.1); + color: darken(@colortheme_alertify-primary, 10%); } } } diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 4ff807638..6ba8c2d07 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -6,16 +6,18 @@ --LessLoader_require: LessLoader_currentFile(); }; & { + .cp-usergrid-container { + margin-bottom: 12px !important; // even when last child of .msg .cp-usergrid-grid { display: flex; flex-wrap: wrap; + margin: -3px; margin-bottom: 6px; - } - &:not(.large) { - .cp-usergrid-grid { - margin: -3px; - margin-bottom: 6px; + max-height: 130px; + overflow-y: auto; + @media screen and (max-height: 515px) { + max-height: unset; // remove double scrollbar } } &.cp-usergrid-empty { @@ -28,17 +30,22 @@ input { flex: 1; min-width: 0; + margin: 0; margin-bottom: 0 !important; + height: 38px; &::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ color: @cryptpad_color_grey; opacity: 1; /* Firefox */ } } - margin-bottom: 15px; + margin-bottom: 10px; &:empty { margin: 0; display: none; } + button:last-child { + margin-right: 0px !important; + } } .cp-usergrid-user { width: 70px; @@ -58,33 +65,48 @@ background-color: @colortheme_alertify-primary; color: @colortheme_alertify-primary-text; order: -1 !important; + .cp-usergrid-avatar { + media-tag, .cp-avatar-default { + opacity: 0.7; + } + } } .cp-usergrid-user-avatar { min-height: 40px; } + .cp-usergrid-user-name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: 100%; text-align: center; - line-height: 18px; + line-height: 20px; + flex: 1; } - border: 1px solid @colortheme_alertify-primary; &:not(.large) { .avatar_main(40px); } &.large { .avatar_main(25px); - width: 140px; + width: 145px; height: 35px; flex-flow: row; - margin: 0; - margin-right: 15px; - margin-bottom: 1px; - &:nth-child(3n) { - margin-right: 0; + margin: 3px; + flex-basis: calc(33.3333333% - 6px); + flex-shrink: 1; + min-width: 0; + .cp-usergrid-user-name { + margin-left: 5px; + text-align: left; + line-height: 150%; + color: @cryptpad_text_col; + } + } + &.cp-selected { + .cp-usergrid-user-name { + color: @colortheme_alertify-primary-text; } } } diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 8efc7397a..8dc14cc8c 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -127,6 +127,18 @@ define([ return input; }; + dialog.selectableArea = function (value, opt) { + var attrs = merge({ + readonly: 'readonly', + }, opt); + + var input = h('textarea', attrs); + $(input).val(value).click(function () { + input.select(); + }); + return input; + }; + dialog.okButton = function (content, classString) { var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.ok.primary'; return h(sel, { tabindex: '2', }, content || Messages.okButton); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index eb8bb21a2..dedabf118 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -147,6 +147,7 @@ define([ : Messages.owner_removeText; var removeCol = UIElements.getUserGrid(msg, { common: common, + large: true, data: _owners, noFilter: true }, function () { @@ -238,6 +239,7 @@ define([ }); var addCol = UIElements.getUserGrid(Messages.owner_addText, { common: common, + large: true, data: _friends }, function () { //console.log(arguments); @@ -254,6 +256,7 @@ define([ }); var teamsList = UIElements.getUserGrid(Messages.owner_addTeamText, { common: common, + large: true, noFilter: true, data: teamsData }, function () {}); @@ -737,12 +740,22 @@ define([ UIElements.getProperties = function (common, data, cb) { var c1; var c2; + var button = [{ + className: 'primary', + name: Messages.okButton, + onClick: function () {}, + keys: [13] + }]; NThen(function (waitFor) { getPadProperties(common, data, waitFor(function (e, c) { - c1 = c[0]; + c1 = UI.dialog.customModal(c[0], { + buttons: button + }); })); getRightsProperties(common, data, waitFor(function (e, c) { - c2 = c[0]; + c2 = UI.dialog.customModal(c[0], { + buttons: button + }); })); }).nThen(function () { var tabs = UI.dialog.tabs([{ @@ -782,8 +795,6 @@ define([ var noOthers = icons.length === 0 ? '.cp-usergrid-empty' : ''; - var buttonSelect = h('button', Messages.share_selectAll); - var buttonDeselect = h('button', Messages.share_deselectAll); var inputFilter = h('input', { placeholder: Messages.share_filterFriend }); @@ -791,9 +802,7 @@ define([ var div = h('div.cp-usergrid-container' + noOthers + (config.large?'.large':''), [ label ? h('label', label) : undefined, h('div.cp-usergrid-filter', (config.noFilter || config.noSelect) ? undefined : [ - inputFilter, - buttonSelect, - buttonDeselect + inputFilter ]), ]); var $div = $(div); @@ -806,23 +815,8 @@ define([ $div.find('.cp-usergrid-user:not(.cp-selected):not([data-name*="'+name+'"])').hide(); } }; - $(inputFilter).on('keydown keyup change', redraw); - $(buttonSelect).click(function () { - $div.find('.cp-usergrid-user:not(.cp-selected):visible').addClass('cp-selected'); - onSelect(); - }); - $(buttonDeselect).click(function () { - $div.find('.cp-usergrid-user.cp-selected').removeClass('cp-selected').each(function (i, el) { - var order = $(el).attr('data-order'); - if (!order) { return; } - $(el).attr('style', 'order:'+order); - }); - redraw(); - onSelect(); - }); - $(div).append(h('div.cp-usergrid-grid', icons)); if (!config.noSelect) { $div.on('click', '.cp-usergrid-user', function () { @@ -883,7 +877,8 @@ define([ var friendsList = UIElements.getUserGrid(null, { common: common, data: friends, - noFilter: false + noFilter: false, + large: true }, refreshButtons); var friendDiv = friendsList.div; $div.append(friendDiv); @@ -909,6 +904,7 @@ define([ var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, { common: common, noFilter: true, + large: true, data: teams }, refreshButtons); $div.append(teamsList.div); @@ -1014,12 +1010,29 @@ define([ if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; } + // check if the pad is password protected + var hash = hashes.editHash || hashes.viewHash; + var href = origin + pathname + '#' + hash; + var parsedHref = Hash.parsePadUrl(href); + var hasPassword = parsedHref.hashData.password; + + var makeFaqLink = function () { + var link = h('span', [ + h('i.fa.fa-question-circle'), + h('a', {href: '#'}, Messages.passwordFaqLink) + ]); + $(link).click(function () { + common.openURL(config.origin + "/faq.html#security-pad_password"); + }); + return link; + }; + + var parsed = Hash.parsePadUrl(pathname); var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1; var rights = h('div.msg.cp-inline-radio-group', [ h('label', Messages.share_linkAccess), - h('br'), h('div.radio-group',[ UI.createRadio('accessRights', 'cp-share-editable-false', Messages.share_linkView, true, { mark: {tabindex:1} }), @@ -1066,9 +1079,42 @@ define([ h('br'), ] : [ UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }), - h('br'), ]; - linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })); + linkContent.push(h('div.cp-spacer')); + linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3})); + + // Show alert if the pad is password protected + if (hasPassword) { + linkContent.push(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), + Messages.share_linkPasswordAlert, h('br'), + makeFaqLink() + ])); + } + + // warning about sharing links + var localStore = window.cryptpadStore; + var dismissButton = h('span.fa.fa-times'); + var shareLinkWarning = h('div.alert.alert-warning.dismissable', + { style: 'display: none;' }, + [ + h('span.cp-inline-alert-text', Messages.share_linkWarning), + dismissButton + ]); + linkContent.push(shareLinkWarning); + + localStore.get('hide-alert-shareLinkWarning', function (val) { + if (val === '1') { return; } + $(shareLinkWarning).show(); + + $(dismissButton).on('click', function () { + localStore.put('hide-alert-shareLinkWarning', '1'); + $(shareLinkWarning).remove(); + }); + + }); + + var link = h('div.cp-share-modal', linkContent); var $link = $(link); @@ -1135,7 +1181,19 @@ define([ // XXX Don't display access rights if no contacts var contactsContent = h('div.cp-share-modal'); - $(contactsContent).append(friendsList); + var $contactsContent = $(contactsContent); + + $contactsContent.append(friendsList); + + // Show alert if the pad is password protected + if (hasPassword) { + $contactsContent.append(h('div.alert.alert-primary', [ + h('i.fa.fa-unlock'), + Messages.share_contactPasswordAlert, h('br'), + makeFaqLink() + ])); + } + var contactButtons = [makeCancelButton(), friendsObject.button]; @@ -1154,9 +1212,18 @@ define([ }; var embedContent = [ h('p', Messages.viewEmbedTag), - h('br'), - UI.dialog.selectable(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1 }) + UI.dialog.selectableArea(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3}) ]; + + // Show alert if the pad is password protected + if (hasPassword) { + embedContent.push(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', + Messages.share_embedPasswordAlert, h('br'), + makeFaqLink() + ])); + } + var embedButtons = [ makeCancelButton(), { className: 'primary', @@ -1261,6 +1328,21 @@ define([ if (!hashes.fileHash) { throw new Error("You must provide a file hash"); } var url = origin + pathname + '#' + hashes.fileHash; + // check if the file is password protected + var parsedHref = Hash.parsePadUrl(url); + var hasPassword = parsedHref.hashData.password; + + var makeFaqLink = function () { + var link = h('span', [ + h('i.fa.fa-question-circle'), + h('a', {href: '#'}, Messages.passwordFaqLink) + ]); + $(link).click(function () { + common.openURL(config.origin + "/faq.html#security-pad_password"); + }); + return link; + }; + var getLinkValue = function () { return url; }; var makeCancelButton = function() { @@ -1272,9 +1354,40 @@ define([ // Share link tab var linkContent = [ - UI.dialog.selectable(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1 }) + UI.dialog.selectableArea(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1, rows:2 }) ]; + // Show alert if the pad is password protected + if (hasPassword) { + linkContent.push(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), + Messages.share_linkPasswordAlert, h('br'), + makeFaqLink() + ])); + } + + // warning about sharing links + var localStore = window.cryptpadStore; + var dismissButton = h('span.fa.fa-times'); + var shareLinkWarning = h('div.alert.alert-warning.dismissable', + { style: 'display: none;' }, + [ + h('span.cp-inline-alert-text', Messages.share_linkWarning), + dismissButton + ]); + linkContent.push(shareLinkWarning); + + localStore.get('hide-alert-shareLinkWarning', function (val) { + if (val === '1') { return; } + $(shareLinkWarning).show(); + + $(dismissButton).on('click', function () { + localStore.put('hide-alert-shareLinkWarning', '1'); + $(shareLinkWarning).remove(); + }); + + }); + var link = h('div.cp-share-modal', linkContent); var linkButtons = [ @@ -1307,7 +1420,17 @@ define([ var friendsList = friendsObject.content; var contactsContent = h('div.cp-share-modal'); - $(contactsContent).append(friendsList); + var $contactsContent = $(contactsContent); + $contactsContent.append(friendsList); + + // Show alert if the pad is password protected + if (hasPassword) { + $contactsContent.append(h('div.alert.alert-primary', [ + h('i.fa.fa-unlock'), + Messages.share_contactPasswordAlert, h('br'), + makeFaqLink() + ])); + } var contactButtons = [makeCancelButton(), friendsObject.button]; @@ -1321,12 +1444,20 @@ define([ // Embed tab var embed = h('div.cp-share-modal', [ h('p', Messages.fileEmbedScript), - h('br'), UI.dialog.selectable(common.getMediatagScript()), h('p', Messages.fileEmbedTag), - h('br'), UI.dialog.selectable(common.getMediatagFromHref(fileData)), ]); + + // Show alert if the pad is password protected + if (hasPassword) { + embed.append(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', + Messages.share_embedPasswordAlert, h('br'), + makeFaqLink() + ])); + } + var embedButtons = [{ className: 'cancel', name: Messages.cancel, @@ -1761,7 +1892,7 @@ define([ if (e) { return void console.error(e); } UIElements.getProperties(common, data, function (e, $prop) { if (e) { return void console.error(e); } - UI.alert($prop[0], undefined, true); + UI.openCustomModal($prop[0]); }); }); }); diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 2f7da5886..3fa850b51 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -4187,7 +4187,7 @@ define([ } getProperties(el, function (e, $prop) { if (e) { return void logError(e); } - UI.alert($prop[0], undefined, true); + UI.openCustomModal($prop[0]); }); } else if ($this.hasClass("cp-app-drive-context-hashtag")) { diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index e439d04c1..e0571bb16 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -488,6 +488,20 @@ define([ Cryptpad.storeInTeam(data, cb); }); + sframeChan.on('EV_GOTO_URL', function (url) { + if (url) { + window.location.href = url; + } else { + window.location.reload(); + } + }); + + sframeChan.on('EV_OPEN_URL', function (url) { + if (url) { + window.open(url); + } + }); + }; addCommonRpc(sframeChan); @@ -956,20 +970,6 @@ define([ }); }); - sframeChan.on('EV_GOTO_URL', function (url) { - if (url) { - window.location.href = url; - } else { - window.location.reload(); - } - }); - - sframeChan.on('EV_OPEN_URL', function (url) { - if (url) { - window.open(url); - } - }); - sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) { Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) { cb({ diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js index 224f7eeb6..b6cb3c125 100644 --- a/www/common/toolbar3.js +++ b/www/common/toolbar3.js @@ -533,7 +533,7 @@ MessengerUI, Messages) { Common.getSframeChannel().event('EV_SHARE_OPEN', { hidden: true }); - $shareBlock.click(function () { + $shareBlock.click(function () { var title = (config.title && config.title.getTitle && config.title.getTitle()) || (config.title && config.title.defaultName) || ""; diff --git a/www/settings/inner.js b/www/settings/inner.js index d67f62818..7c9dd0630 100644 --- a/www/settings/inner.js +++ b/www/settings/inner.js @@ -51,6 +51,7 @@ define([ 'cp-settings-info-block', 'cp-settings-displayname', 'cp-settings-language-selector', + 'cp-settings-resettips', 'cp-settings-logout-everywhere', 'cp-settings-autostore', 'cp-settings-userfeedback', @@ -67,7 +68,6 @@ define([ ], 'drive': [ 'cp-settings-drive-duplicate', - 'cp-settings-resettips', 'cp-settings-thumbnails', 'cp-settings-drive-backup', 'cp-settings-drive-import-local', @@ -835,7 +835,7 @@ define([ var localStore = window.cryptpadStore; $button.click(function () { Object.keys(localStore.store).forEach(function (k) { - if(k.slice(0, 9) === "hide-info") { + if(/^(hide-(info|alert))/.test(k)) { localStore.put(k, null); } });