Skip to content

fix: keep plugin window visible after file dialogs#518

Merged
lzx8589561 merged 3 commits into
ZToolsCenter:mainfrom
jn12-29:fix/plugin-dialog-file-picker-hide-minimal
Jun 3, 2026
Merged

fix: keep plugin window visible after file dialogs#518
lzx8589561 merged 3 commits into
ZToolsCenter:mainfrom
jn12-29:fix/plugin-dialog-file-picker-hide-minimal

Conversation

@jn12-29

@jn12-29 jn12-29 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • suppress plugin window blur/mouseup hiding while plugin open/save dialogs are active
  • keep existing Linux delayed blur handling and Windows/macOS immediate blur behavior intact
  • use a dialog-specific suppression flag so existing blur suppression flows keep their own state

Why

Plugin showOpenDialog / showSaveDialog calls can blur the main window and emit a trailing mouseup when the native dialog closes. ZTools treated those events like an outside click and hid the plugin window after selecting a file.

Verification

  • node_modules/.bin/tsc.cmd --noEmit -p tsconfig.node.json --composite false
  • node_modules/.bin/vue-tsc.cmd --noEmit -p tsconfig.web.json --composite false
  • internal-plugins/setting/node_modules/.bin/vue-tsc.cmd --noEmit
  • node_modules/.bin/eslint.cmd --quiet src/main/api/plugin/dialog.ts src/main/managers/windowManager.ts
  • node_modules/.bin/electron-vite.cmd build
  • internal-plugins/setting/node_modules/.bin/vite.cmd build
  • node_modules/.bin/electron-builder.cmd --dir
  • Manually tested with the AI Agents dev plugin: selecting an image through the plugin file picker keeps the ZTools window visible, while normal outside clicks still hide it.

Copilot AI review requested due to automatic review settings June 1, 2026 12:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR prevents the main window from auto-hiding due to queued blur/mouseup events emitted around native modal dialog close, by introducing a dedicated “blur-hide suppression” guard and using it when showing plugin dialogs.

Changes:

  • Added modal-dialog-specific blur-hide suppression state and centralized isBlurHideSuppressed() checks across blur/mouseup hide paths.
  • Introduced withBlurHideSuppressed() helper to scope suppression around modal operations with a short delayed release.
  • Wrapped plugin file open/save dialogs with withBlurHideSuppressed() to avoid unintended window hiding.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/main/managers/windowManager.ts Adds modal-dialog blur-hide suppression state, helper methods, and integrates suppression checks into blur/mouseup handling.
src/main/api/plugin/dialog.ts Wraps synchronous open/save dialogs with the new suppression helper to prevent unwanted auto-hide.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main/managers/windowManager.ts Outdated
Comment thread src/main/managers/windowManager.ts Outdated
Comment thread src/main/managers/windowManager.ts

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to temporarily suppress window hiding on blur when native modal dialogs (such as file open/save dialogs) are displayed. This is achieved by wrapping synchronous dialog calls in a new withBlurHideSuppressed helper within WindowManager. The review feedback points out that withBlurHideSuppressed currently only supports synchronous callbacks, which would cause the suppression to release prematurely if an asynchronous callback (returning a Promise) is used. A robust implementation handling both synchronous and asynchronous callbacks was suggested.

Comment thread src/main/managers/windowManager.ts Outdated
@jn12-29 jn12-29 requested a review from Copilot June 1, 2026 12:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread src/main/managers/windowManager.ts Outdated
Comment on lines +86 to +89
// Native modal dialogs can emit queued blur/mouseup events around close.
private modalDialogBlurHideSuppressed: boolean = false
private modalDialogBlurHideReleaseTimer: ReturnType<typeof setTimeout> | null = null
private modalDialogBlurHideSuppressionDepth: number = 0
Comment on lines +904 to +907
public withBlurHideSuppressed<T>(
callback: () => T | PromiseLike<T>,
releaseDelayMs: number = 500
): T | Promise<T> {
Comment thread src/main/api/plugin/dialog.ts Outdated
Comment on lines +79 to +81
const result = windowManager.withBlurHideSuppressed(() =>
dialog.showSaveDialogSync(targetWindow, options)
)
@jn12-29 jn12-29 requested a review from Copilot June 1, 2026 15:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment on lines +903 to +927
public withBlurHideSuppressed<T>(
callback: () => PromiseLike<T>,
releaseDelayMs?: number
): Promise<T>
public withBlurHideSuppressed<T>(callback: () => T, releaseDelayMs?: number): T
public withBlurHideSuppressed<T>(
callback: () => T | PromiseLike<T>,
releaseDelayMs: number = DEFAULT_MODAL_DIALOG_BLUR_HIDE_RELEASE_DELAY_MS
): T | Promise<T> {
this.beginModalDialogBlurHideSuppression()
try {
const result = callback()
if (this.isPromiseLike(result)) {
return Promise.resolve(result).finally(() => {
this.endModalDialogBlurHideSuppression(releaseDelayMs)
})
}

this.endModalDialogBlurHideSuppression(releaseDelayMs)
return result
} catch (error) {
this.endModalDialogBlurHideSuppression(releaseDelayMs)
throw error
}
}
Comment on lines +87 to +90
// 原生模态对话框关闭前后可能发出排队的 blur/mouseup 事件。
private modalDialogBlurHideSuppressed: boolean = false
private modalDialogBlurHideReleaseTimer: ReturnType<typeof setTimeout> | null = null
private modalDialogBlurHideSuppressionDepth: number = 0
Comment on lines +164 to +179
private endModalDialogBlurHideSuppression(releaseDelayMs: number): void {
this.modalDialogBlurHideSuppressionDepth = Math.max(
0,
this.modalDialogBlurHideSuppressionDepth - 1
)
if (this.modalDialogBlurHideSuppressionDepth > 0) return

if (this.modalDialogBlurHideReleaseTimer) {
clearTimeout(this.modalDialogBlurHideReleaseTimer)
}

this.modalDialogBlurHideReleaseTimer = setTimeout(() => {
this.modalDialogBlurHideSuppressed = false
this.modalDialogBlurHideReleaseTimer = null
}, releaseDelayMs)
}
@lzx8589561 lzx8589561 merged commit 5e2dd23 into ZToolsCenter:main Jun 3, 2026
@jn12-29 jn12-29 deleted the fix/plugin-dialog-file-picker-hide-minimal branch June 7, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants