mirror of https://github.com/keeweb/keeweb
fix #830: minimize instead of close option on macOS
parent
a2194435e6
commit
2deb241ff2
|
@ -27,8 +27,9 @@ const AutoType = {
|
|||
return;
|
||||
}
|
||||
Events.on('auto-type', e => this.handleEvent(e));
|
||||
Events.on('main-window-blur', e => this.resetPendingEvent(e));
|
||||
Events.on('main-window-will-close', e => this.resetPendingEvent(e));
|
||||
Events.on('main-window-blur', e => this.mainWindowBlur(e));
|
||||
Events.on('main-window-focus', e => this.mainWindowFocus(e));
|
||||
Events.on('main-window-will-close', e => this.mainWindowWillClose(e));
|
||||
Events.on('closed-open-view', e => this.processPendingEvent(e));
|
||||
},
|
||||
|
||||
|
@ -258,6 +259,31 @@ const AutoType = {
|
|||
});
|
||||
},
|
||||
|
||||
mainWindowBlur() {
|
||||
this.mainWindowBlurTimer = setTimeout(() => {
|
||||
// macOS emits focus-blur-focus event in a row when triggering auto-type from minimized state
|
||||
delete this.mainWindowBlurTimer;
|
||||
this.resetPendingEvent();
|
||||
if (this.selectEntryView) {
|
||||
this.selectEntryView.emit('result', undefined);
|
||||
}
|
||||
}, Timeouts.AutoTypeWindowFocusAfterBlur);
|
||||
},
|
||||
|
||||
mainWindowFocus() {
|
||||
if (this.mainWindowBlurTimer) {
|
||||
clearTimeout(this.mainWindowBlurTimer);
|
||||
this.mainWindowBlurTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
mainWindowWillClose() {
|
||||
this.resetPendingEvent();
|
||||
if (this.selectEntryView) {
|
||||
this.selectEntryView.emit('result', undefined);
|
||||
}
|
||||
},
|
||||
|
||||
resetPendingEvent() {
|
||||
if (this.pendingEvent) {
|
||||
this.pendingEvent = null;
|
||||
|
|
|
@ -208,9 +208,6 @@ const Launcher = {
|
|||
minimizeApp() {
|
||||
this.hideApp();
|
||||
},
|
||||
canMinimize() {
|
||||
return false;
|
||||
},
|
||||
canDetectOsSleep() {
|
||||
return false;
|
||||
},
|
||||
|
|
|
@ -163,6 +163,7 @@ const Launcher = {
|
|||
},
|
||||
requestExit() {
|
||||
const app = this.remoteApp();
|
||||
app.setSkipBeforeQuitEvent();
|
||||
if (this.restartPending) {
|
||||
app.restartApp();
|
||||
} else {
|
||||
|
@ -189,15 +190,15 @@ const Launcher = {
|
|||
clipboard.clear('selection');
|
||||
}
|
||||
},
|
||||
quitOnRealQuitEventIfMinimizeOnQuitIsEnabled() {
|
||||
return this.platform() === 'darwin';
|
||||
},
|
||||
minimizeApp() {
|
||||
this.remoteApp().minimizeApp({
|
||||
restore: Locale.menuRestoreApp.replace('{}', 'KeeWeb'),
|
||||
quit: Locale.menuQuitApp.replace('{}', 'KeeWeb')
|
||||
});
|
||||
},
|
||||
canMinimize() {
|
||||
return process.platform !== 'darwin';
|
||||
},
|
||||
canDetectOsSleep() {
|
||||
return process.platform !== 'linux';
|
||||
},
|
||||
|
@ -218,10 +219,10 @@ const Launcher = {
|
|||
},
|
||||
hideApp() {
|
||||
const app = this.remoteApp();
|
||||
if (this.canMinimize()) {
|
||||
app.minimizeThenHideIfInTray();
|
||||
} else {
|
||||
if (this.platform() === 'darwin') {
|
||||
app.hide();
|
||||
} else {
|
||||
app.minimizeThenHideIfInTray();
|
||||
}
|
||||
},
|
||||
isAppFocused() {
|
||||
|
@ -328,6 +329,9 @@ Events.on('app-ready', () =>
|
|||
);
|
||||
|
||||
Launcher.remoteApp().on('remote-app-event', e => {
|
||||
if (window.debugRemoteAppEvents) {
|
||||
logger.debug('remote-app-event', e.name);
|
||||
}
|
||||
Events.emit(e.name, e.data);
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ const Timeouts = {
|
|||
CheckWindowClosed: 300,
|
||||
OtpFadeDuration: 10000,
|
||||
AutoTypeAfterHide: 100,
|
||||
AutoTypeWindowFocusAfterBlur: 500,
|
||||
DropDownClickWait: 500,
|
||||
RedrawInactiveWindow: 50,
|
||||
PopupWaitTime: 1000,
|
||||
|
|
|
@ -90,6 +90,8 @@ class AppView extends View {
|
|||
this.listenTo(Events, 'enter-full-screen', this.enterFullScreen);
|
||||
this.listenTo(Events, 'leave-full-screen', this.leaveFullScreen);
|
||||
this.listenTo(Events, 'import-csv-requested', this.showImportCsv);
|
||||
this.listenTo(Events, 'launcher-before-quit', this.launcherBeforeQuit);
|
||||
|
||||
this.listenTo(UpdateModel, 'change:updateReady', this.updateApp);
|
||||
|
||||
window.onbeforeunload = this.beforeUnload.bind(this);
|
||||
|
@ -334,6 +336,18 @@ class AppView extends View {
|
|||
}
|
||||
}
|
||||
|
||||
launcherBeforeQuit() {
|
||||
// this is currently called only on macos
|
||||
const event = {
|
||||
fromBeforeQuit: true,
|
||||
preventDefault() {}
|
||||
};
|
||||
const result = this.beforeUnload(event);
|
||||
if (result !== false) {
|
||||
Launcher.exit();
|
||||
}
|
||||
}
|
||||
|
||||
beforeUnload(e) {
|
||||
const exitEvent = {
|
||||
preventDefault() {
|
||||
|
@ -342,12 +356,19 @@ class AppView extends View {
|
|||
};
|
||||
Events.emit('main-window-will-close', exitEvent);
|
||||
if (exitEvent.prevented) {
|
||||
Launcher.preventExit(e);
|
||||
return;
|
||||
return Launcher ? Launcher.preventExit(e) : false;
|
||||
}
|
||||
|
||||
let minimizeInsteadOfClose = this.model.settings.minimizeOnClose;
|
||||
if (e.fromBeforeQuit) {
|
||||
if (Launcher.quitOnRealQuitEventIfMinimizeOnQuitIsEnabled()) {
|
||||
minimizeInsteadOfClose = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.model.files.hasDirtyFiles()) {
|
||||
const exit = () => {
|
||||
if (Launcher.canMinimize() && this.model.settings.minimizeOnClose) {
|
||||
if (minimizeInsteadOfClose) {
|
||||
Launcher.minimizeApp();
|
||||
} else {
|
||||
Launcher.exit();
|
||||
|
@ -401,8 +422,7 @@ class AppView extends View {
|
|||
Launcher &&
|
||||
!Launcher.exitRequested &&
|
||||
!Launcher.restartPending &&
|
||||
Launcher.canMinimize() &&
|
||||
this.model.settings.minimizeOnClose
|
||||
minimizeInsteadOfClose
|
||||
) {
|
||||
Launcher.minimizeApp();
|
||||
return Launcher.preventExit(e);
|
||||
|
|
|
@ -32,7 +32,6 @@ class AutoTypeSelectView extends View {
|
|||
constructor(model) {
|
||||
super(model);
|
||||
this.initScroll();
|
||||
this.listenTo(Events, 'main-window-blur', this.mainWindowBlur);
|
||||
this.listenTo(Events, 'main-window-will-close', this.mainWindowWillClose);
|
||||
this.listenTo(Events, 'keypress:auto-type', this.keyPressed);
|
||||
this.setupKeys();
|
||||
|
@ -209,13 +208,8 @@ class AutoTypeSelectView extends View {
|
|||
this.showItemOptions(itemEl, e);
|
||||
}
|
||||
|
||||
mainWindowBlur() {
|
||||
this.cancelAndClose();
|
||||
}
|
||||
|
||||
mainWindowWillClose(e) {
|
||||
e.preventDefault();
|
||||
this.cancelAndClose();
|
||||
}
|
||||
|
||||
showItemOptions(itemEl, event) {
|
||||
|
|
|
@ -89,7 +89,7 @@ class SettingsGeneralView extends View {
|
|||
devTools: Launcher && Launcher.devTools,
|
||||
canAutoUpdate: Updater.enabled,
|
||||
canAutoSaveOnClose: !!Launcher,
|
||||
canMinimize: Launcher && Launcher.canMinimize(),
|
||||
canMinimize: !!Launcher,
|
||||
canDetectMinimize: !!Launcher,
|
||||
canDetectOsSleep: Launcher && Launcher.canDetectOsSleep(),
|
||||
canAutoType: AutoType.enabled,
|
||||
|
|
|
@ -116,6 +116,14 @@ app.on('activate', () => {
|
|||
}
|
||||
}
|
||||
});
|
||||
app.on('before-quit', e => {
|
||||
if (process.platform === 'darwin') {
|
||||
if (!app.skipBeforeQuitEvent) {
|
||||
e.preventDefault();
|
||||
emitRemoteEvent('launcher-before-quit');
|
||||
}
|
||||
}
|
||||
});
|
||||
app.on('will-quit', () => {
|
||||
electron.globalShortcut.unregisterAll();
|
||||
});
|
||||
|
@ -174,6 +182,9 @@ app.minimizeThenHideIfInTray = function() {
|
|||
app.getMainWindow = function() {
|
||||
return mainWindow;
|
||||
};
|
||||
app.setSkipBeforeQuitEvent = () => {
|
||||
app.skipBeforeQuitEvent = true;
|
||||
};
|
||||
app.setGlobalShortcuts = setGlobalShortcuts;
|
||||
app.reqNative = reqNative;
|
||||
app.showAndFocusMainWindow = showAndFocusMainWindow;
|
||||
|
@ -274,10 +285,9 @@ function createMainWindow() {
|
|||
}
|
||||
|
||||
function restoreMainWindow() {
|
||||
// if (process.platform === 'darwin') {
|
||||
// app.dock.show();
|
||||
// mainWindow.show();
|
||||
// }
|
||||
if (process.platform === 'darwin' && !app.dock.isVisible()) {
|
||||
app.dock.show();
|
||||
}
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
|
@ -294,6 +304,9 @@ function showAndFocusMainWindow() {
|
|||
mainWindow.show();
|
||||
}
|
||||
mainWindow.focus();
|
||||
if (process.platform === 'darwin' && !app.dock.isVisible()) {
|
||||
app.dock.show();
|
||||
}
|
||||
}
|
||||
|
||||
function closeMainWindow() {
|
||||
|
|
|
@ -4,6 +4,7 @@ Release notes
|
|||
`+` YubiKey integration in two modes: OATH and Challenge-Response
|
||||
`+` configs are now encrypted with a key stored in keychain
|
||||
`+` #1460: auto-type on double-clicking field labels
|
||||
`+` #830: minimize instead of close option on macOS
|
||||
`+` #557: Argon2 speed improvements in desktop apps
|
||||
`+` #1503: ARM64 Windows support
|
||||
`+` #1480: option to create a portable installation
|
||||
|
|
Loading…
Reference in New Issue