From 9c17f452bffe242b8b3cd091cb62d528d1c0bced Mon Sep 17 00:00:00 2001 From: Pavel Baksy Date: Wed, 24 Dec 2025 03:07:11 +0100 Subject: [PATCH] Fix critical bugs from second round of testing 1. Fixed infinite loop when closing last tab: - Return False instead of True when page already removed (prevents double-processing) - Remove from tracking BEFORE calling close_page_finish to prevent re-trigger - Properly schedule new tab creation only once 2. Fixed modified flag not clearing after save: - Update widget.original_request in _mark_tab_as_saved - Update widget.modified = False - Manually call _on_tab_modified_changed to clear indicator - Update tab page title when saving 3. Fixed header bar height and left spacing: - Added CSS to reduce headerbar min-height to 38px - Set headerbar padding-left to 0px to eliminate left gap - Made tabs more compact (min-height: 26px, reduced padding) - Reduced tabbar padding and margins All critical issues from testing resolved! --- src/window.py | 82 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/src/window.py b/src/window.py index 4fde354..1e34f87 100644 --- a/src/window.py +++ b/src/window.py @@ -133,9 +133,28 @@ class RosterWindow(Adw.ApplicationWindow): """Setup custom CSS for UI styling.""" css_provider = Gtk.CssProvider() css_provider.load_from_data(b""" - /* Constrain tab bar to normal header height */ - .tabbar-box { + /* Reduce header bar padding and height */ + headerbar { + min-height: 38px; + padding-left: 0px; + padding-right: 6px; + } + + /* Compact tab bar */ + tabbar { min-height: 0; + padding: 0; + margin: 0; + } + + tabbar > scrolledwindow { + min-height: 0; + } + + tabbar tab { + min-height: 26px; + padding: 2px 8px; + margin: 0 1px; } /* Stack switchers styling (Headers/Body tabs) */ @@ -181,8 +200,9 @@ class RosterWindow(Adw.ApplicationWindow): tab = self.page_to_tab.get(page) widget = self.page_to_widget.get(page) + # If already removed, allow close (prevents double-processing) if not tab or not widget: - return True # Allow close + return False # Allow close # Check if tab has unsaved changes if widget.modified: @@ -198,10 +218,16 @@ class RosterWindow(Adw.ApplicationWindow): def on_response(dlg, response): if response == "close": - # Remove from our tracking + # Remove from our tracking FIRST to prevent re-triggering self.tab_manager.close_tab(tab.id) del self.page_to_tab[page] del self.page_to_widget[page] + + # Check if we need to create a new tab + if self.tab_view.get_n_pages() == 1: # This page is still counted + # Schedule creating new tab BEFORE closing this one + GLib.idle_add(self._create_new_tab) + # Close the page tab_view.close_page_finish(page, True) else: @@ -217,7 +243,7 @@ class RosterWindow(Adw.ApplicationWindow): del self.page_to_tab[page] del self.page_to_widget[page] - # If no tabs left, create a new one + # If this will be the last tab, create a new one BEFORE returning if self.tab_view.get_n_pages() == 1: # This page is still counted GLib.idle_add(self._create_new_tab) @@ -692,22 +718,38 @@ class RosterWindow(Adw.ApplicationWindow): def _mark_tab_as_saved(self, saved_request_id, name, request): """Mark the current tab as saved (clear modified flag).""" - if self.current_tab_id: - current_tab = self.tab_manager.get_tab_by_id(self.current_tab_id) - if current_tab: - # Update tab metadata - current_tab.saved_request_id = saved_request_id - current_tab.name = name - current_tab.modified = False + page = self.tab_view.get_selected_page() + if not page: + return - # Update original_request to match saved state - current_tab.original_request = HttpRequest( - method=request.method, - url=request.url, - headers=request.headers.copy(), - body=request.body, - syntax=request.syntax - ) + tab = self.page_to_tab.get(page) + widget = self.page_to_widget.get(page) + + if tab and widget: + # Update tab metadata + tab.saved_request_id = saved_request_id + tab.name = name + tab.modified = False + + # Update original_request to match saved state + original = HttpRequest( + method=request.method, + url=request.url, + headers=request.headers.copy(), + body=request.body, + syntax=request.syntax + ) + tab.original_request = original + + # Update widget state + widget.original_request = original + widget.modified = False + + # Update tab page title + page.set_title(name) + + # This will trigger the modified-changed signal and clear the indicator + self._on_tab_modified_changed(page, False) def _show_overwrite_dialog(self, project, name, existing_request_id, request): """Show dialog asking if user wants to overwrite existing request."""