From 8cc2ad14b2c7ecf475b083863d37d363437009b0 Mon Sep 17 00:00:00 2001 From: Dario Chiappetta Date: Mon, 30 Nov 2015 11:47:06 +0100 Subject: [PATCH] Minor UI/UX improvements. --- frontend/delta/css/clipperz.css | 48 +++++++++++++++---- frontend/delta/css/clipperz.css.map | 2 +- .../Clipperz/PM/UI/Components/Cards/View.js | 2 - .../UI/Components/ExtraFeatures/DataExport.js | 4 +- .../UI/Components/ExtraFeatures/DevicePIN.js | 16 ++++++- .../js/Clipperz/PM/UI/Components/Overlay.js | 22 +++++++-- .../PM/UI/Components/Pages/UnlockPage.js | 4 +- .../delta/js/Clipperz/PM/UI/MainController.js | 9 +++- frontend/delta/scss/core/overlay.scss | 34 ++++++++++++- 9 files changed, 113 insertions(+), 28 deletions(-) diff --git a/frontend/delta/css/clipperz.css b/frontend/delta/css/clipperz.css index ece2e06..0f2b2ba 100644 --- a/frontend/delta/css/clipperz.css +++ b/frontend/delta/css/clipperz.css @@ -119,6 +119,7 @@ http://jonibologna.com/flexbox-cheatsheet/ -ms-transform: rotate(0deg) translate(0, 0); -o-transform: rotate(0deg) translate(0, 0); transform: rotate(0deg) translate(0, 0); } + 100% { -webkit-transform: rotate(359deg) translate(0, 0); -moz-transform: rotate(359deg) translate(0, 0); @@ -132,6 +133,7 @@ http://jonibologna.com/flexbox-cheatsheet/ -ms-transform: rotate(0deg) translate(0, 0); -o-transform: rotate(0deg) translate(0, 0); transform: rotate(0deg) translate(0, 0); } + 100% { -webkit-transform: rotate(359deg) translate(0, 0); -moz-transform: rotate(359deg) translate(0, 0); @@ -145,6 +147,7 @@ http://jonibologna.com/flexbox-cheatsheet/ -ms-transform: rotate(0deg) translate(0, 0); -o-transform: rotate(0deg) translate(0, 0); transform: rotate(0deg) translate(0, 0); } + 100% { -webkit-transform: rotate(359deg) translate(0, 0); -moz-transform: rotate(359deg) translate(0, 0); @@ -158,6 +161,7 @@ http://jonibologna.com/flexbox-cheatsheet/ -ms-transform: rotate(0deg) translate(0, 0); -o-transform: rotate(0deg) translate(0, 0); transform: rotate(0deg) translate(0, 0); } + 100% { -webkit-transform: rotate(359deg) translate(0, 0); -moz-transform: rotate(359deg) translate(0, 0); @@ -190,6 +194,18 @@ div.overlay { z-index: -2; } div.overlay .mask.hidden { display: none; } + div.overlay .mask.card { + top: 48px; } + .extra-wide div.overlay .mask.card { + left: 46.6%; } + .wide div.overlay .mask.card { + left: 33.3%; } + .narrow div.overlay .mask.card { + left: 100%; } + .extra-wide div.overlay.card { + left: 74%; } + .wide div.overlay.card { + left: 66.6%; } div.overlay .title { color: #FFF; font-weight: bold; @@ -222,7 +238,7 @@ div.overlay { font-size: 96pt; color: white; text-shadow: none; } - div.overlay.ios-overlay-show { + div.overlay.ios-overlay-show:not(.card) { -webkit-animation-name: ios-overlay-show; -webkit-animation-duration: 750ms; -webkit-animation-timing-function: linear; @@ -248,7 +264,7 @@ div.overlay { animation-timing-function: linear; animation-iteration-count: 1; animation-fill-mode: none; } - div.overlay.ios-overlay-hide { + div.overlay.ios-overlay-hide:not(.card) { -webkit-animation-name: ios-overlay-hide; -webkit-animation-duration: 750ms; -webkit-animation-timing-function: linear; @@ -478,61 +494,73 @@ div.overlay { @-webkit-keyframes overlay-spin { from { opacity: 1; } + to { opacity: 0.25; } } @-moz-keyframes overlay-spin { from { opacity: 1; } + to { opacity: 0.25; } } @-ms-keyframes overlay-spin { from { opacity: 1; } + to { opacity: 0.25; } } @keyframes overlay-spin { from { opacity: 1; } + to { opacity: 0.25; } } @-webkit-keyframes ios-overlay-show { 0% { opacity: 0; } + 100% { opacity: 1; } } @-moz-keyframes ios-overlay-show { 0% { opacity: 0; } + 100% { opacity: 1; } } @-ms-keyframes ios-overlay-show { 0% { opacity: 0; } + 100% { opacity: 1; } } @keyframes ios-overlay-show { 0% { opacity: 0; } + 100% { opacity: 1; } } @-webkit-keyframes ios-overlay-hide { 0% { opacity: 1; } + 100% { opacity: 0; } } @-moz-keyframes ios-overlay-hide { 0% { opacity: 1; } + 100% { opacity: 0; } } @-ms-keyframes ios-overlay-hide { 0% { opacity: 1; } + 100% { opacity: 0; } } @keyframes ios-overlay-hide { 0% { opacity: 1; } + 100% { opacity: 0; } } /* @@ -2494,13 +2522,13 @@ span.count { #extraFeaturesPanel .extraFeatureIndex footer { font-size: 8pt; padding: 5px 5px 5px 5px; - border-top: 1px solid #999; } + border-top: 1px solid #999999; } #extraFeaturesPanel .extraFeatureIndex footer span { - color: #999; } + color: #999999; } #extraFeaturesPanel .extraFeatureIndex footer span:after { content: ":"; } #extraFeaturesPanel .extraFeatureIndex footer a { - color: #999; + color: #999999; text-decoration: none; padding-left: 5px; font-weight: bold; } @@ -3298,7 +3326,7 @@ div.cardList ul { padding-right: 0px; box-shadow: -4px 0px 3px -1px rgba(0, 0, 0, 0.2); } div.cardList ul li.archived { - background-color: #eee; + background-color: #eeeeee; color: #999; } div.cardList ul li .favicon { width: 48px; @@ -3398,7 +3426,7 @@ div.cardList.narrow { content: ""; } #cardDetailPage .view.archived, .cardDetail .view.archived { - background-color: #eee; } + background-color: #eeeeee; } #cardDetailPage .view .cardDetailToolbar, .cardDetail .view .cardDetailToolbar { background-color: #1863a1; color: white; } @@ -3848,7 +3876,7 @@ div.cardList.narrow { cursor: grab; cursor: -moz-grab; cursor: -webkit-grab; - background: repeating-linear-gradient(0deg, white, white 2px, #ddd 2px, #ddd 3px); + background: repeating-linear-gradient(0deg, white, white 2px, #dddddd 2px, #dddddd 3px); width: 28px; height: 20px; margin-left: 6px; @@ -4095,7 +4123,7 @@ div.cardList.narrow { min-width: 220px; width: 80%; max-width: 400px; - background-color: #333; + background-color: #333333; color: #fff; -webkit-border-radius: 6px; -moz-border-radius: 6px; @@ -4110,7 +4138,7 @@ div.cardList.narrow { margin-left: 0px; width: 0; height: 0; - border-top: 5px solid #333; + border-top: 5px solid #333333; border-left: 5px solid transparent; border-right: 5px solid transparent; } .passwordGenerator .passwordGeneratorBaloon form span { diff --git a/frontend/delta/css/clipperz.css.map b/frontend/delta/css/clipperz.css.map index 48d23d3..412e42f 100644 --- a/frontend/delta/css/clipperz.css.map +++ b/frontend/delta/css/clipperz.css.map @@ -4,4 +4,4 @@ "sources": ["file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/reset.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/fonts.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/clipperz-font/dejavu.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/mixin.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/overlay.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/layout.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/behavior.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/parameters.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/flex.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/palette.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/tagEditor.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/loadingPage.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/loginPage.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/selectionPanel.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/settingsPanel.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/accountStatus.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/card.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/dialogBox.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/style/help.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/clipperz.scss","file:///home/dario/clipperz/codice/bitbucket-dario/frontend/delta/scss/core/sizes.scss"], "names": [], "file": "clipperz.css" -} \ No newline at end of file +} diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js b/frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js index 0b4e3a8..73b2e60 100644 --- a/frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js +++ b/frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js @@ -423,8 +423,6 @@ Clipperz.PM.UI.Components.Cards.ViewClass = React.createClass({ render: function () { var result; -console.log(this.props['_isBrandNew']); - if (this.props['loading'] == true) { result = this.renderLoading(); } else if (this.props['_reference']) { diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DataExport.js b/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DataExport.js index b833528..cf9af5e 100644 --- a/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DataExport.js +++ b/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DataExport.js @@ -68,7 +68,7 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataExportClass = React.createClass({ React.DOM.h3({}, "Offline copy"), React.DOM.div({'className':'description'}, [ React.DOM.p({}, "Download a read-only portable version of Clipperz. Very convenient when no Internet connection is available."), - React.DOM.p({}, "An offline copy is just a single HTML file that contains both the whole Clipperz web application and your encrypted data."), + React.DOM.p({}, "An offline copy is just a single HTML file that contains both the whole Clipperz web application and your encrypted data, except file attachments."), React.DOM.p({}, "It is as secure as the hosted Clipperz service since they both share the same code and security architecture.") ]), React.DOM.a({'className':'button', 'onClick':this.handleDownloadOfflineCopyLink}, "download offline copy") @@ -77,7 +77,7 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataExportClass = React.createClass({ React.DOM.h3({}, "HTML + JSON"), React.DOM.div({'className':'description'}, [ React.DOM.p({}, "Download a printer-friendly HTML file that lists the content of all your cards."), - React.DOM.p({}, "This same file also contains all your data in JSON format."), + React.DOM.p({}, "This same file also contains all your data in JSON format. Please note that file attachments are not included."), React.DOM.p({'className':'warning'}, "Beware: all data are unencrypted! Therefore make sure to properly store and manage this file.") ]), React.DOM.a({'className':'button', 'onClick':this.handleExportLink}, "download HTML+JSON") diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DevicePIN.js b/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DevicePIN.js index a68271f..6fae7ee 100644 --- a/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DevicePIN.js +++ b/frontend/delta/js/Clipperz/PM/UI/Components/ExtraFeatures/DevicePIN.js @@ -41,13 +41,23 @@ Clipperz.PM.UI.Components.ExtraFeatures.DevicePINClass = React.createClass({ //========================================================================= handleChange: function(anEvent) { - if (anEvent.target.value.length <= this.props['PIN'].DEFAULT_PIN_LENGTH) { + var newValue = anEvent.target.value; + + if (!isNaN(newValue) && newValue.length <= this.props['PIN'].DEFAULT_PIN_LENGTH) { this.setState({ 'pinValue': anEvent.target.value }); } }, + handleSubmit: function(anEvent) { + var isSubmitEnabled = (this.state['pinValue'].length == this.props['PIN'].DEFAULT_PIN_LENGTH); + + if (isSubmitEnabled) { this.savePIN(); } + + anEvent.preventDefault(); + }, + setFocus: function() { this.refs['pinValue'].getDOMNode().focus(); }, @@ -94,7 +104,9 @@ Clipperz.PM.UI.Components.ExtraFeatures.DevicePINClass = React.createClass({ React.DOM.div({'className': 'content'}, [ // React.DOM.p({}, "PIN is "+((this.props['PIN'].isSet()) ? '' : 'not ')+"set on this device"), React.DOM.p({}, ((this.props['PIN'].isSet()) ? "PIN is set on this device" : "PIN is not set on this device")), - React.DOM.form({},[ + React.DOM.form({ + 'onSubmit': this.handleSubmit, + },[ React.DOM.input({ 'type': 'tel', 'key': 'pinValue', diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js b/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js index f0f5869..263d021 100644 --- a/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js +++ b/frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js @@ -53,9 +53,9 @@ Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, { //------------------------------------------------------------------------- - 'show': function (aMessage, showMask, showProgress) { + 'show': function (aMessage, showMask, showProgress, showOnCardDetail) { if (showMask === true) { - this.showMask(); + this.showMask(showOnCardDetail); } if (showProgress === true) { @@ -68,6 +68,12 @@ Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, { MochiKit.DOM.removeElementClass(this.element(), 'spinnerOnly'); } + if (showOnCardDetail) { + MochiKit.DOM.addElementClass(this.element(), 'card'); + } else { + MochiKit.DOM.removeElementClass(this.element(), 'card'); + } + this.resetStatus(); this.setMessage(aMessage); MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-hide'); @@ -90,7 +96,12 @@ Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, { return this.getElement('mask'); }, - 'showMask': function () { + 'showMask': function (showOnCardDetail) { + MochiKit.DOM.removeElementClass(this.maskElement(), 'card'); + + if (showOnCardDetail) { + MochiKit.DOM.addElementClass(this.maskElement(), 'card'); + } MochiKit.DOM.removeElementClass(this.maskElement(), 'hidden'); }, @@ -123,12 +134,13 @@ Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, { return MochiKit.Async.callLater(delay, MochiKit.Base.bind(this.hide, this)) }, - 'hide': function () { + 'hide': function (withoutAnimationTime) { + var secondsBeforeHiding = withoutAnimationTime ? 0 : 1; var element = this.element(); this.hideProgressBar(); MochiKit.DOM.removeElementClass(element, 'ios-overlay-show'); MochiKit.DOM.addElementClass(element, 'ios-overlay-hide'); - return MochiKit.Async.callLater(1, MochiKit.Style.hideElement, element); + return MochiKit.Async.callLater(secondsBeforeHiding, MochiKit.Style.hideElement, element); }, 'hideSpinner': function () { diff --git a/frontend/delta/js/Clipperz/PM/UI/Components/Pages/UnlockPage.js b/frontend/delta/js/Clipperz/PM/UI/Components/Pages/UnlockPage.js index 3c36d4e..4a716ae 100644 --- a/frontend/delta/js/Clipperz/PM/UI/Components/Pages/UnlockPage.js +++ b/frontend/delta/js/Clipperz/PM/UI/Components/Pages/UnlockPage.js @@ -73,7 +73,7 @@ Clipperz.PM.UI.Components.Pages.UnlockPageClass = React.createClass({ this.refs['passphrase'].getDOMNode().blur(); MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'unlock', this.refs['passphrase'].getDOMNode().value, 'PASSPHRASE'); - this.resetUnlockForm(); + // this.resetUnlockForm(); }, submitPIN: function() { @@ -83,7 +83,7 @@ Clipperz.PM.UI.Components.Pages.UnlockPageClass = React.createClass({ MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'unlock', pin, 'PIN'); - this.resetUnlockForm(); + // this.resetUnlockForm(); }, resetUnlockForm: function() { diff --git a/frontend/delta/js/Clipperz/PM/UI/MainController.js b/frontend/delta/js/Clipperz/PM/UI/MainController.js index da89576..bc99158 100644 --- a/frontend/delta/js/Clipperz/PM/UI/MainController.js +++ b/frontend/delta/js/Clipperz/PM/UI/MainController.js @@ -429,6 +429,7 @@ Clipperz.log("THE BROWSER IS OFFLINE"); deferredResult.addMethod(this.user(), 'lock'); deferredResult.addMethod(this, 'deleteCleanTextData'); deferredResult.addMethod(this.pages()['unlockPage'], 'setProps', {'username': this.user().username()}); + deferredResult.addCallback(MochiKit.Async.callLater, 0.1, MochiKit.Base.method(this.pages()['unlockPage'], 'resetUnlockForm')); deferredResult.addMethod(this.pages()['unlockPage'], 'setInitialFocus'); deferredResult.addCallback(MochiKit.Async.callLater, 1, MochiKit.Base.method(this.pages()['mainPage'], 'replaceProps', {'locked': true})); @@ -496,7 +497,7 @@ Clipperz.log("THE BROWSER IS OFFLINE"); 'disabled': false, 'forceCredentials': false, }); - deferredResult.addMethod(unlockPage, 'resetUnlockForm'); + // deferredResult.addMethod(unlockPage, 'resetUnlockForm'); deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'enableLock'); deferredResult.addMethod(overlay, 'done', "", 0.5); @@ -706,7 +707,8 @@ Clipperz.log("THE BROWSER IS OFFLINE"); deferredResult = MochiKit.Async.succeed(); } else { if (showLoading) { - this.setPageProperties('mainPage', 'selectedCard', {'loading':true, 'label':someInfo['label'], '_reference':someInfo['reference']}); + // this.setPageProperties('mainPage', 'selectedCard', {'loading':true, 'label':someInfo['label'], '_reference':someInfo['reference']}); + this.overlay().show('', true, false, true) } deferredResult = new Clipperz.Async.Deferred('MainController.updateSelectedCard', {trace:false}); @@ -717,6 +719,7 @@ Clipperz.log("THE BROWSER IS OFFLINE"); if ((this.mediaQueryStyle() == 'narrow') && shouldShowCardDetail) { deferredResult.addMethod(this, 'showCardDetailInNarrowView'); } + deferredResult.addMethod(this.overlay(), 'hide', true); MochiKit.Async.callLater(0.1, MochiKit.Base.method(deferredResult, 'callback')); } @@ -2117,6 +2120,8 @@ Clipperz.log("THE BROWSER IS OFFLINE"); this._mediaQueryStyle = newQueryStyle; + MochiKit.DOM.setElementClass(document.body, newQueryStyle); + if (currentPage == 'cardDetailPage') { this.moveOutPage(this.currentPage(), 'mainPage'); } diff --git a/frontend/delta/scss/core/overlay.scss b/frontend/delta/scss/core/overlay.scss index 472cfb8..298d74e 100644 --- a/frontend/delta/scss/core/overlay.scss +++ b/frontend/delta/scss/core/overlay.scss @@ -33,6 +33,23 @@ div.overlay { &.hidden { display: none; } + + &.card { + + top: 48px; + + .extra-wide & { + left: 46.6%; + } + + .wide & { + left: 33.3%; + } + + .narrow & { + left: 100%; + } + } } z-index: 99999; position: fixed; @@ -45,6 +62,15 @@ div.overlay { background: rgba(0,0,0,0.8); @include border-radius(20px); + &.card { + .extra-wide & { + left: 74%; + } + .wide & { + left: 66.6%; + } + } + .title { color: #FFF; // font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; @@ -78,12 +104,16 @@ div.overlay { } &.ios-overlay-show { - @include animation(ios-overlay-show, 750ms); + &:not(.card) { + @include animation(ios-overlay-show, 750ms); + } } &.ios-overlay-hide { - @include animation(ios-overlay-hide, 750ms, linear, 1, forwards); + &:not(.card) { + @include animation(ios-overlay-hide, 750ms, linear, 1, forwards); + } } // http://37signals.com/svn/posts/2577-loading-spinner-animation-using-css-and-webkit