From dbdacfc0bdffe90facec713979f61e7972325bde Mon Sep 17 00:00:00 2001 From: bartool Date: Fri, 6 Mar 2026 19:45:56 +0100 Subject: [PATCH] fix: resolve UI freeze by separating pystray and tkinter event loops --- git_monitor/tray_app.py | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/git_monitor/tray_app.py b/git_monitor/tray_app.py index 91f4ccb..b921865 100644 --- a/git_monitor/tray_app.py +++ b/git_monitor/tray_app.py @@ -42,14 +42,33 @@ class TrayApp: self.icon = pystray.Icon("GitMonitor", image, "Git Monitor", menu) def select_repository(self, icon=None, item=None): - # Open folder dialog in a separate thread or use the hidden root - # tkinter dialogs need to run in the main thread or with care - repo_path = filedialog.askdirectory(title="Select Git Repository Folder") - if repo_path: - logger.info(f"User selected repository: {repo_path}") - if git_manager.load_repository(repo_path): - config.repository_path = repo_path - self.start_monitoring(repo_path) + logger.info("Opening folder selection dialog...") + # Use a temporary function to run in a way that doesn't block + def ask_folder(): + try: + # Ensure the root window is focused and on top + self.root.deiconify() + self.root.attributes("-topmost", True) + + repo_path = filedialog.askdirectory( + parent=self.root, + title="Select Git Repository Folder" + ) + + self.root.withdraw() + + if repo_path: + logger.info(f"User selected repository: {repo_path}") + if git_manager.load_repository(repo_path): + config.repository_path = repo_path + self.start_monitoring(repo_path) + else: + logger.info("Folder selection cancelled by user.") + except Exception as e: + logger.error(f"Error in folder selection: {e}") + + # Schedule the dialog to run + self.root.after(0, ask_folder) def start_monitoring(self, path): if self.watcher: @@ -75,7 +94,10 @@ class TrayApp: def run(self): self.create_icon() - self.icon.run() + # Run pystray in a separate thread + threading.Thread(target=self.icon.run, daemon=True).start() + # Keep the main thread for tkinter mainloop to handle dialogs + self.root.mainloop() if __name__ == "__main__": app = TrayApp()