From 769ba1c12b3bd2ffe311e65bed920303b647202d Mon Sep 17 00:00:00 2001 From: antelle Date: Sat, 15 Apr 2017 23:26:52 +0200 Subject: [PATCH] mobile field editing improvements --- app/scripts/views/fields/field-view-text.js | 45 ++++++++++++++++++++- app/styles/areas/_details.scss | 29 +++++++++++++ release-notes.md | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/app/scripts/views/fields/field-view-text.js b/app/scripts/views/fields/field-view-text.js index 157cce04..dcee47d3 100644 --- a/app/scripts/views/fields/field-view-text.js +++ b/app/scripts/views/fields/field-view-text.js @@ -4,6 +4,7 @@ const GeneratorView = require('../generator-view'); const KeyHandler = require('../../comp/key-handler'); const Keys = require('../../const/keys'); const PasswordGenerator = require('../../util/password-generator'); +const FeatureDetector = require('../../util/feature-detector'); const kdbxweb = require('kdbxweb'); const FieldViewText = FieldView.extend({ @@ -36,6 +37,9 @@ const FieldViewText = FieldView.extend({ if (this.model.multiline) { this.setInputHeight(); } + if (FeatureDetector.isMobile) { + this.createMobileControls(); + } if (this.model.canGen) { $('
').addClass('details__field-value-btn details__field-value-btn-gen').appendTo(this.valueEl) .click(this.showGeneratorClick.bind(this)) @@ -43,6 +47,21 @@ const FieldViewText = FieldView.extend({ } }, + createMobileControls: function() { + this.mobileControls = {}; + ['cancel', 'apply'].forEach(action => { + this.mobileControls[action] = $('
') + .addClass('details__field-value-btn details__field-value-btn-' + action) + .appendTo(this.labelEl) + .data('action', action) + .on({ + mousedown: this.mobileFieldControlClick.bind(this), + touchstart: this.mobileFieldControlTouchStart.bind(this), + touchend: this.mobileFieldControlTouchEnd.bind(this) + }); + }); + }, + showGeneratorClick: function(e) { e.stopPropagation(); if (!this.gen) { @@ -163,6 +182,11 @@ const FieldViewText = FieldView.extend({ return; } delete this.input; + if (this.mobileControls) { + this.mobileControls.cancel.remove(); + this.mobileControls.apply.remove(); + delete this.mobileControls; + } this.stopBlurListener(); if (typeof newVal === 'string' && this.value instanceof kdbxweb.ProtectedValue) { newVal = kdbxweb.ProtectedValue.fromString(newVal); @@ -177,7 +201,26 @@ const FieldViewText = FieldView.extend({ this.stopListening(Backbone, 'click main-window-will-close', this.fieldValueBlur); }, - render: function() { + mobileFieldControlClick(e) { + e.stopPropagation(); + this.stopBlurListener(); + const action = $(e.target).data('action'); + if (action === 'apply') { + this.endEdit(this.input.val()); + } else { + this.endEdit(); + } + }, + + mobileFieldControlTouchStart(e) { + this.$el.attr('active-mobile-action', $(e.target).data('action')); + }, + + mobileFieldControlTouchEnd() { + this.$el.removeAttr('active-mobile-action'); + }, + + render() { FieldView.prototype.render.call(this); } }); diff --git a/app/styles/areas/_details.scss b/app/styles/areas/_details.scss index 070c2592..b8f6f29b 100644 --- a/app/styles/areas/_details.scss +++ b/app/styles/areas/_details.scss @@ -172,6 +172,7 @@ padding-right: 1em; border: 1px solid transparent; line-height: $details-field-line-height; + position: relative; &:hover { @include th { color: medium-color(); } } @@ -240,6 +241,16 @@ width: 100%; height: 20px; .details__field--protected & { font-family: $monospace-font-family; } + transition: background-color $slow-transition-out, border-color $slow-transition-out; + .details__field--edit[active-mobile-action] & { + transition: background-color $slow-transition-in, border-color $slow-transition-in; + } + .details__field--edit[active-mobile-action=apply] & { + @include th { background: action-color(); } + } + .details__field--edit[active-mobile-action=cancel] & { + @include th { background: error-color(); border-color: error-color(); } + } } >input { .chrome & { padding-bottom: 1px; } // TODO: find a better cross-browser way to do it @@ -281,6 +292,24 @@ &:before { content: $fa-var-unlock; } .details__field--protected & { &:before { content: $fa-var-lock; } } } + @include mobile { + &-btn-apply, &-btn-cancel { + height: 100%; + width: 50%; + position: absolute; + top: 0; + &:before { padding: .2em 1.5em; } + @include th { background: background-color(); } + } + &-btn-apply { + &:before { content: $fa-var-check; } + right: 0; + } + &-btn-cancel { + &:before { content: $fa-var-times; } + left: 0; + } + } &--select { border-width: 0; padding: 0; diff --git a/release-notes.md b/release-notes.md index e692f481..16935014 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,7 @@ Release notes ##### v1.5.0 (TBD) `+` plugins `*` translations are available only as plugins +`+` mobile field editing improvements `+` file path hint in recent files list `+` cacheConfigSettings config option `+` keyboard-accessible autocomplete