diff --git a/app/scripts/auto-type/index.js b/app/scripts/auto-type/index.js index dba86130..d7822513 100644 --- a/app/scripts/auto-type/index.js +++ b/app/scripts/auto-type/index.js @@ -218,7 +218,7 @@ const AutoType = { logger.debug('auto-type event delayed'); this.focusMainWindow(); try { - await AppModel.instance.unlockAnyFile(); + await AppModel.instance.unlockAnyFile('autoTypeUnlockMessage'); } catch { logger.debug('auto-type event canceled'); return; diff --git a/app/scripts/locales/base.json b/app/scripts/locales/base.json index 9ffc8ab6..97e615ff 100644 --- a/app/scripts/locales/base.json +++ b/app/scripts/locales/base.json @@ -361,6 +361,7 @@ "autoTypeSelectionHintOpt": "Only type the username", "autoTypeSelectionHintShift": "Other fields", "autoTypeSelectionOtp": "One-time code", + "autoTypeUnlockMessage": "Unlock to auto-type", "appSecWarn": "Not Secure!", "appSecWarnBody1": "You have loaded this app with an insecure connection. Someone may be watching you and stealing your passwords. We strongly advise you to stop, unless you clearly understand what you're doing.", diff --git a/app/scripts/models/app-model.js b/app/scripts/models/app-model.js index 690411e5..a8c0e888 100644 --- a/app/scripts/models/app-model.js +++ b/app/scripts/models/app-model.js @@ -186,6 +186,7 @@ class AppModel { this.appLogger.info('Running pending file unlock operation'); this.fileUnlockPromise.resolve(file); this.fileUnlockPromise = null; + Events.emit('unlock-message-changed', null); } return true; @@ -1431,19 +1432,25 @@ class AppModel { } } - unlockAnyFile() { + unlockAnyFile(unlockRes) { this.rejectPendingFileUnlockPromise('Replaced with a new operation'); return new Promise((resolve, reject) => { - this.fileUnlockPromise = { resolve, reject }; + this.fileUnlockPromise = { resolve, reject, unlockRes }; this.appLogger.info('Pending file unlock operation is set'); + Events.emit('unlock-message-changed', unlockRes); }); } + get unlockMessageRes() { + return this.fileUnlockPromise?.unlockRes; + } + rejectPendingFileUnlockPromise(reason) { if (this.fileUnlockPromise) { this.appLogger.info('Cancel pending file unlock operation', reason); this.fileUnlockPromise.reject(new Error(reason)); this.fileUnlockPromise = null; + Events.emit('unlock-message-changed', null); } } diff --git a/app/scripts/views/open-view.js b/app/scripts/views/open-view.js index 688e770b..b9979fc9 100644 --- a/app/scripts/views/open-view.js +++ b/app/scripts/views/open-view.js @@ -52,6 +52,7 @@ class OpenView extends View { 'click .open__settings-yubikey': 'selectYubiKeyChalResp', 'click .open__last-item': 'openLast', 'click .open__icon-generate': 'toggleGenerator', + 'click .open__message-cancel-btn': 'openMessageCancelClick', dragover: 'dragover', dragleave: 'dragleave', drop: 'drop' @@ -76,6 +77,7 @@ class OpenView extends View { this.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp, null, 'open'); this.listenTo(Events, 'main-window-focus', this.windowFocused.bind(this)); this.listenTo(Events, 'usb-devices-changed', this.usbDevicesChanged.bind(this)); + this.listenTo(Events, 'unlock-message-changed', this.unlockMessageChanged.bind(this)); this.once('remove', () => { this.passwordInput.reset(); }); @@ -118,6 +120,7 @@ class OpenView extends View { canOpenKeyFromDropbox: !Launcher && Storage.dropbox.enabled, demoOpened: this.model.settings.demoOpened, storageProviders, + unlockMessageRes: this.model.unlockMessageRes, canOpen: this.model.settings.canOpen, canOpenDemo: this.model.settings.canOpenDemo, canOpenSettings: this.model.settings.canOpenSettings, @@ -1159,6 +1162,20 @@ class OpenView extends View { } } } + + unlockMessageChanged(unlockMessageRes) { + const messageEl = this.el.querySelector('.open__message'); + messageEl.classList.toggle('hide', !unlockMessageRes); + + if (unlockMessageRes) { + const contentEl = this.el.querySelector('.open__message-content'); + contentEl.innerText = Locale[unlockMessageRes]; + } + } + + openMessageCancelClick() { + this.model.rejectPendingFileUnlockPromise('User canceled'); + } } export { OpenView }; diff --git a/app/styles/areas/_open.scss b/app/styles/areas/_open.scss index 423abafb..ad7d7f27 100644 --- a/app/styles/areas/_open.scss +++ b/app/styles/areas/_open.scss @@ -340,6 +340,32 @@ margin-top: 1em; } } + + &__message { + display: flex; + justify-content: space-between; + min-width: 20vw; + background: var(--secondary-background-color); + border-radius: var(--block-border-radius); + margin-bottom: $large-padding; + &-content { + padding: $medium-padding; + padding-right: $small-spacing; + } + &-cancel-btn { + padding: $medium-padding; + padding-left: $small-spacing; + cursor: pointer; + opacity: 0.5; + transition: opacity $base-duration $base-timing; + &:hover { + opacity: 1; + } + &-icon { + vertical-align: bottom; + } + } + } } .open-list { diff --git a/app/templates/open.hbs b/app/templates/open.hbs index e0cc6238..94d342cd 100644 --- a/app/templates/open.hbs +++ b/app/templates/open.hbs @@ -1,5 +1,11 @@