diff --git a/app/scripts/views/fields/field-view-text.js b/app/scripts/views/fields/field-view-text.js index 0125087f..77627aab 100644 --- a/app/scripts/views/fields/field-view-text.js +++ b/app/scripts/views/fields/field-view-text.js @@ -63,13 +63,14 @@ class FieldViewText extends FieldView { } if (Features.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)) - .mousedown(this.showGenerator.bind(this)); + } else { + if (this.model.canGen) { + $('
') + .addClass('details__field-value-btn details__field-value-btn-gen') + .appendTo(this.valueEl) + .click(this.showGeneratorClick.bind(this)) + .mousedown(this.showGenerator.bind(this)); + } } Tip.hideTip(this.valueEl[0]); Tip.hideTip(this.labelEl[0]); diff --git a/app/scripts/views/fields/field-view.js b/app/scripts/views/fields/field-view.js index bc2ba4e9..6e69412f 100644 --- a/app/scripts/views/fields/field-view.js +++ b/app/scripts/views/fields/field-view.js @@ -1,5 +1,6 @@ import kdbxweb from 'kdbxweb'; import { View } from 'framework/views/view'; +import { Events } from 'framework/events'; import { CopyPaste } from 'comp/browser/copy-paste'; import { Tip } from 'util/ui/tip'; import { isEqual } from 'util/fn'; @@ -27,6 +28,9 @@ class FieldView extends View { Tip.hideTip(this.valueEl[0]); } }); + if (Features.isMobile) { + this.listenTo(Events, 'click', this.bodyClick); + } } render() { @@ -114,7 +118,12 @@ class FieldView extends View { } const sel = window.getSelection().toString(); if (!sel) { - this.edit(); + if (Features.isMobile) { + e.stopPropagation(); + this.showMobileActions(); + } else { + this.edit(); + } } } @@ -266,6 +275,76 @@ class FieldView extends View { .removeClass('details__field-value--revealed') .html(this.renderValue(this.value)); } + + bodyClick(e) { + if (!this.mobileActionsEl) { + return; + } + if (this.valueEl[0].contains(e.target) || this.mobileActionsEl[0].contains(e.target)) { + return; + } + this.mobileActionsEl.remove(); + delete this.mobileActionsEl; + } + + showMobileActions() { + if (this.readonly) { + return; + } + if (this.mobileActionsEl) { + this.mobileActionsEl.remove(); + delete this.mobileActionsEl; + return; + } + const left = this.valueEl.position().left; + const width = this.$el.width() - left; + const top = this.valueEl.height(); + + const mobileActionsEl = $('
') + .addClass('details__field-mobile-actions') + .appendTo(this.$el) + .css({ left, top, width }); + + const actions = []; + if (this.value) { + actions.push({ name: 'copy', icon: 'clipboard' }); + } + actions.push({ name: 'edit', icon: 'pencil' }); + if (this.value instanceof kdbxweb.ProtectedValue) { + actions.push({ name: 'reveal', icon: 'eye' }); + } + if (this.model.canGen) { + actions.push({ name: 'generate', icon: 'bolt' }); + } + for (const action of actions) { + $('
') + .addClass(`details__field-mobile-action fa fa-${action.icon}`) + .appendTo(mobileActionsEl) + .click(() => this.doMobileAction(action.name)); + } + + this.mobileActionsEl = mobileActionsEl; + } + + doMobileAction(name) { + this.mobileActionsEl.remove(); + delete this.mobileActionsEl; + switch (name) { + case 'copy': + this.copyValue(); + break; + case 'edit': + this.edit(); + break; + case 'reveal': + this.revealValue(); + break; + case 'generate': + this.edit(); + setTimeout(() => this.showGenerator(), 0); + break; + } + } } export { FieldView }; diff --git a/app/styles/areas/_details.scss b/app/styles/areas/_details.scss index 443a69f0..942e10d3 100644 --- a/app/styles/areas/_details.scss +++ b/app/styles/areas/_details.scss @@ -187,6 +187,7 @@ flex-direction: row; justify-content: flex-start; margin-bottom: 0.5em; + position: relative; &-label { color: var(--muted-color); @@ -457,6 +458,17 @@ color: var(--medium-color); } } + + &-mobile-actions { + position: absolute; + background: var(--background-color); + z-index: $z-index-no-modal; + } + + &-mobile-action { + padding: $medium-padding; + cursor: pointer; + } } &__attachments { diff --git a/release-notes.md b/release-notes.md index ac13e8db..fea01946 100644 --- a/release-notes.md +++ b/release-notes.md @@ -9,6 +9,7 @@ Release notes `+` #480: option to launch the app minimized `+` #1307: option to disable Markdown support `+` #1310: password generator on the start screen +`+` #197: mobile actions panel `-` fix #1273: untranslated menu items `-` fix #1311: better monospace fonts `-` fix #1319: removed a storage request for invalid passwords