diff --git a/CHANGELOG.md b/CHANGELOG.md index edf75ffb5..dfa69006a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,72 @@ +# Smilodon's revenge (3.18.1) + +Our next major release (3.19.0) is still a few weeks away. +In the meantime we've been working on some minor improvements and bug fixes that we wanted to ship as soon as possible. + +New features: + +* Rich text pads can now be exported to .doc format. A few features don't translate well to the exported format (some fonts, embedded videos and pdfs), but for the most part your documents should work +* Items in the "Recent pads" section of your drive can now be dragged to other folders via the filesystem tree UI +* The user admin menu (found in the top-right corner) now includes an option to display the current version of the CryptPad instance you're using. We plan to add some more information here in the near future. +* The kanban app now offers better support for editing markdown within cards with autocompleted parentheses. We've also added support for embedded media, allowing users to drag images and other content into the card content editor. + +Bug fixes: + +* Account deletion via the settings page works once again +* Some small layout and usability issues in the drive have been addressed + * dropdown menus flow in the appropriate direction when space is limited + * changing the sorting criteria no longer causes the browser to jump to the top of the page +* Hitting enter or escape in the kanban's card tag field while it's empty now closes the modal (instead of doing nothing) +* Language preferences (as configured via the settings page) are applied when you log in (previously it would reset to English or your browser's settings) +* A performance issue triggered by hiding a closed support ticket from the admin panel has been optimized. Previously it would lock up the shared worker in cases when there were many unclosed tickets. +* We've updated the parameters of the XLSX import/export functionality to prevent an "out of memory" error that primarily affected large spreadsheets. It should now allocate more memory instead of failing silently. +* Finally, members of a team can now directly share or transfer ownership of a document owned by their team to their own account without having to go through the additional steps of offering it to themself and accepting the offer. + +Updating from 3.18.0 to 3.18.1 is pretty standard: + +1. Stop your server +2. Get the latest code with git +3. Restart your server + +# Smilodon release (3.18.0) + +## Goals + +This is a big one! A lot of people are going to love it and a few are probably going to hate it. + +This release introduces some major changes to our apps' appearances with the intent of making it easier to use, easier for us to support, and easier to maintain. + +## Update notes + +If you're using a mostly standard CryptPad installation this should be a rather easy update. + +If you've customized your styles, particularly for the purpose of overriding the default colors, you may encounter some problems. **We recommend that you test this version in a staging environment** before deploying to ensure that it is compatible with your modifications. + +Otherwise, update to 3.18.0 from 3.17.0 in the following manner: + +1. stop your server +2. fetch the latest code with git +3. bower update +4. relaunch your server + +## Features + +* Obviously, there's the major redesign mentioned in our _goals_. + * You'll immediately notice that we've changed a lot of our color scheme. Apps still have colors as accents to help differentiate them, but the colors are more subtle. The move towards a more monochrome design makes it easier for us to ensure that the UI has a sufficient amount of contrast (less eye strain for everybody!) and simplifies design issues by settling on a simpler color palette. + * You'll probably also notice that a lot of the toolbar features have been rearranged. The chat and userlist are now at the right, while we've adopted the "File menu" layout to which users of office productivity are accustomed. A lot of the common features that were buried in our `...` menu are now under "File" ("new", "import/export", "history", "move to trash", etc.). Some apps feature their special menus ("Insert", "Tools", "Theme") depending on whether they support certain features. In general we'll use text in addition to icons in the toolbar except on very small screens where the use of space is constrained. + * Finally, you'll find some of CryptPad's most important functionality right in the center of the toolbar. The "Share" and "Access" buttons already existed, but lots of people had trouble finding them and missed out on our fine-grained access controls by always sharing the URL directly from their browser's address bar. In case you hadn't seen it, the "Share menu" gives you the ability to generate links that let others view, edit, or delete the document in question. The "Access menu" provides an overview of the document's access settings, and lets its owner(s) add passwords, enable or disable other viewers' ability to request edit rights, restrict access to a dynamic list of users or teams, and modify ownership of the document. It will soon be even more important to know about these menus, because **we plan to enable "Safe links" as the default behaviour in our next release**. "Safe links" are URLs that contain only a document's id instead of its cryptographic secrets, making it less likely that you'll accidentally leak the ability to read your documents during screenshots or when copy-pasting URLs. +* The toolbar redesign has also affected the drive interface, but it's special enough that it deserves a separate mention: + * You can now collapse the sidebar which contains the search button, recent pads, filesystem tree, templates, trash, and account storage quota meter. This should make navigation of the drive on mobile devices much simpler. + * The actual "search" interface is no longer inside the sidebar. Instead, clicking search will bring you to an interface which uses the full size available to display the search bar and its results. +* By the time the toolbar was mostly redesigned we realized that our mockups hadn't included a link to the "todo" app. In fact, we'd been meaning to deprecate it in favour of Kanbans for some time, but we hadn't gotten around to it. So, now there's a migration that will be run automatically when you access your account for the first time after this release. Your todo-list will be transformed into a Kanban located in the root of your drive. +* On that note, this release also makes it much easier to drag and drop kanban cards within and between full columns thanks to an improved scrolling behaviour while you are holding a card. + +## Bug fixes + +* While implementing the todo-list migration we noticed that user accounts were running migrations without updating their version afterward. This resulted in redundant migrations being run at login time, so now that the version has been updated you might notice that login is marginally faster. +* We also fixed a regression in the "Print" functionality of the rich text editor, so you should be able to print correctly-formatted rich text documents once more. +* Lastly, there were some rather annoying issues with spreadsheets throughout this release that resulted in some users not being able to load their sheets or in their sheets being rendered or encoded incorrectly. We spent a lot of time solving these issues, and believe spreadsheets to be stable once more. + # RedGazelle's revenge release (3.17.1) In recent months a growing amount of our time has been going towards answering support tickets, emails, and GitHub issues. This has made it a little more difficult to also maintain a bi-weekly release schedule, since there's some overhead involved in deploying our latest code and producing release notes. @@ -10,7 +79,7 @@ Updating to 3.17.1 from 3.17.0 is pretty standard: 1. Stop your server 2. Get the latest code with git -3. Restart your server +3. Restart your server # RedGazelle release (3.17.0) diff --git a/bower.json b/bower.json index ab99a55a8..9fd787c20 100644 --- a/bower.json +++ b/bower.json @@ -24,7 +24,7 @@ "ckeditor": "4.14.0", "codemirror": "^5.19.0", "requirejs": "2.3.5", - "marked": "0.5.0", + "marked": "1.1.0", "rangy": "rangy-release#~1.3.0", "json.sortify": "~2.1.0", "secure-fabric.js": "secure-v1.7.9", @@ -48,7 +48,8 @@ "sortablejs": "^1.6.0", "saferphore": "^0.0.1", "jszip": "Stuk/jszip#^3.1.5", - "requirejs-plugins": "^1.0.3" + "requirejs-plugins": "^1.0.3", + "dragula.js": "3.7.2" }, "resolutions": { "bootstrap": "^v4.0.0", diff --git a/customize.dist/fonts/cptools/fonts/cptools.svg b/customize.dist/fonts/cptools/fonts/cptools.svg index 93eef8d38..3540c5d06 100644 --- a/customize.dist/fonts/cptools/fonts/cptools.svg +++ b/customize.dist/fonts/cptools/fonts/cptools.svg @@ -26,4 +26,6 @@ + + \ No newline at end of file diff --git a/customize.dist/fonts/cptools/fonts/cptools.ttf b/customize.dist/fonts/cptools/fonts/cptools.ttf index 18338a9ee..2788cf010 100644 Binary files a/customize.dist/fonts/cptools/fonts/cptools.ttf and b/customize.dist/fonts/cptools/fonts/cptools.ttf differ diff --git a/customize.dist/fonts/cptools/fonts/cptools.woff b/customize.dist/fonts/cptools/fonts/cptools.woff index d8f56ba86..64b641b9d 100644 Binary files a/customize.dist/fonts/cptools/fonts/cptools.woff and b/customize.dist/fonts/cptools/fonts/cptools.woff differ diff --git a/customize.dist/fonts/cptools/style.css b/customize.dist/fonts/cptools/style.css index 349b62f2b..85ed350f5 100644 --- a/customize.dist/fonts/cptools/style.css +++ b/customize.dist/fonts/cptools/style.css @@ -1,11 +1,12 @@ @font-face { font-family: 'cptools'; src: - url('fonts/cptools.ttf?cljhos') format('truetype'), - url('fonts/cptools.woff?cljhos') format('woff'), - url('fonts/cptools.svg?cljhos#cptools') format('svg'); + url('fonts/cptools.ttf?da4x1y') format('truetype'), + url('fonts/cptools.woff?da4x1y') format('woff'), + url('fonts/cptools.svg?da4x1y#cptools') format('svg'); font-weight: normal; font-style: normal; + font-display: block; } .cptools { @@ -24,6 +25,12 @@ -moz-osx-font-smoothing: grayscale; } +.cptools-add-bottom:before { + content: "\e913"; +} +.cptools-add-top:before { + content: "\e914"; +} .cptools-folder-upload:before { content: "\e912"; } diff --git a/customize.dist/login.js b/customize.dist/login.js index 3954aa1e2..35121f113 100644 --- a/customize.dist/login.js +++ b/customize.dist/login.js @@ -341,6 +341,11 @@ define([ if (shouldImport) { setMergeAnonDrive(); } + var l = Util.find(rt.proxy, ['settings', 'general', 'language']); + var LS_LANG = "CRYPTPAD_LANG"; + if (l) { + localStorage.setItem(LS_LANG, l); + } return void LocalStore.login(userHash, uname, function () { cb(void 0, res); }); @@ -357,7 +362,7 @@ define([ if (shouldImport) { setMergeAnonDrive(); } else { - proxy.version = 6; + proxy.version = 10; } Feedback.send('REGISTRATION', true); diff --git a/customize.dist/pages.js b/customize.dist/pages.js index c611d608e..6ba39e49a 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -61,6 +61,9 @@ define([ var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ? '/imprint.html' : AppConfig.imprint); + + Pages.versionString = "CryptPad v3.18.1 (Smilodon's revenge)"; + Pages.infopageFooter = function () { return h('footer', [ h('div.container', [ @@ -96,7 +99,7 @@ define([ ]), footerCol('footer_legal', [ footLink('/terms.html', 'footer_tos'), - footLink('/privacy.html', 'privacy'), + footLink(AppConfig.privacy, 'privacy'), AppConfig.imprint ? footLink(imprintUrl, 'imprint') : undefined, ]), /*footerCol('footer_contact', [ @@ -107,7 +110,7 @@ define([ ])*/ ]) ]), - h('div.cp-version-footer', "CryptPad v3.17.1 (RedGazelle's revenge)") + h('div.cp-version-footer', Pages.versionString) ]); }; diff --git a/customize.dist/pages/features.js b/customize.dist/pages/features.js index 07aed6367..00308fc29 100644 --- a/customize.dist/pages/features.js +++ b/customize.dist/pages/features.js @@ -4,8 +4,9 @@ define([ '/customize/messages.js', '/customize/application_config.js', '/common/outer/local-store.js', - '/customize/pages.js' -], function ($, h, Msg, AppConfig, LocalStore, Pages) { + '/customize/pages.js', + '/api/config', +], function ($, h, Msg, AppConfig, LocalStore, Pages, Config) { var origin = encodeURIComponent(window.location.hostname); var accounts = { donateURL: 'https://accounts.cryptpad.fr/#/donate?on=' + origin, @@ -29,99 +30,107 @@ define([ sessionStorage.redirectTo = '/features.html'; window.location.href = '/login/'; });*/ - return h('div#cp-main', [ - Pages.infopageTopbar(), - h('div.container-fluid.cp_cont_features',[ - h('div.container',[ - h('center', h('h1', Msg.features_title)), + + var anonymousFeatures = + h('div.col-12.col-sm-4.cp-anon-user',[ + h('div.card',[ + h('div.card-body',[ + h('h3.text-center',Msg.features_anon) + ]), + h('div.card-body.cp-pricing',[ + h('div.text-center', '0€'), + h('div.text-center', Msg.features_noData), + ]), + h('ul.list-group.list-group-flush', + ['apps', 'core', 'file0', 'cryptdrive0', 'storage0'].map(function (f) { + return h('li.list-group-item', [ + h('div.cp-check'), + h('div.cp-content', [ + h('div.cp-feature', Msg['features_f_' + f]), + h('div.cp-note', Msg['features_f_' + f + '_note']) + ]) + ]); + }) + ), ]), - ]), - h('div.container',[ - h('div.row.cp-container.cp-features-web.justify-content-sm-center',[ - h('div.col-12.col-sm-4.cp-anon-user',[ - h('div.card',[ - h('div.card-body',[ - h('h3.text-center',Msg.features_anon) - ]), - h('div.card-body.cp-pricing',[ - h('div.text-center', '0€'), - h('div.text-center', Msg.features_noData), - ]), - h('ul.list-group.list-group-flush', - ['apps', 'core', 'file0', 'cryptdrive0', 'storage0'].map(function (f) { - return h('li.list-group-item', [ - h('div.cp-check'), - h('div.cp-content', [ - h('div.cp-feature', Msg['features_f_' + f]), - h('div.cp-note', Msg['features_f_' + f + '_note']) - ]) - ]); - }) - ), - ]), + ]); + var registeredFeatures = + h('div.col-12.col-sm-4.cp-regis-user',[ + h('div.card',[ + h('div.card-body',[ + h('h3.text-center',Msg.features_registered) + ]), + h('div.card-body.cp-pricing',[ + h('div.text-center', '0€'), + h('div.text-center', Msg.features_noData), + ]), + h('ul.list-group.list-group-flush', [ + ['anon', 'social', 'file1', 'cryptdrive1', 'devices', 'storage1'].map(function (f) { + return h('li.list-group-item', [ + h('div.cp-check'), + h('div.cp-content', [ + h('div.cp-feature', Msg['features_f_' + f]), + h('div.cp-note', Msg['features_f_' + f + '_note']) + ]) + ]); + }), ]), - h('div.col-12.col-sm-4.cp-regis-user',[ - h('div.card',[ - h('div.card-body',[ - h('h3.text-center',Msg.features_registered) - ]), - h('div.card-body.cp-pricing',[ - h('div.text-center', '0€'), - h('div.text-center', Msg.features_noData), - ]), - h('ul.list-group.list-group-flush', [ - ['anon', 'social', 'file1', 'cryptdrive1', 'devices', 'storage1'].map(function (f) { - return h('li.list-group-item', [ - h('div.cp-check'), - h('div.cp-content', [ - h('div.cp-feature', Msg['features_f_' + f]), - h('div.cp-note', Msg['features_f_' + f + '_note']) - ]) - ]); - }), - ]), - h('div.card-body',[ - h('div.cp-features-register#cp-features-register', [ - h('a', { - href: '/register/' - }, h('button.cp-features-register-button', Msg.features_f_register)) - ]), - h('div.cp-note', Msg.features_f_register_note) - ]), + h('div.card-body',[ + h('div.cp-features-register#cp-features-register', [ + h('a', { + href: '/register/' + }, h('button.cp-features-register-button', Msg.features_f_register)) ]), + h('div.cp-note', Msg.features_f_register_note) ]), - h('div.col-12.col-sm-4.cp-anon-user',[ - h('div.card',[ - h('div.card-body',[ - h('h3.text-center',Msg.features_premium) - ]), - h('div.card-body.cp-pricing',[ - h('div.text-center', h('a', { - href: accounts.upgradeURL, - target: '_blank' - }, Msg._getKey('features_pricing', ['5', '10', '15']))), - h('div.text-center', Msg.features_emailRequired), - ]), - h('ul.list-group.list-group-flush', [ - ['reg', 'storage2', 'support', 'supporter'].map(function (f) { - return h('li.list-group-item', [ - h('div.cp-check'), - h('div.cp-content', [ - h('div.cp-feature', Msg['features_f_' + f]), - h('div.cp-note', Msg['features_f_' + f + '_note']) - ]) - ]); - }), - ]), - h('div.card-body',[ - h('div.cp-features-register#cp-features-subscribe', [ - premiumButton - ]), - LocalStore.isLoggedIn() ? undefined : h('div.cp-note', Msg.features_f_subscribe_note) - ]), + ]), + ]); + var premiumFeatures = + h('div.col-12.col-sm-4.cp-anon-user',[ + h('div.card',[ + h('div.card-body',[ + h('h3.text-center',Msg.features_premium) + ]), + h('div.card-body.cp-pricing',[ + h('div.text-center', h('a', { + href: accounts.upgradeURL, + target: '_blank' + }, Msg._getKey('features_pricing', ['5', '10', '15']))), + h('div.text-center', Msg.features_emailRequired), + ]), + h('ul.list-group.list-group-flush', [ + ['reg', 'storage2', 'support', 'supporter'].map(function (f) { + return h('li.list-group-item', [ + h('div.cp-check'), + h('div.cp-content', [ + h('div.cp-feature', Msg['features_f_' + f]), + h('div.cp-note', Msg['features_f_' + f + '_note']) + ]) + ]); + }), + ]), + h('div.card-body',[ + h('div.cp-features-register#cp-features-subscribe', [ + premiumButton ]), + LocalStore.isLoggedIn() ? undefined : h('div.cp-note', Msg.features_f_subscribe_note) ]), ]), + ]); + var availableFeatures = + Config.allowSubscriptions ? + [anonymousFeatures, registeredFeatures, premiumFeatures] : + [anonymousFeatures, registeredFeatures]; + + return h('div#cp-main', [ + Pages.infopageTopbar(), + h('div.container-fluid.cp_cont_features',[ + h('div.container',[ + h('center', h('h1', Msg.features_title)), + ]), + ]), + h('div.container', [ + h('div.row.cp-container.cp-features-web.justify-content-sm-center', availableFeatures), ]), Pages.infopageFooter() ]); diff --git a/customize.dist/src/less2/include/app-print.less b/customize.dist/src/less2/include/app-print.less index 6ff8964eb..e4c344b20 100644 --- a/customize.dist/src/less2/include/app-print.less +++ b/customize.dist/src/less2/include/app-print.less @@ -21,7 +21,6 @@ } * { visibility: hidden; - height: auto; max-height: none; } .cp-app-slide-viewer #cp-app-slide-print { diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index 709afa7c8..3b232be81 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -68,36 +68,40 @@ @colortheme_dropdown-bg-active: #e8e8e8; // Apps, these colors are used for customizing the toolbar for the apps. +@colortheme_toolbar-warn: @colortheme_alertify-red; +@colortheme_pad-toolbar-bg: #eeeeee; +@colortheme_help-bg: #ddd; +@colortheme_userlist-bg: #eee; +@colortheme_pad-chat-bg: #AAA; -@colortheme_pad-bg: #1c4fa0; +@colortheme_pad-bg: #256ad5; @colortheme_pad-color: #fff; -@colortheme_pad-toolbar-bg: #c1e7ff; @colortheme_pad-warn: #ffae00; @colortheme_slide-bg: #e57614; @colortheme_slide-color: #fff; @colortheme_slide-warn: #005868; -@colortheme_code-bg: #ffae00; +@colortheme_code-bg: #EAA000; @colortheme_code-color: #000; @colortheme_code-warn: #9A37F7; -@colortheme_poll-bg: #006304; +@colortheme_poll-bg: #2c9e98; @colortheme_poll-color: #fff; @colortheme_poll-help-bg: #bbffbb; @colortheme_poll-th-bg: #005bef; @colortheme_poll-th-fg: #fff; @colortheme_poll-warn: #ffade3; -@colortheme_whiteboard-bg: #800080; +@colortheme_whiteboard-bg: #a72ba7; @colortheme_whiteboard-color: #fff; @colortheme_whiteboard-warn: #ffae00; -@colortheme_drive-bg: #0087ff; +@colortheme_drive-bg: #0087FF; @colortheme_drive-color: #fff; @colortheme_drive-warn: #cd2532; -@colortheme_teams-bg: #0b0061; +@colortheme_teams-bg: #4a3bbd; @colortheme_teams-color: #fff; @colortheme_teams-warn: #cd2532; @@ -121,8 +125,8 @@ @colortheme_profile-color: #fff; @colortheme_profile-warn: #cd2532; -@colortheme_todo-bg: #7bccd1; -@colortheme_todo-color: #000; +@colortheme_todo-bg: #999; +@colortheme_todo-color: #3F4141; @colortheme_todo-warn: #cd2532; @colortheme_oodoc-bg: #5170B5; @@ -141,15 +145,15 @@ @colortheme_kanban-color: #000; @colortheme_kanban-warn: #e6385d; -@colortheme_admin-bg: #7c0404; +@colortheme_admin-bg: #0087ff; @colortheme_admin-color: #FFF; @colortheme_admin-warn: #ffae00; -@colortheme_notifications-bg: #4ae397; +@colortheme_notifications-bg: #0087ff; @colortheme_notifications-color: #000; @colortheme_notifications-warn: #e34a85; -@colortheme_support-bg: #42d1f4; +@colortheme_support-bg: #0087ff; @colortheme_support-color: #000; @colortheme_support-warn: #9A37F7; diff --git a/customize.dist/src/less2/include/drive.less b/customize.dist/src/less2/include/drive.less index d8b254c42..0eb400587 100644 --- a/customize.dist/src/less2/include/drive.less +++ b/customize.dist/src/less2/include/drive.less @@ -12,6 +12,10 @@ .limit-bar_main(); .tokenfield_main(); + @colortheme_drive-bg-light: lighten(@colortheme_drive-bg, 30%); + @colortheme_drive-bg-active: lighten(@colortheme_drive-bg, 20%); + @colortheme_drive-color: @cryptpad_text_col; + @drive_hover: #eee; @drive_hover-light: lighten(@drive_hover, 20%); @drive_info-box-bg: #d2e1f2; @@ -212,6 +216,41 @@ } + #cp-app-drive-search { + display: flex; + align-items: center; + max-width: 400px; + font-size: 30px; + margin: 15px; + input { + background: transparent; + color: @colortheme_drive-color; + .tools_placeholder-color(@colortheme_drive-color); + outline-width: 0px; + border-radius: 0; + width: 100%; + border: 0; + border-bottom: 3px solid @colortheme_drive-color; + margin: 0 5px; + flex: 1; + min-width: 0; + &:focus { + outline-width: 0px; + } + &.cp-app-drive-search-active { + & ~ .cp-app-drive-search-cancel { + visibility: visible; + } + } + } + .cp-app-drive-search-cancel { + visibility: hidden; + cursor: pointer; + } + .cp-app-drive-tree-search-icon, .cp-app-drive-search-cancel { + color: @colortheme_drive-color; + } + } @@ -234,6 +273,22 @@ display: flex; flex-flow: column; max-height: 100%; + position: relative; + .cp-close-button { + position: absolute; + cursor: pointer; + right: 5px; + top: 5px; + font-size: 18px; + padding: 3px; + margin: 0; + border: 0; + background-color: transparent; + outline: none; + &:hover { + color: #000; + } + } .cp-app-drive-tree-categories-container { flex: 1; overflow: auto; @@ -306,51 +361,6 @@ .cp-limit-container { margin-top: 5px; } - #cp-app-drive-tree-search { - text-align: center; - padding: 0; - position: relative; - display: flex; - background: lighten(@colortheme_drive-bg, 8%); - border-right: 1px solid lighten(@colortheme_drive-bg, 16%); - input { - background: transparent; - color: @colortheme_drive-color; - .tools_placeholder-color(@colortheme_drive-color); - outline-width: 0px; - border-radius: 0; - width: 100%; - //border: 1px solid #ccc; - border: 0; - //border-right: 0; - height: @variables_bar-height; - padding: 0 5px; - padding-left: 45px; - flex: 1; - min-width: 0; - &:focus { - outline-width: 0px; - } - &.cp-app-drive-search-active { - & ~ .cp-app-drive-tree-search-icon { - display: none; - } - & ~ .cp-app-drive-search-cancel { - display: inline-block; - } - } - } - .cp-app-drive-search-cancel { - display: none; - cursor: pointer; - } - .cp-app-drive-tree-search-icon, .cp-app-drive-search-cancel { - color: @colortheme_drive-color; - position: absolute; - left: 20px; // TODO align with drive categories - top: 8px; - } - } .fa.cp-app-drive-icon-expcol { margin-left: -10px; font-size: 14px; @@ -706,6 +716,9 @@ } } } + .cp-app-drive-element-state { + display: none !important; + } } } .cp-app-drive-element { @@ -719,6 +732,9 @@ .cp-app-drive-element-type, .cp-app-drive-element-filler { display: none !important; } + .cp-app-drive-element-sort { + display: block !important; + } } @media screen and (max-width: 740px) { @@ -734,8 +750,70 @@ .cp-app-drive-element-header .cp-app-drive-element-state { display: none !important; } - .cp-app-drive-element-sort { - display: block !important; + } + } + + & > .cp-app-drive-path { + width: 100%; + height: @variables_bar-height; + line-height: @variables_bar-height; + cursor: default; + width: auto; + overflow: hidden; + white-space: nowrap; + flex-shrink: 0; + min-width: 50px; + max-width: 100%; + text-align: left; + display: flex; + flex-direction: row; + + .cp-app-drive-path-inner { + display: flex; + flex-flow: row-reverse; + flex-grow: 1; + justify-content: flex-end; + .cp-app-drive-path-element { + display: inline-block; + flex-shrink: 0; + max-width: 100%; + height: @variables_bar-height; + line-height: @variables_bar-height; + font-size: @colortheme_app-font-size; + padding: 0 5px; + border: 0; + //background: @colortheme_drive-bg-active; + color: @colortheme_drive-color; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.15s; + cursor: pointer; + + &:first-child { + flex-shrink: 1; + } + + &.cp-app-drive-path-separator { + color: #ccc; + cursor: default; + } + + &.cp-app-drive-path-collapse { + position: relative; + } + + &.cp-app-drive-element-droppable { + background-color: @drive_droppable-bg; + } + &:not(.cp-app-drive-element-droppable):hover { + &:not(.cp-app-drive-path-separator) { + text-decoration: underline; + } + & ~ .cp-app-drive-path-element:not(.cp-app-drive-path-separator) { + text-decoration: underline; + } + } } } } @@ -811,191 +889,20 @@ } - /* Toolbar */ - - #cp-app-drive-toolbar { - background: lighten(@colortheme_drive-bg, 8%); - color: @colortheme_drive-color; - //height: 30px; - //display: flex; - //flex-flow: row; - z-index: 100; - box-sizing: border-box; - height: @variables_bar-height; - padding: 0; - display: flex; - flex-flow: row; - - * { - outline-width: 0; - &:focus { - outline-width: 0; - } - } - - .cp-toolbar-icon-history { - float: right; - &.active { - background-color: rgba(0, 0, 255, 0.2); - } - .cp-toolbar-drawer-element { - display: none; - } - } - - .cp-app-drive-toolbar-rightside, .cp-app-drive-toolbar-leftside { - display: inline-block; - margin: 0; - padding: 0; - .fa, .cptools { - margin: 0; - vertical-align: top; - } - button { - height: @variables_bar-height !important; - padding: 0 10px; - border: none; - border-radius: 0; - box-sizing: border-box; - background: transparent; - font-size: @colortheme_app-font-size; - color: @colortheme_drive-color; - transition: all 0.15s; - display: inline-flex; - align-items: center; - .drawer { - display: none; - } - .fa, .cptools, span { - font-size: @colortheme_app-font-size; - } - &:hover { - background: @colortheme_drive-bg; - } - &.cp-app-drive-toolbar-active { - display: none; - } - } - } - .cp-app-drive-toolbar-rightside { - float: right; - flex-shrink: 0; - & > * { - float: right; + .cp-toolbar-bottom { + .cp-toolbar-bottom-right { + .fa-history { order: 50; } + .fa-list, .fa-th-large { order: 25; } + #cp-app-drive-toolbar-context-mobile, #cp-app-drive-toolbar-contextbuttons { order: 0; } + #cp-app-drive-toolbar-context-mobile { + .fa { margin: 0 !important; } } #cp-app-drive-toolbar-contextbuttons { - display: inline-block; - height: 100%; - } - padding-left: 10px; - } - .cp-app-drive-toolbar-leftside { - flex-shrink: 0; - & > span { - height: 100%; - margin: 0; - } - button { - padding: 0 10px; - .fa, .cptools { - margin-right: 5px; - } - .cp-dropdown-button-title { - display: inline-flex; - height: @variables_bar-height; - align-items: center; - span:not(.fa):not(.cptools) { - line-height: 23px; - } - } - } - } - - button { - font: @colortheme_app-font; - span { - font: @colortheme_app-font; - } - .fa, &.fa { - font-family: FontAwesome; - } - .cptools, &.cptools { - font-family: cptools; - } - } - - .cp-app-drive-path { - width: 100%; - height: @variables_bar-height; - line-height: @variables_bar-height; - cursor: default; - width: auto; - overflow: hidden; - white-space: nowrap; - flex-shrink: 1; - min-width: 50px; - max-width: 100%; - text-align: left; - display: flex; - flex-direction: row; - - .cp-app-drive-path-inner { + height: @variables_bar-height; display: flex; - flex-flow: row-reverse; - flex-grow: 1; - - .cp-app-drive-path-element { - display: inline-block; - flex-shrink: 0; - max-width: 100%; - height: @variables_bar-height; - line-height: @variables_bar-height; - font-size: @colortheme_app-font-size; - padding: 0 5px; - border: 0; - background: darken(@colortheme_drive-bg, 7%); - color: @colortheme_drive-color; - box-sizing: border-box; - overflow: hidden; - text-overflow: ellipsis; - transition: all 0.15s; - cursor: pointer; - - &:first-child { - flex-shrink: 1; - } - - &.cp-app-drive-path-separator { - color: #ccc; - cursor: default; - } - - &.cp-app-drive-path-collapse { - position: relative; - } - - &.cp-app-drive-element-droppable { - background-color: @drive_droppable-bg; - } - &:not(.cp-app-drive-element-droppable):hover { - &:not(.cp-app-drive-path-separator) { - background-color: darken(@colortheme_drive-bg, 15%); - text-decoration: underline; - } - & ~ .cp-app-drive-path-element { - background-color: darken(@colortheme_drive-bg, 15%); - } - & ~ .cp-app-drive-path-element:not(.cp-app-drive-path-separator) { - text-decoration: underline; - } - } - } + align-items: center; } } - - .cp-app-drive-toolbar-filler { - flex: 1; - } } #cp-app-drive-edition-state { @@ -1003,7 +910,7 @@ display: flex; align-items: center; justify-content: center; - background-color: lighten(@colortheme_drive-bg, 32%); + background-color: @colortheme_drive-bg-active; color: black; font-weight: bold; text-transform: uppercase; diff --git a/customize.dist/src/less2/include/framework.less b/customize.dist/src/less2/include/framework.less index 0d34361ab..94532d5c7 100644 --- a/customize.dist/src/less2/include/framework.less +++ b/customize.dist/src/less2/include/framework.less @@ -42,7 +42,10 @@ .tippy_main(); .checkmark_main(20px); .password_main(); - .messenger_main(); + .messenger_main( + @color: @cryptpad_text_col, + @bg-color: @colortheme_pad-chat-bg + ); .cursor_main(); .usergrid_main(); .mentions_main(); diff --git a/customize.dist/src/less2/include/help.less b/customize.dist/src/less2/include/help.less index 2859b42fa..3bc9ae1e0 100644 --- a/customize.dist/src/less2/include/help.less +++ b/customize.dist/src/less2/include/help.less @@ -1,30 +1,15 @@ @import (reference) "./colortheme-all.less"; -.help_vars ( - @color: @colortheme_default-color, - @bg-color: @colortheme_default-bg -) { - @help-bg-color-l15: lighten(@bg-color, 15%); - @help-text-color: contrast(@help-bg-color-l15, #fff, #000); //@color; - @help-link-color: contrast(@help-bg-color-l15, lighten(spin(@bg-color, 180), 10%), darken(spin(@bg-color, 180), 10%)); -} -.help_main ( - @color: @colortheme_default-color, - @bg-color: @colortheme_default-bg -) { +.help_main () { --LessLoader_require: LessLoader_currentFile(); - .help_vars(@color, @bg-color); - --help-bg-color-l15: @help-bg-color-l15; - --help-text-color: @help-text-color; - --help-link-color: @help-link-color; }; & { - .help_vars(); .cp-help-container { position: relative; - background-color: @help-bg-color-l15; - background-color: var(--help-bg-color-l15); + background-color: @colortheme_help-bg; + max-height: 50%; + overflow-y: auto; &.cp-help-hidden { display: none; } @@ -36,13 +21,11 @@ cursor: pointer; } .cp-help-text { - color: @help-text-color; - color: var(--help-text-color); + color: @cryptpad_text_col; margin: 0; padding: 5px 15px; a { - color: @help-link-color; - color: var(--help-link-color); + color: @colortheme_link-color; } h1 { font-size: 20px; diff --git a/customize.dist/src/less2/include/messenger.less b/customize.dist/src/less2/include/messenger.less index ddf1540c9..66ad741bb 100644 --- a/customize.dist/src/less2/include/messenger.less +++ b/customize.dist/src/less2/include/messenger.less @@ -1,11 +1,32 @@ @import (reference) './avatar.less'; @import (reference) "./colortheme-all.less"; -.messenger_main() { +.messenger_vars ( + @color: @colortheme_friends-color, // color of the toolbar text + @bg-color: @colortheme_friends-bg, // color of the toolbar background +) { + @msg-color: @color; + @msg-bg-color: @bg-color; + @msg-bg-color-light: lighten(@bg-color, 15%); + @msg-bg-color-lighter: lighten(@bg-color, 20%); + @msg-bg-color-dark: darken(@bg-color, 10%); + @msg-bg-color-darker: darken(@bg-color, 20%); +}; +.messenger_main( + @color: @colortheme_friends-color, // color of the toolbar text + @bg-color: @colortheme_friends-bg, // color of the toolbar background +) { --LessLoader_require: LessLoader_currentFile(); + .messenger_vars(@color, @bg-color); + --msg-color: @msg-color; + --msg-bg-color: @msg-bg-color; + --msg-bg-color-light: @msg-bg-color-light; + --msg-bg-color-lighter: @msg-bg-color-lighter; + --msg-bg-color-dark: @msg-bg-color-dark; + --msg-bg-color-darker: @msg-bg-color-darker; }; & { - @keyframes example { + @keyframes notif { 0% { background: rgba(0,0,0,0.1); } @@ -17,9 +38,8 @@ } } + .messenger_vars(); @button-border: 2px; - @bg-color: @colortheme_friends-bg; - @color: @colortheme_friends-color; @room-height: 48px; #cp-app-contacts-container { @@ -57,7 +77,8 @@ #cp-app-contacts-friendlist { width: 200px; height: 100%; - background-color: lighten(@bg-color, 10%); + background-color: @msg-bg-color; + background-color: var(--msg-bg-color); overflow-y: auto; display: flex; flex-flow: column; @@ -86,7 +107,7 @@ background-color: rgba(0,0,0,0.3); } &.cp-app-contacts-notify { - animation: example 2s ease-in-out infinite; + animation: notif 2s ease-in-out infinite; } } .cp-app-contacts-remove { @@ -94,7 +115,7 @@ width: 20px; text-align: center; &:hover { - color: darken(@color, 20%); + color: darken(@msg-color, 20%); } } @@ -183,7 +204,7 @@ display: flex; } cursor: pointer; - color: @color; + color: @msg-color; media-tag { img { color: #000; @@ -252,14 +273,16 @@ #cp-app-contacts-messaging { flex: 1; height: 100%; - background-color: lighten(@bg-color, 20%); + background-color: @msg-bg-color-lighter; + background-color: var(--msg-bg-color-lighter); min-width: 0; .cp-app-contacts-info { padding: 20px; } .cp-app-contacts-header { - background-color: lighten(@bg-color, 15%); + background-color: @msg-bg-color; + background-color: var(--msg-bg-color); padding: 0; display: flex; justify-content: space-between; @@ -289,7 +312,7 @@ //display: none; .hover; &.cp-app-contacts-faded { - color: darken(@bg-color, 5%); + color: @cryptpad_text_col; } } @@ -300,7 +323,8 @@ } .cp-app-contacts-tips { margin: 1em; - background-color: lighten(@bg-color, 15%); + background-color: @msg-bg-color-light; + background-color: var(--msg-bg-color-light); font-size: 14px; padding: 10px; position: relative; @@ -352,7 +376,7 @@ display: none; font-size: 0.8em; align-items: center; - color: @color; + color: @msg-color; font-weight: bold; position: absolute; right: 0; @@ -372,7 +396,8 @@ } } .cp-app-contacts-input { - background-color: lighten(@bg-color, 15%); + background-color: @msg-bg-color-lighter; + background-color: var(--msg-bg-color-lighter); height: auto; min-height: 50px; display: flex; @@ -385,22 +410,28 @@ border: none; height: 54px; // 2 lines (22px height) + 2 margins (5px) flex: 1; - background-color: darken(@bg-color, 10%); - color: @color; + background-color: white; + color: @cryptpad_text_col; + //background-color: @msg-bg-color-dark; + //background-color: var(--msg-bg-color-dark); + //color: @msg-color; resize: none; overflow-y: auto; - .placeholder(#bbb); + .placeholder(#999); &[disabled="true"] { - .placeholder(#999); + .placeholder(#666); } } button { height: 54px !important; border-radius: 0; border: none; - background-color: darken(@bg-color, 15%) !important; + color: #eee; + background-color: @msg-bg-color-darker; + background-color: var(--msg-bg-color-darker); &:hover { - background-color: darken(@bg-color, 20%) !important; + background-color: @msg-bg-color-dark; + background-color: var(--msg-bg-color-dark); } } } diff --git a/customize.dist/src/less2/include/support.less b/customize.dist/src/less2/include/support.less index 0a352ec32..890ba810d 100644 --- a/customize.dist/src/less2/include/support.less +++ b/customize.dist/src/less2/include/support.less @@ -52,6 +52,7 @@ } } .cp-support-list-actions { + display: flex; order: 3; .cp-support-hide { display: none; diff --git a/customize.dist/src/less2/include/toolbar-history.less b/customize.dist/src/less2/include/toolbar-history.less index cb41c2112..7538fb2bc 100644 --- a/customize.dist/src/less2/include/toolbar-history.less +++ b/customize.dist/src/less2/include/toolbar-history.less @@ -82,7 +82,7 @@ } } button { - color: inherit; + color: @cryptpad_text_col; background-color: rgba(0,0,0,0.2); &:hover { background-color: rgba(0,0,0,0.4); diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 542d3f35b..985f6bd83 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -16,21 +16,9 @@ @bg-color: @colortheme_default-bg, // color of the toolbar background @warn-color: @colortheme_default-warn // color of the warning text in the toolbar ) { - @toolbar-color: @color; - @toolbar-color-l20: lighten(@color, 20%); - @toolbar-color-d20: darken(@color, 20%); - @toolbar-color-d15: darken(@color, 15%); - @toolbar-bg-color: @bg-color; - @toolbar-bg-color-l8: lighten(@bg-color, 8%); - @toolbar-bg-color-l20: lighten(@bg-color, 20%); - @toolbar-bg-color-d5: darken(@bg-color, 5%); - @toolbar-bg-color-d10: darken(@bg-color, 10%); - @toolbar-bg-color-d15: darken(@bg-color, 15%); - - @toolbar-warn-color: @warn-color; - - @toolbar-userlist-name-edit: contrast(@toolbar-color, @toolbar-color-l20, @toolbar-color-d20); + @toolbar-bg-color-light: lighten(@bg-color, 30%); + @toolbar-bg-color-active: lighten(@bg-color, 20%); }; .toolbar_main ( @@ -42,31 +30,11 @@ --LessLoader_require: LessLoader_currentFile(); .toolbar_vars(@color, @bg-color, @warn-color); - --toolbar-color: @toolbar-color; - --toolbar-color-l20: @toolbar-color-l20; - --toolbar-color-d20: @toolbar-color-d20; - --toolbar-color-d15: @toolbar-color-d15; - --toolbar-bg-color: @toolbar-bg-color; - --toolbar-bg-color-l8: @toolbar-bg-color-l8; - --toolbar-bg-color-l20: @toolbar-bg-color-l20; - --toolbar-bg-color-d5: @toolbar-bg-color-d5; - --toolbar-bg-color-d10: @toolbar-bg-color-d10; - --toolbar-bg-color-d15: @toolbar-bg-color-d15; - - --toolbar-warn-color: @toolbar-warn-color; - - --toolbar-userlist-name-edit: @toolbar-userlist-name-edit; - - @media screen and (max-width: @barWidth) { - .cp-toolbar-rightside { - flex-wrap: wrap; - height: auto; - width: 100%; - } - } + --toolbar-bg-color-light: @toolbar-bg-color-light; + --toolbar-bg-color-active: @toolbar-bg-color-active; - .help_main(@color, @bg-color); + .help_main(); .notifications_main(); .dropdown_main(); .history_main(); @@ -74,21 +42,13 @@ .modal_main(); }; & { - @keyframes notification { - 0% { - background: rgba(0,0,0,0); - } - 50% { - background: rgba(0,0,0,0.2); - } - 100% { - background: rgba(0,0,0,0); - } - } + @toolbar-color: @cryptpad_text_col; + @toolbar-color-light: lighten(@cryptpad_text_col, 10%); .toolbar_vars(); + @toolbar-top-bg: #eee; @toolbar_line-height: 32px; - @toolbar_top-height: 64px; + @toolbar_top-height: 76px; @toolbar_button-font: @colortheme_app-font; // if we spell 'share' correctly, then adblock plus hides the share button @@ -105,19 +65,16 @@ .cp-markdown-toolbar { height: @toolbar_line-height; - background-color: @toolbar-bg-color-l20; - background-color: var(--toolbar-bg-color-l20); + background-color: @colortheme_pad-toolbar-bg; display: none; button { height: @toolbar_line-height !important; outline: 0; color: @toolbar-color; - color: var(--toolbar-color); .toolbar_button; font: normal normal normal 14px/1 FontAwesome; &:hover { - background-color: @toolbar-bg-color-l8; - background-color: var(--toolbar-bg-color-l8); + background-color: darken(@colortheme_pad-toolbar-bg, 5%); } &.cp-markdown-help { float: right; } } @@ -166,15 +123,13 @@ padding: 0; box-sizing: border-box; position: relative; - order: -2; - resize: horizontal; + order: 99; z-index: 1; #cp-app-contacts-container { height: 100%; } .cp-toolbar-chat-drawer-close { color: @toolbar-color; - color: var(--toolbar-color); position: absolute; top: 0; right: 1px; @@ -196,7 +151,7 @@ overflow-x: hidden; padding: 10px; box-sizing: border-box; - order: -3; + order: 100; z-index: 1; .cp-toolbar-userlist-drawer-close { position: absolute; @@ -386,39 +341,21 @@ } .cp-toolbar-userlist-drawer { - background-color: @toolbar-bg-color; - background-color: var(--toolbar-bg-color); + background-color: @colortheme_userlist-bg; color: @toolbar-color; - color: var(--toolbar-color); .cp-toolbar-userlist-drawer-close { color: @toolbar-color; - color: var(--toolbar-color); } h2 { - background-color: @toolbar-bg-color-d10; - background-color: var(--toolbar-bg-color-d10); color: @toolbar-color; - color: var(--toolbar-color); } .cp-toolbar-userlist-name-input { - background-color: @toolbar-bg-color-d10; - background-color: var(--toolbar-bg-color-d10); - color: @toolbar-color; - color: var(--toolbar-color); + background-color: rgba(0,0,0,0.1); } .cp-toolbar-userlist-button { - color: @toolbar-userlist-name-edit; - color: var(--toolbar-userlist-name-edit); background: transparent; &:hover { - color: @toolbar-color; - color: var(--toolbar-color); - } - } - .cp-toolbar-userlist-friend { - &:hover { - color: @toolbar-color-d15; - color: var(--toolbar-color-d15); + color: @toolbar-color-light; } } } @@ -438,10 +375,10 @@ display: flex; flex-wrap: wrap; justify-content: space-between; - background-color: @toolbar-bg-color; - background-color: var(--toolbar-bg-color); - color: @toolbar-color; - color: var(--toolbar-color); + + background-color: @toolbar-top-bg; + color: @toolbar-bg-color; + color: var(--toolbar-bg-color); .fa { font: normal normal normal 14px/1 FontAwesome; @@ -531,17 +468,13 @@ } .cp-toolbar-title { height: @toolbar_line-height; + flex-flow: row; line-height: initial; margin: 0; .cp-toolbar-title-hoverable { width: 100%; } - .cp-toolbar-title-value-page { - padding: 5px; - line-height: unset; - border: 0; - } - .cp-toolbar-title-editable, .cp-toolbar-title-value-page { + .cp-toolbar-title-editable, .cp-toolbar-title-value { max-width: ~"calc(100vw - 26px)"; display: inline-block; overflow: hidden; @@ -549,13 +482,21 @@ font-size: @colortheme_app-font-size; height: @toolbar_line-height; box-sizing: border-box; - line-height: 20px; + line-height: @toolbar_line-height; + } + .cp-toolbar-title-readonly { + font-size: 14px; + } + .cp-toolbar-title-value { + padding: 5px; + line-height: @toolbar_line-height - 10px; + border: 0; } .cp-toolbar-title-edit, .cp-toolbar-title-save { box-sizing: border-box; height: @toolbar_line-height; - line-height: @colortheme_app-font-size; - display: inline-block; + line-height: @toolbar_line-height; + display: inline-flex; .fa { font-size: @colortheme_app-font-size; @@ -569,9 +510,16 @@ line-height: calc(@toolbar_line-height - 12px); // padding + border } } + .cp-toolbar-spinner { + min-width: 100px; + margin: 0; + height: @toolbar_line-height; + line-height: @toolbar_line-height; + } .cp-toolbar-link { height: @toolbar_line-height; width: @toolbar_line-height; + transform: scale(0.5); .cp-toolbar-link-logo { padding: 5px; } @@ -594,17 +542,6 @@ } } } - .cp-toolbar-new { - height: @toolbar_line-height; - width: @toolbar_line-height; - margin-left: 0; - button { - height: @toolbar_line-height; - width: @toolbar_line-height; - font-size: 20px; - margin-top: -1px; - } - } .cp-toolbar-user-dropdown { height: @toolbar_line-height; width: @toolbar_line-height; @@ -628,105 +565,11 @@ margin: 0; } } - /* - .cp-toolbar-top-filler { - flex: 1; - } - .cp-toolbar-title { - flex: auto; - width: 100%; - order: 10; - height: @toolbar_line-height; - line-height: initial; - margin: 0; - .cp-toolbar-title-hoverable { - width: 100%; - } - .cp-toolbar-title-editable { - max-width: ~"calc(100vw - 26px)"; - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - font-size: @colortheme_app-font-size; - height: @toolbar_line-height; - box-sizing: border-box; - line-height: 20px; - } - .cp-toolbar-title-edit, .cp-toolbar-title-save { - box-sizing: border-box; - height: @toolbar_line-height; - line-height: @colortheme_app-font-size; - display: inline-block; - - .fa { - font-size: @colortheme_app-font-size; - } - } - input { - height: @toolbar_line-height; - font-size: @colortheme_app-font-size; - flex: 1; - max-width: none; - line-height: calc(@toolbar_line-height - 12px); // padding + border - } - } - */ } } - .cp-toolbar-spinner { - font-size: @colortheme_app-font-size; - color: @toolbar-color; - color: var(--toolbar-color); - } .cp-toolbar-limit { - text-shadow: -1px 0 @toolbar-color, 0 1px @toolbar-color, 1px 0 @toolbar-color, 0 -1px @toolbar-color; - text-shadow: -1px 0 var(--toolbar-color), 0 1px var(--toolbar-color), 1px 0 var(--toolbar-color), 0 -1px var(--toolbar-color); - color: @toolbar-warn-color; - color: var(--toolbar-warn-color); - } - .cp-toolbar-leftside, .cp-toolbar-rightside { - background-color: @toolbar-bg-color-l8; - background-color: var(--toolbar-bg-color-l8); - button:hover, button.cp-toolbar-button-active { - background-color: @toolbar-bg-color; - background-color: var(--toolbar-bg-color); - } - } - .cp-toolbar-title-hoverable:hover { - .cp-toolbar-title-editable, .cp-toolbar-title-edit { - cursor: text; - border: 1px solid @toolbar-bg-color-d15; - border: 1px solid var(--toolbar-bg-color-d15); - background: @toolbar-bg-color-d10; - background: var(--toolbar-bg-color-d10); - transition: all 0.15s; - color: @toolbar-color; - color: var(--toolbar-color); - } - .cp-toolbar-title-editable { - cursor: text; - } - } - .cp-toolbar-title-save { - border: 1px solid @toolbar-bg-color-d15; - border: 1px solid var(--toolbar-bg-color-d15); - background: @toolbar-bg-color-d10; - background: var(--toolbar-bg-color-d10); - color: @toolbar-color; - color: var(--toolbar-color); - &:hover { - background: @toolbar-bg-color-d5; - background: var(--toolbar-bg-color-d5); - } - } - input { - border: 1px solid @toolbar-bg-color-d15; - border: 1px solid var(--toolbar-bg-color-d15); - background: @toolbar-bg-color-d10; - background: var(--toolbar-bg-color-d10); - color: @toolbar-color; - color: var(--toolbar-color); + color: @colortheme_toolbar-warn; } .cp-dropdown-content.cp-dropdown-left a { color: black; @@ -752,8 +595,7 @@ padding: 0; margin: 0 5px; font-size: @colortheme_app-font-size; - color: @toolbar-warn-color; - color: var(--toolbar-warn-color); + color: @colortheme_toolbar-warn; .cp-pnp-msg { padding-left: 5px; font-family: @colortheme_font; @@ -762,8 +604,7 @@ font-size: @colortheme_app-font-size; font-family: @colortheme_font; font-weight: bold; - color: @toolbar-warn-color; - color: var(--toolbar-warn-color); + color: @colortheme_toolbar-warn; &:hover { text-decoration: underline; } @@ -784,34 +625,32 @@ //flex: 1; } .cp-toolbar-title { + color: @cryptpad_text_col; flex: 1; overflow: hidden; text-overflow: ellipsis; order: 3; height: 100%; display: inline-flex; - align-items: center; - line-height: @toolbar_top-height; + flex-flow: column; + justify-content: center; margin: 0 10px; .cp-toolbar-title-value { border: 1px solid transparent; - padding: 5px; - font-size: 25px; + padding: 0 5px; + font-size: 30px; vertical-align: middle; - line-height: 25px; white-space: nowrap; } .cp-toolbar-title-value-page { border: 1px solid transparent; padding: 0 5px; - line-height: 48px; } .cp-toolbar-title-edit, .cp-toolbar-title-save { display: flex; align-items: center; font-size: 20px; vertical-align: middle; - line-height: 20px; .fa { font-size: 20px; } @@ -821,21 +660,37 @@ font-size: 25px; font-style: italic; white-space: nowrap; + display: inline-flex; + align-items: center; } .cp-toolbar-title-hoverable { display: inline-flex; overflow: hidden; + align-self: baseline; + max-width: 100%; + &:hover { + .cp-toolbar-title-editable, .cp-toolbar-title-edit { + border: 1px solid @toolbar-bg-color; + border: 1px solid var(--toolbar-bg-color); + transition: all 0.15s; + } + .cp-toolbar-title-editable { + cursor: text; + } + } } .cp-toolbar-title-edit { cursor: pointer; border: 1px solid transparent; - padding: 5px; + padding: 0 5px; border-collapse: collapse; span { cursor: pointer; } } .cp-toolbar-title-save { + border: 1px solid @toolbar-bg-color; + border: 1px solid var(--toolbar-bg-color); cursor: pointer; padding: 5px; border-collapse: collapse; @@ -843,54 +698,45 @@ cursor: pointer; } } - .cp-toolbar-title-editable { + .cp-toolbar-title-value { overflow: hidden; text-overflow: ellipsis; border-collapse: collapse; } input { + color: @cryptpad_text_col; + border: 1px solid @toolbar-bg-color; + border: 1px solid var(--toolbar-bg-color); max-width: ~"calc(100% - 40px)"; //flex: 1; vertical-align: middle; box-sizing: border-box; cursor: auto; width: 300px; - font-size: 20px; - padding: 5px 5px; - height: 40px; - line-height: 28px; // padding + border + font-size: 30px; + padding: 0 5px; + height: 43px; } } - .cp-toolbar-link, .cp-toolbar-new, .cp-toolbar-notifications { - font-size: 48px; - line-height: 64px; + .cp-toolbar-link, .cp-toolbar-notifications { + line-height: @toolbar_top-height; width: @toolbar_top-height; height: @toolbar_top-height; padding: 0; box-sizing: border-box; display: inline-block; - - color: white; - a { - color: white; - } - transition: all 0.15s; } - .cp-toolbar-notifications, .cp-toolbar-new { - background-color: rgba(0,0,0,0.2); - &:hover { - background-color: rgba(0,0,0,0.3); - } + .cp-toolbar-notifications { text-align: center; font-size: 32px; + margin-left: 10px; &> button { display: flex; align-items: center; justify-content: center; - width: 64px; + width: @toolbar_top-height; font-size: 1em; - color: inherit; - height: 64px; + height: @toolbar_top-height; padding: 0px; margin: 0; &::before { @@ -899,8 +745,8 @@ padding-top: 4px; } &:hover { - background-color: initial; border-color: transparent; + background-color: rgba(50,50,50,0.1); } span { vertical-align: top; @@ -909,9 +755,6 @@ color: inherit; } } - } - .cp-toolbar-notifications { - margin-left: 10px; .cp-notifications-empty { color: black; padding: 5px; @@ -920,14 +763,15 @@ position: relative; .cp-dropdown-button-title { position: absolute; - bottom: 0; - right: 0; + bottom: 10px; + right: 16px; font-size: 14px; border: 1px solid; border-radius: 50%; width: 20px; height: 20px; line-height: 16px; + background: @toolbar-top-bg; &.cp-notifications-small { font-size: 10px; line-height: 17px; @@ -940,10 +784,6 @@ align-items: center; justify-content: center; cursor: pointer; - background-color: rgba(0,0,0,0.4); - &:hover { - background-color: rgba(0,0,0,0.5); - } order: 1; .fa { margin: 0; @@ -955,6 +795,13 @@ height: auto; padding: 10px; + svg { + * { + fill: @toolbar-bg-color; + fill: var(--toolbar-bg-color); + } + } + img { cursor: pointer; height: 100%; @@ -967,9 +814,7 @@ display: inline-flex; order: 6; line-height: @toolbar_top-height; - color: white; .cp-toolbar-notifications { order: 1; } - .cp-toolbar-new { order: 2; } .cp-toolbar-user-dropdown { order: 3; } .cp-toolbar-backup { order: 4; } // TODO drive migration to secure iframe &> * { @@ -980,40 +825,44 @@ .cp-toolbar-user-dropdown { z-index: 10000; //Z cp-toolbar-user-dropdown //margin-left: 20px; - height: 64px; - width: 64px; + height: @toolbar_top-height; + width: @toolbar_top-height; padding: 0px; box-sizing: border-box; text-align: center; + +/* background-color: rgba(0,0,0,0.3); transition: all 0.15s; &:hover { background-color: rgba(0,0,0,0.4); } + */ + .cp-dropdown-content { margin: 0; - overflow: visible; } & > button { display: flex; justify-content: center; align-items: center; - height: 64px; - width: 64px; + height: @toolbar_top-height; + width: @toolbar_top-height; padding: 0; + &:hover { + border-color: transparent; + background-color: rgba(50,50,50,0.1); + } span { text-align: center; width: 100%; - font-size: 32px; + font-size: 48px; display: inline-flex; justify-content: center; align-items: center; } &.cp-avatar { - .avatar_main(48px); - media-tag { - margin: 8px; - } + .avatar_main(64px); border: 0; } } @@ -1037,16 +886,37 @@ } } - .cp-toolbar-leftside { - //height: @toolbar_line-height; - &:empty { - height: 0; + .cp-toolbar-history { + background-color: @toolbar-bg-color-light; + background-color: var(--toolbar-bg-color-light); + color: @cryptpad_text_col; + } + .cp-toolbar-bottom { + background-color: @toolbar-bg-color-light; + background-color: var(--toolbar-bg-color-light); + color: @cryptpad_text_col; + button:hover, button.cp-toolbar-button-active { + background-color: @toolbar-bg-color-active; + background-color: var(--toolbar-bg-color-active); + } + button.cp-toolbar-button-active { + border-color: @toolbar-bg-color-active; + border-color: var(--toolbar-bg-color-active); + } + button:hover, button:focus { + border-color: @toolbar-bg-color-active; + border-color: var(--toolbar-bg-color-active); + //border-color: @cryptpad_text_col; } + display: inline-flex; align-items: center; + justify-content: space-between; max-width: 100%; flex: 1 1 auto; - //margin-bottom: -1px; + &:empty { + height: 0; + } .cp-toolbar-users { pre { /* needed for ckeditor */ @@ -1055,146 +925,163 @@ } } button { + border: 1px solid transparent; + box-sizing: border-box; + position: relative; margin: 0px; border-radius: 0; - height: 100%; + height: @toolbar_line-height; + display: inline-flex; + align-items: center; + .fa, .cptools { + margin-right: 5px; + } } - .cp-dropdown-content { - margin-top: -1px; + + &.cp-toolbar-small { + button { + .cp-toolbar-name, .cp-button-name { + display: none; + } + i { + margin-right: 0; + } + } } & > span { height: @toolbar_line-height; } - #cp-toolbar-userlist-drawer-open { order: 0; } - #cp-toolbar-chat-drawer-open { order: 1; } - .cp-toolbar-share-button { order: 2; } - .cp-toolbar-spinner { order: 3; } - #cp-toolbar-userlist-drawer-open button { - width: 125px; - text-align: center; - } - #cp-toolbar-chat-drawer-open button { - &.cp-toolbar-notification { - animation: notification 2s ease-in-out infinite; - } + .cp-toolbar-bottom-left { + display: flex; + order: 1; } - .cp-toolbar-share-button { - width: 50px; - text-align: center; + .cp-toolbar-bottom-mid { + display: flex; + order: 2; } - } - .cp-toolbar-rightside { - display: flex; - min-height: @toolbar_line-height; - overflow: hidden; - &:empty { - min-height: 0; - height: 0; + .cp-toolbar-bottom-right { + order: 3; + display: flex; + #cp-toolbar-chat-drawer-open { order: 0; } + #cp-toolbar-userlist-drawer-open { order: 1; } } - .cp-toolbar-rightside-button { - cursor: pointer; - // UI actions - &.cp-toolbar-icon-toggle { order: 1; } - &.cp-toolbar-icon-preview { order: 2; } - &.cp-toolbar-icon-present { order: 3; } - // Content actions - &.cp-toolbar-icon-mediatag { order: 10; } - order: 11; - // Storage actions - &.cp-toolbar-icon-hashtag { order: 20; } - &.cp-toolbar-icon-template { order: 21; } - &.cp-toolbar-icon-forget { order: 22; } - // Drawer - &.cp-toolbar-drawer-button { order: 30; } - + .cp-toolbar-bottom-right { + button { + white-space: nowrap; + } } + .cp-toolbar-bottom-left { + .cp-toolbar-appmenu, .cp-toolbar-file { + button { + &::before, .fa { + min-width: 20px; + text-align: center; + margin-right: 0; + } + } + } + .cp-toolbar-file { + order: 1; + } + .cp-toolbar-appmenu { + order: 3; + } + .cp-toolbar-mediatag, .cp-toolbar-icon-mediatag { + order: 5; + } + .cp-toolbar-tools { + order: 7; + } + .cp-toolbar-file { + button { + &.fa-plus { order: 0; } + &.fa-history { order: 5; } + &.fa-hashtag { order: 10; } + &.fa-bookmark { order: 15; } + &.fa-upload { order: 20; } + &.fa-clone { order: 25; } + &.fa-download { order: 30; } + &.fa-print { order: 35; } + &.fa-trash { order: 40; } + &.fa-info-circle { order: 100; } - .cp-toolbar-drawer-content:empty ~ .cp-toolbar-drawer-button { - display: none; - } - .cp-toolbar-drawer-content { - box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.2); - position: absolute; - right: 0px; - margin-top: @toolbar_line-height; - min-width: 50px; - background: @colortheme_dropdown-bg; - display: flex; - flex-flow: column; - z-index: 10000; //Z cp-toolbar-drawer-content - color: black; - .fa { - font-size: 17px; + &.cp-toolbar-icon-help { order: 150; } + } } - &> span { - order: 8; - box-sizing: border-box; - min-width: 150px; - height: @toolbar_line-height; - border-radius: 0; - border: 0; + + .cp-toolbar-drawer-content:empty ~ .cp-toolbar-drawer-button { + display: none; } - button { - padding: 5px 16px; - text-align: left; - margin: 0; - border-radius: 0; - border: 0; - width: 100%; - line-height: 1em; - &.cp-toolbar-button-active { - background-color: inherit; + .cp-toolbar-drawer-content { + box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.2); + overflow-y: auto; + overflow-x: hidden; + &.cp-dropdown-visible { + overflow: visible; } - .cp-toolbar-drawer-element { - margin-left: 10px; - display: inline; - vertical-align: baseline; + position: absolute; + left: 0px; + top: @toolbar_line-height; + margin: -1px; + min-width: 50px; + background: @colortheme_dropdown-bg; + display: flex; + flex-flow: column; + z-index: 10000; //Z cp-toolbar-drawer-content + color: black; + .fa { + font-size: 17px; } - &.fa-info-circle, &.fa-history, &.fa-cog { - .cp-toolbar-drawer-element { - margin-left: 11px; - } + &> span { + order: 8; + box-sizing: border-box; + min-width: 150px; + height: @toolbar_line-height; + border-radius: 0; + border: 0; } - &.fa-unlock-alt { - .cp-toolbar-drawer-element { - margin-left: 15px; + button { + white-space: nowrap; + padding: 5px 16px; + text-align: left; + margin: 0; + border-radius: 0; + border: 0; + width: 100%; + line-height: 1em; + &.cp-toolbar-button-active { + background-color: inherit; } - } - &.fa-question { .cp-toolbar-drawer-element { - margin-left: 16px; + margin-left: 10px; + display: inline; + vertical-align: baseline; + } + &:hover { + background-color: @colortheme_dropdown-bg-hover !important; + color: @colortheme_dropdown-color; } } - &:hover { - background-color: @colortheme_dropdown-bg-hover !important; - color: @colortheme_dropdown-color; - } - order: 8; - &.fa-history { order: 1; } - &.fa-clone { order: 1; } - &.fa-download { order: 2; } - &.fa-upload { order: 3; } - &.fa-print { order: 4; } - &.fa-arrows-h { order: 5; } - &.fa-cog { order: 5; } - &.fa-paint-brush { order: 5; } - &.fa-info-circle { order: 6; } - &.fa-help { order: 7; } } } } + .cp-toolbar-spinner { - line-height: @toolbar_line-height; - padding: 0 20px; + color: @cryptpad_text_col; + font-size: 14px; + padding: 0 8px; + height: 20px; + line-height: 20px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 200px; box-sizing: border-box; + margin-bottom: 5px; &> span.fa { height: 20px; width: 20px; diff --git a/package-lock.json b/package-lock.json index 41298194f..9840bd099 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "cryptpad", - "version": "3.17.1", + "version": "3.18.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index dd815c524..56e512b22 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cryptpad", "description": "realtime collaborative visual editor with zero knowlege server", - "version": "3.17.1", + "version": "3.18.1", "license": "AGPL-3.0+", "repository": { "type": "git", diff --git a/www/admin/inner.js b/www/admin/inner.js index 8a9c2d4f4..2ff62cf1f 100644 --- a/www/admin/inner.js +++ b/www/admin/inner.js @@ -2,7 +2,7 @@ define([ 'jquery', '/api/config', '/bower_components/chainpad-crypto/crypto.js', - '/common/toolbar3.js', + '/common/toolbar.js', '/bower_components/nthen/index.js', '/common/sframe-common.js', '/common/hyperscript.js', @@ -255,17 +255,27 @@ define([ if (msg.type !== 'TICKET') { return; } if (!$ticket.length) { - $ticket = APP.support.makeTicket($div, content, function () { + $ticket = APP.support.makeTicket($div, content, function (hideButton) { + // the ticket will still be displayed until the worker confirms its deletion + // so make it unclickable in the meantime + hideButton.setAttribute('disabled', true); var error = false; - hashesById[id].forEach(function (d) { - common.mailbox.dismiss(d, function (err) { - if (err) { - error = true; - console.error(err); - } + nThen(function (w) { + hashesById[id].forEach(function (d) { + common.mailbox.dismiss(d, w(function (err) { + if (err) { + error = true; + console.error(err); + } + })); }); + }).nThen(function () { + if (!error) { return void $ticket.remove(); } + // if deletion failed then reactivate the button and warn + hideButton.removeAttribute('disabled'); + // and show a generic error message + UI.alert(Messages.error); }); - if (!error) { $ticket.remove(); } }); } $ticket.append(APP.support.makeMessage(content, hash)); diff --git a/www/code/inner.js b/www/code/inner.js index 3ffb2baef..de91714c4 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -77,6 +77,31 @@ define([ 'xml', ]); + var mkThemeButton = function (framework) { + var $theme = $(h('button.cp-toolbar-appmenu', [ + h('i.cptools.cptools-palette'), + h('span.cp-button-name', Messages.toolbar_theme) + ])); + var $content = $(h('div.cp-toolbar-drawer-content', { + tabindex: 1 + })).hide(); + + // set up all the necessary events + UI.createDrawer($theme, $content); + + framework._.toolbar.$theme = $content; + framework._.toolbar.$bottomL.append($theme); + }; + + var mkCbaButton = function (framework, markers) { + var $showAuthorColorsButton = framework._.sfCommon.createButton('', true, { + text: Messages.cba_hide, + name: 'authormarks', + icon: 'fa-paint-brush', + }).hide(); + framework._.toolbar.$theme.append($showAuthorColorsButton); + markers.setButton($showAuthorColorsButton); + }; var mkPrintButton = function (framework, $content, $print) { var $printButton = framework._.sfCommon.createButton('print', true); $printButton.click(function () { @@ -92,7 +117,7 @@ define([ var markdownTb = framework._.sfCommon.createMarkdownToolbar(editor); $codeMirrorContainer.prepend(markdownTb.toolbar); - framework._.toolbar.$rightside.append(markdownTb.button); + framework._.toolbar.$bottomL.append(markdownTb.button); var modeChange = function (mode) { if (['markdown', 'gfm'].indexOf(mode) !== -1) { return void markdownTb.setState(true); } @@ -168,7 +193,7 @@ define([ } }); - framework._.toolbar.$rightside.append($previewButton); + framework._.toolbar.$bottomM.append($previewButton); $preview.click(function (e) { if (!e.target) { return; } @@ -325,7 +350,7 @@ define([ setButton(!markers.getState()); UI.alert(content); }); - framework._.toolbar.$drawer.append($cbaButton); + framework._.toolbar.$theme.append($cbaButton); }; var mkFilePicker = function (framework, editor, evModeChange) { @@ -356,6 +381,8 @@ define([ var previewPane = mkPreviewPane(editor, CodeMirror, framework, isPresentMode); var markdownTb = mkMarkdownTb(editor, framework); + mkThemeButton(framework); + var markers = Markers.create({ common: common, framework: framework, @@ -363,18 +390,15 @@ define([ devMode: privateData.devMode, editor: editor }); - - var $showAuthorColorsButton = framework._.sfCommon.createButton('', true, { - icon: 'fa-paint-brush', - }).hide(); - framework._.toolbar.$rightside.append($showAuthorColorsButton); - markers.setButton($showAuthorColorsButton); + mkCbaButton(framework, markers); var $print = $('#cp-app-code-print'); var $content = $('#cp-app-code-preview-content'); mkPrintButton(framework, $content, $print); - mkHelpMenu(framework); + if (!privateData.isEmbed) { + mkHelpMenu(framework); + } var evModeChange = Util.mkEvent(); evModeChange.reg(previewPane.modeChange); diff --git a/www/code/markers.js b/www/code/markers.js index bf3f00f82..b070e68fc 100644 --- a/www/code/markers.js +++ b/www/code/markers.js @@ -604,16 +604,13 @@ define([ var setButton = function (Env, $button) { var toggle = function () { - var tippy = $button[0] && $button[0]._tippy; if (Env.opacity) { Env.opacity = 0; - if (tippy) { tippy.title = Messages.cba_show; } - else { $button.attr('title', Messages.cba_show); } + $button.find('.cp-toolbar-drawer-element').text(Messages.cba_show); $button.removeClass("cp-toolbar-button-active"); } else { Env.opacity = MARK_OPACITY; - if (tippy) { tippy.title = Messages.cba_hide; } - else { $button.attr('title', Messages.cba_hide); } + $button.find('.cp-toolbar-drawer-element').text(Messages.cba_hide); $button.addClass("cp-toolbar-button-active"); } }; @@ -625,30 +622,9 @@ define([ }); }; - var authorUid = function (existing) { - if (!Array.isArray(existing)) { existing = []; } - var n; - var i = 0; - while (!n || existing.indexOf(n) !== -1 && i++ < 1000) { - n = Math.floor(Math.random() * 1000000); - } - // If we can't find a valid number in 1000 iterations, use 0... - if (existing.indexOf(n) !== -1) { n = 0; } - return n; - }; var getAuthorId = function (Env) { - var existing = Object.keys(Env.authormarks.authors || {}).map(Number); - if (!Env.common.isLoggedIn()) { return authorUid(existing); } - var userData = Env.common.getMetadataMgr().getUserData(); - var uid; - existing.some(function (id) { - var author = Env.authormarks.authors[id] || {}; - if (author.curvePublic !== userData.curvePublic) { return; } - uid = Number(id); - return true; - }); - return uid || authorUid(existing); + return Env.common.getAuthorId(Env.authormarks.authors, userData.curvePublic); }; var ready = function (Env) { Env.ready = true; diff --git a/www/common/application_config_internal.js b/www/common/application_config_internal.js index ab573ae70..50249baa8 100644 --- a/www/common/application_config_internal.js +++ b/www/common/application_config_internal.js @@ -12,7 +12,7 @@ define(function() { * You should never remove the drive from this list. */ config.availablePadTypes = ['drive', 'teams', 'pad', 'sheet', 'code', 'slide', 'poll', 'kanban', 'whiteboard', - /*'oodoc', 'ooslide',*/ 'file', 'todo', 'contacts']; + /*'oodoc', 'ooslide',*/ 'file', /*'todo',*/ 'contacts']; /* The registered only types are apps restricted to registered users. * You should never remove apps from this list unless you know what you're doing. The apps * listed here by default can't work without a user account. @@ -20,7 +20,7 @@ define(function() { * users and these users will be redirected to the login page if they still try to access * the app */ - config.registeredOnlyTypes = ['file', 'contacts', 'oodoc', 'ooslide', 'notifications']; + config.registeredOnlyTypes = ['file', 'contacts', 'oodoc', 'ooslide', 'notifications', 'support']; /* CryptPad is available is multiple languages, but only English and French are maintained * by the developers. The other languages may be outdated, and any missing string for a langauge @@ -40,6 +40,12 @@ define(function() { // config.imprint = true; // config.imprint = 'https://xwiki.com/en/company/legal-notice'; + /* You can display a link to your own privacy policy in the static pages footer. + * To do so, set the following value to the absolute URL of your privacy policy. + */ + config.privacy = '/privacy.html'; + // config.privacy = 'https://xwiki.com/en/company/PrivacyPolicy'; + /* Cryptpad apps use a common API to display notifications to users * by default, notifications are hidden after 5 seconds * You can change their duration here (measured in milliseconds) diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 55fe42e2a..6ddf0a320 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -377,6 +377,14 @@ define([ field.focus(); }); + var $field = field.tokenfield.closest('.tokenfield').find('.token-input'); + $field.on('keypress', function (e) { + if (!$field.val() && e.which === 13) { return void $ok.click(); } + }); + $field.on('keydown', function (e) { + if (!$field.val() && e.which === 27) { return void $cancel.click(); } + }); + return tagger; }; @@ -1364,5 +1372,43 @@ define([ }; }; + /* Given two jquery objects (a 'button' and a 'drawer') + add handlers to make it such that clicking the button + displays the drawer contents, and blurring the button + hides the drawer content. Used for toolbar buttons at the moment. + */ + UI.createDrawer = function ($button, $content) { + $button.click(function () { + $content.toggle(); + $button.removeClass('cp-toolbar-button-active'); + if ($content.is(':visible')) { + $button.addClass('cp-toolbar-button-active'); + $content.focus(); + var wh = $(window).height(); + var topPos = $button[0].getBoundingClientRect().bottom; + $content.css('max-height', Math.floor(wh - topPos - 1)+'px'); + } + }); + var onBlur = function (e) { + if (e.relatedTarget) { + var $relatedTarget = $(e.relatedTarget); + + if ($relatedTarget.is('.cp-toolbar-drawer-button')) { return; } + if ($relatedTarget.parents('.cp-toolbar-drawer-content').length) { + $relatedTarget.blur(onBlur); + return; + } + } + $button.removeClass('cp-toolbar-button-active'); + $content.hide(); + }; + $content.blur(onBlur).appendTo($button); + $('body').keydown(function (e) { + if (e.which === 27) { + $content.blur(); + } + }); + }; + return UI; }); diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js index 19b6713da..8c78d9d6d 100644 --- a/www/common/common-thumbnail.js +++ b/www/common/common-thumbnail.js @@ -197,17 +197,26 @@ define([ }; Thumb.fromBlob = function (blob, _cb) { var cb = Util.once(_cb); - if (blob.type.indexOf('video/') !== -1) { - return void Thumb.fromVideoBlob(blob, cb); - } - if (blob.type.indexOf('application/pdf') !== -1) { - return void Thumb.fromPdfBlob(blob, cb); - } - if (Util.isPlainTextFile(blob.type, blob.name)) { - return void Thumb.fromPlainTextBlob(blob, cb); - } - if (blob.type.indexOf('image/') !== -1) { - return void Thumb.fromImageBlob(blob, cb); + // The blob is already in memory, it should be super-fast to make a thumbnail + // ==> 1s timeout + setTimeout(function () { + cb('TIMEOUT'); + }, 1000); + try { + if (blob.type.indexOf('video/') !== -1) { + return void Thumb.fromVideoBlob(blob, cb); + } + if (blob.type.indexOf('application/pdf') !== -1) { + return void Thumb.fromPdfBlob(blob, cb); + } + if (Util.isPlainTextFile(blob.type, blob.name)) { + return void Thumb.fromPlainTextBlob(blob, cb); + } + if (blob.type.indexOf('image/') !== -1) { + return void Thumb.fromImageBlob(blob, cb); + } + } catch (e) { + return void cb('THUMBNAIL_ERROR'); } return void cb('NO_THUMBNAIL'); }; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index fe28eb6d0..91dd5a403 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -21,6 +21,24 @@ define([ Messages, AppConfig, Pages, NThen, InviteInner, Visible) { var UIElements = {}; + UIElements.getSvgLogo = function () { + var svg = (function(){/* + + + + + image/svg+xml + + + + + + + +*/}).toString().slice(14,-3); + return svg; + }; + UIElements.prettySize = function (bytes) { var kB = Util.bytesToKilobytes(bytes); if (kB < 1024) { return kB + Messages.KB; } @@ -28,28 +46,69 @@ define([ return mB + Messages.MB; }; - UIElements.updateTags = function (common, href) { + UIElements.updateTags = function (common, hrefs) { var existing, tags; + var allTags = {}; + if (!hrefs || typeof (hrefs) === "string") { + hrefs = [hrefs]; + } NThen(function(waitFor) { common.getSframeChannel().query("Q_GET_ALL_TAGS", null, waitFor(function(err, res) { if (err || res.error) { return void console.error(err || res.error); } existing = Object.keys(res.tags).sort(); })); }).nThen(function (waitFor) { - common.getPadAttribute('tags', waitFor(function (err, res) { - if (err) { - if (err === 'NO_ENTRY') { - UI.alert(Messages.tags_noentry); + var _err; + hrefs.forEach(function (href) { + common.getPadAttribute('tags', waitFor(function (err, res) { + if (err) { + if (err === 'NO_ENTRY') { + UI.alert(Messages.tags_noentry); + } + waitFor.abort(); + _err = err; + return void console.error(err); } - waitFor.abort(); - return void console.error(err); - } - tags = res || []; - }), href); + allTags[href] = res || []; + + if (tags) { + // Intersect with tags from previous pads + tags = (res || []).filter(function (tag) { + return tags.indexOf(tag) !== -1; + }); + } else { + tags = res || []; + } + }), href); + }); }).nThen(function () { UI.dialog.tagPrompt(tags, existing, function (newTags) { if (!Array.isArray(newTags)) { return; } - common.setPadAttribute('tags', newTags, null, href); + var added = []; + var removed = []; + newTags.forEach(function (tag) { + if (tags.indexOf(tag) === -1) { + added.push(tag); + } + }); + tags.forEach(function (tag) { + if (newTags.indexOf(tag) === -1) { + removed.push(tag); + } + }); + var update = function (oldTags) { + Array.prototype.push.apply(oldTags, added); + removed.forEach(function (tag) { + var idx = oldTags.indexOf(tag); + oldTags.splice(idx, 1); + }); + }; + + hrefs.forEach(function (href) { + var oldTags = allTags[href] || []; + update(oldTags); + common.setPadAttribute('tags', Util.deduplicateString(oldTags), null, href); + }); }); }); }; @@ -1305,6 +1364,7 @@ define([ case 'import': button = $('