fix: Resolve a series of miniWindow display issues and improve app behavior across platforms (#3072)
This commit is contained in:
parent
2da8a73124
commit
8a7db19e73
@ -23,17 +23,8 @@ function getShortcutHandler(shortcut: Shortcut) {
|
|||||||
configManager.setZoomFactor(1)
|
configManager.setZoomFactor(1)
|
||||||
}
|
}
|
||||||
case 'show_app':
|
case 'show_app':
|
||||||
return (window: BrowserWindow) => {
|
return () => {
|
||||||
if (window.isVisible()) {
|
windowService.toggleMainWindow()
|
||||||
if (window.isFocused()) {
|
|
||||||
window.hide()
|
|
||||||
} else {
|
|
||||||
window.focus()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
window.show()
|
|
||||||
window.focus()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case 'mini_window':
|
case 'mini_window':
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@ -16,6 +16,9 @@ export class WindowService {
|
|||||||
private mainWindow: BrowserWindow | null = null
|
private mainWindow: BrowserWindow | null = null
|
||||||
private miniWindow: BrowserWindow | null = null
|
private miniWindow: BrowserWindow | null = null
|
||||||
private wasFullScreen: boolean = false
|
private wasFullScreen: boolean = false
|
||||||
|
//hacky-fix: store the focused status of mainWindow before miniWindow shows
|
||||||
|
//to restore the focus status when miniWindow hides
|
||||||
|
private wasMainWindowFocused: boolean = false
|
||||||
private selectionMenuWindow: BrowserWindow | null = null
|
private selectionMenuWindow: BrowserWindow | null = null
|
||||||
private lastSelectedText: string = ''
|
private lastSelectedText: string = ''
|
||||||
private contextMenu: Menu | null = null
|
private contextMenu: Menu | null = null
|
||||||
@ -30,6 +33,7 @@ export class WindowService {
|
|||||||
public createMainWindow(): BrowserWindow {
|
public createMainWindow(): BrowserWindow {
|
||||||
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
this.mainWindow.show()
|
this.mainWindow.show()
|
||||||
|
this.mainWindow.focus()
|
||||||
return this.mainWindow
|
return this.mainWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +60,7 @@ export class WindowService {
|
|||||||
titleBarOverlay: theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight,
|
titleBarOverlay: theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight,
|
||||||
backgroundColor: isMac ? undefined : theme === 'dark' ? '#181818' : '#FFFFFF',
|
backgroundColor: isMac ? undefined : theme === 'dark' ? '#181818' : '#FFFFFF',
|
||||||
trafficLightPosition: { x: 8, y: 12 },
|
trafficLightPosition: { x: 8, y: 12 },
|
||||||
...(process.platform === 'linux' ? { icon } : {}),
|
...(isLinux ? { icon } : {}),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, '../preload/index.js'),
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
@ -68,6 +72,12 @@ export class WindowService {
|
|||||||
|
|
||||||
this.setupMainWindow(this.mainWindow, mainWindowState)
|
this.setupMainWindow(this.mainWindow, mainWindowState)
|
||||||
|
|
||||||
|
//preload miniWindow to resolve series of issues about miniWindow in Mac
|
||||||
|
const enableQuickAssistant = configManager.getEnableQuickAssistant()
|
||||||
|
if (enableQuickAssistant && !this.miniWindow) {
|
||||||
|
this.miniWindow = this.createMiniWindow(true)
|
||||||
|
}
|
||||||
|
|
||||||
return this.mainWindow
|
return this.mainWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +158,8 @@ export class WindowService {
|
|||||||
// show window only when laucn to tray not set
|
// show window only when laucn to tray not set
|
||||||
const isLaunchToTray = configManager.getLaunchToTray()
|
const isLaunchToTray = configManager.getLaunchToTray()
|
||||||
if (!isLaunchToTray) {
|
if (!isLaunchToTray) {
|
||||||
|
//[mac]hacky-fix: miniWindow set visibleOnFullScreen:true will cause dock icon disappeared
|
||||||
|
app.dock?.show()
|
||||||
mainWindow.show()
|
mainWindow.show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -305,9 +317,8 @@ export class WindowService {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
mainWindow.hide()
|
mainWindow.hide()
|
||||||
|
|
||||||
if (isMac && isTrayOnClose) {
|
//for mac users, should hide dock icon if close to tray
|
||||||
app.dock?.hide() //for mac to hide to tray
|
app.dock?.hide()
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mainWindow.on('closed', () => {
|
mainWindow.on('closed', () => {
|
||||||
@ -328,44 +339,48 @@ export class WindowService {
|
|||||||
|
|
||||||
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
if (this.mainWindow.isMinimized()) {
|
if (this.mainWindow.isMinimized()) {
|
||||||
return this.mainWindow.restore()
|
this.mainWindow.restore()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
//[macOS] Known Issue
|
||||||
|
// setVisibleOnAllWorkspaces true/false will NOT bring window to current desktop in Mac (works fine with Windows)
|
||||||
|
// AppleScript may be a solution, but it's not worth
|
||||||
|
this.mainWindow.setVisibleOnAllWorkspaces(true)
|
||||||
this.mainWindow.show()
|
this.mainWindow.show()
|
||||||
this.mainWindow.focus()
|
this.mainWindow.focus()
|
||||||
|
this.mainWindow.setVisibleOnAllWorkspaces(false)
|
||||||
} else {
|
} else {
|
||||||
this.mainWindow = this.createMainWindow()
|
this.mainWindow = this.createMainWindow()
|
||||||
this.mainWindow.focus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//for mac users, when window is shown, should show dock icon (dock may be set to hide when launch)
|
|
||||||
app.dock?.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public showMiniWindow() {
|
public toggleMainWindow() {
|
||||||
const enableQuickAssistant = configManager.getEnableQuickAssistant()
|
// should not toggle main window when in full screen
|
||||||
|
if (this.wasFullScreen) {
|
||||||
if (!enableQuickAssistant) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectionMenuWindow && !this.selectionMenuWindow.isDestroyed()) {
|
if (this.mainWindow && !this.mainWindow.isDestroyed() && this.mainWindow.isVisible()) {
|
||||||
this.selectionMenuWindow.hide()
|
if (this.mainWindow.isFocused()) {
|
||||||
}
|
// if tray is enabled, hide the main window, else do nothing
|
||||||
|
if (configManager.getTray()) {
|
||||||
if (this.miniWindow && !this.miniWindow.isDestroyed()) {
|
this.mainWindow.hide()
|
||||||
if (this.miniWindow.isMinimized()) {
|
app.dock?.hide()
|
||||||
this.miniWindow.restore()
|
}
|
||||||
|
} else {
|
||||||
|
this.mainWindow.focus()
|
||||||
}
|
}
|
||||||
this.miniWindow.show()
|
|
||||||
this.miniWindow.center()
|
|
||||||
this.miniWindow.focus()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.showMainWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
public createMiniWindow(isPreload: boolean = false): BrowserWindow {
|
||||||
this.miniWindow = new BrowserWindow({
|
this.miniWindow = new BrowserWindow({
|
||||||
width: 500,
|
width: 500,
|
||||||
height: 520,
|
height: 520,
|
||||||
show: true,
|
show: false,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
transparent: isMac,
|
transparent: isMac,
|
||||||
vibrancy: 'under-window',
|
vibrancy: 'under-window',
|
||||||
@ -375,6 +390,11 @@ export class WindowService {
|
|||||||
alwaysOnTop: true,
|
alwaysOnTop: true,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
|
...(isMac ? { type: 'panel' } : {}),
|
||||||
|
skipTaskbar: true,
|
||||||
|
minimizable: false,
|
||||||
|
maximizable: false,
|
||||||
|
fullscreenable: false,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, '../preload/index.js'),
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
@ -383,8 +403,23 @@ export class WindowService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//miniWindow should show in current desktop
|
||||||
|
this.miniWindow?.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true })
|
||||||
|
//make miniWindow always on top of fullscreen apps with level set
|
||||||
|
this.miniWindow.setAlwaysOnTop(true, 'screen-saver', 1)
|
||||||
|
|
||||||
|
this.miniWindow.on('ready-to-show', () => {
|
||||||
|
if (isPreload) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wasMainWindowFocused = this.mainWindow?.isFocused() || false
|
||||||
|
this.miniWindow?.center()
|
||||||
|
this.miniWindow?.show()
|
||||||
|
})
|
||||||
|
|
||||||
this.miniWindow.on('blur', () => {
|
this.miniWindow.on('blur', () => {
|
||||||
this.miniWindow?.hide()
|
this.hideMiniWindow()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.miniWindow.on('closed', () => {
|
this.miniWindow.on('closed', () => {
|
||||||
@ -410,9 +445,48 @@ export class WindowService {
|
|||||||
hash: '#/mini'
|
hash: '#/mini'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.miniWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
public showMiniWindow() {
|
||||||
|
const enableQuickAssistant = configManager.getEnableQuickAssistant()
|
||||||
|
|
||||||
|
if (!enableQuickAssistant) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selectionMenuWindow && !this.selectionMenuWindow.isDestroyed()) {
|
||||||
|
this.selectionMenuWindow.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.miniWindow && !this.miniWindow.isDestroyed()) {
|
||||||
|
this.wasMainWindowFocused = this.mainWindow?.isFocused() || false
|
||||||
|
|
||||||
|
if (this.miniWindow.isMinimized()) {
|
||||||
|
this.miniWindow.restore()
|
||||||
|
}
|
||||||
|
this.miniWindow.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.miniWindow = this.createMiniWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
public hideMiniWindow() {
|
public hideMiniWindow() {
|
||||||
|
//hacky-fix:[mac/win] previous window(not self-app) should be focused again after miniWindow hide
|
||||||
|
if (isWin) {
|
||||||
|
this.miniWindow?.minimize()
|
||||||
|
this.miniWindow?.hide()
|
||||||
|
return
|
||||||
|
} else if (isMac) {
|
||||||
|
this.miniWindow?.hide()
|
||||||
|
if (!this.wasMainWindowFocused) {
|
||||||
|
app.hide()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.miniWindow?.hide()
|
this.miniWindow?.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,11 +495,12 @@ export class WindowService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public toggleMiniWindow() {
|
public toggleMiniWindow() {
|
||||||
if (this.miniWindow) {
|
if (this.miniWindow && !this.miniWindow.isDestroyed() && this.miniWindow.isVisible()) {
|
||||||
this.miniWindow.isVisible() ? this.miniWindow.hide() : this.miniWindow.show()
|
this.hideMiniWindow()
|
||||||
} else {
|
return
|
||||||
this.showMiniWindow()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.showMiniWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
public showSelectionMenu(bounds: { x: number; y: number }) {
|
public showSelectionMenu(bounds: { x: number; y: number }) {
|
||||||
|
|||||||
@ -1190,7 +1190,7 @@
|
|||||||
"reset_defaults_confirm": "Are you sure you want to reset all shortcuts?",
|
"reset_defaults_confirm": "Are you sure you want to reset all shortcuts?",
|
||||||
"reset_to_default": "Reset to Default",
|
"reset_to_default": "Reset to Default",
|
||||||
"search_message": "Search Message",
|
"search_message": "Search Message",
|
||||||
"show_app": "Show App",
|
"show_app": "Show/Hide App",
|
||||||
"show_settings": "Open Settings",
|
"show_settings": "Open Settings",
|
||||||
"title": "Keyboard Shortcuts",
|
"title": "Keyboard Shortcuts",
|
||||||
"toggle_new_context": "Clear Context",
|
"toggle_new_context": "Clear Context",
|
||||||
|
|||||||
@ -1189,7 +1189,7 @@
|
|||||||
"reset_defaults_confirm": "すべてのショートカットをリセットしてもよろしいですか?",
|
"reset_defaults_confirm": "すべてのショートカットをリセットしてもよろしいですか?",
|
||||||
"reset_to_default": "デフォルトにリセット",
|
"reset_to_default": "デフォルトにリセット",
|
||||||
"search_message": "メッセージを検索",
|
"search_message": "メッセージを検索",
|
||||||
"show_app": "アプリを表示",
|
"show_app": "アプリを表示/非表示",
|
||||||
"show_settings": "設定を開く",
|
"show_settings": "設定を開く",
|
||||||
"title": "ショートカット",
|
"title": "ショートカット",
|
||||||
"toggle_new_context": "コンテキストをクリア",
|
"toggle_new_context": "コンテキストをクリア",
|
||||||
|
|||||||
@ -1189,7 +1189,7 @@
|
|||||||
"reset_defaults_confirm": "Вы уверены, что хотите сбросить все горячие клавиши?",
|
"reset_defaults_confirm": "Вы уверены, что хотите сбросить все горячие клавиши?",
|
||||||
"reset_to_default": "Сбросить настройки по умолчанию",
|
"reset_to_default": "Сбросить настройки по умолчанию",
|
||||||
"search_message": "Поиск сообщения",
|
"search_message": "Поиск сообщения",
|
||||||
"show_app": "Показать приложение",
|
"show_app": "Показать/скрыть приложение",
|
||||||
"show_settings": "Открыть настройки",
|
"show_settings": "Открыть настройки",
|
||||||
"title": "Горячие клавиши",
|
"title": "Горячие клавиши",
|
||||||
"toggle_new_context": "Очистить контекст",
|
"toggle_new_context": "Очистить контекст",
|
||||||
|
|||||||
@ -1190,7 +1190,7 @@
|
|||||||
"reset_defaults_confirm": "确定要重置所有快捷键吗?",
|
"reset_defaults_confirm": "确定要重置所有快捷键吗?",
|
||||||
"reset_to_default": "重置为默认",
|
"reset_to_default": "重置为默认",
|
||||||
"search_message": "搜索消息",
|
"search_message": "搜索消息",
|
||||||
"show_app": "显示应用",
|
"show_app": "显示/隐藏应用",
|
||||||
"show_settings": "打开设置",
|
"show_settings": "打开设置",
|
||||||
"title": "快捷方式",
|
"title": "快捷方式",
|
||||||
"toggle_new_context": "清除上下文",
|
"toggle_new_context": "清除上下文",
|
||||||
|
|||||||
@ -1189,7 +1189,7 @@
|
|||||||
"reset_defaults_confirm": "確定要重設所有快捷鍵嗎?",
|
"reset_defaults_confirm": "確定要重設所有快捷鍵嗎?",
|
||||||
"reset_to_default": "重設為預設",
|
"reset_to_default": "重設為預設",
|
||||||
"search_message": "搜尋訊息",
|
"search_message": "搜尋訊息",
|
||||||
"show_app": "顯示應用程式",
|
"show_app": "顯示/隱藏應用程式",
|
||||||
"show_settings": "開啟設定",
|
"show_settings": "開啟設定",
|
||||||
"title": "快速方式",
|
"title": "快速方式",
|
||||||
"toggle_new_context": "清除上下文",
|
"toggle_new_context": "清除上下文",
|
||||||
|
|||||||
@ -175,7 +175,7 @@ const GeneralSettings: FC = () => {
|
|||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
<SettingRowTitle>{t('settings.tray.onclose')}</SettingRowTitle>
|
<SettingRowTitle>{t('settings.tray.onclose')}</SettingRowTitle>
|
||||||
<Switch checked={trayOnClose} onChange={(checked) => updateTrayOnClose(checked)} disabled={!tray} />
|
<Switch checked={trayOnClose} onChange={(checked) => updateTrayOnClose(checked)} />
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user