ui: overhaul sidebar, add content filters and state improvements
Sidebar layout: - Replace AdwNavigationSplitView with GtkPaned for a resizable sidebar with a persistent width stored in GSettings. - Apply navigation-sidebar CSS class to the content Stack only (not the ToolbarView) so both header bars share the same colour and height. - Override Adwaita's automatic paned-first-child header tint and gap via application-level CSS. - Remove the gap between the sidebar header and the first list item. - Add toggle-sidebar button and F9 shortcut; sidebar visibility and width are persisted across restarts. Loading indicator: - Replace the large AdwSpinner status page + header Stack with a small Gtk.Spinner (16×16) in the header Stack so the header height never changes during loading. Article row: - Add hexpand to title and excerpt labels so text reflows when the sidebar is resized. Content: - Inline CSS into the HTML template at load time (/*INJECT_CSS*/ placeholder) so WebKit does not need a custom URI scheme handler. - Fix max-width centering and padding for article body and header. - Fix embedded video/iframe auto-opening in browser by checking NavigationType::LinkClicked instead of is_user_gesture(). Content filters: - Add Preferences dialog with a TextView for content-rewrite rules stored in GSettings (content-filters key). - Rule format: "domain find replace [find replace …]" one per line. - Rules are applied to article HTML before display and reloaded on every refresh. Shortcuts: - Add Ctrl+W to close, Ctrl+Q to quit, F1 for keyboard shortcuts overlay, j/k and arrow-key navigation via a capture-phase controller so keys work regardless of which widget has focus. Misc: - Set window title to "FeedTheMonkey" (fixes Hyprland title bar). - Update About dialog website URL.
This commit is contained in:
parent
141f9ee32d
commit
8fd52dd8a0
16 changed files with 680 additions and 320 deletions
|
|
@ -7,121 +7,140 @@ template $FeedTheMonkeyWindow : Adw.ApplicationWindow {
|
|||
default-height: 600;
|
||||
|
||||
Adw.ToastOverlay toast_overlay {
|
||||
Adw.NavigationSplitView split_view {
|
||||
sidebar: Adw.NavigationPage {
|
||||
title: _("FeedTheMonkey");
|
||||
Paned paned {
|
||||
focusable: false;
|
||||
shrink-start-child: false;
|
||||
resize-start-child: false;
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
Stack refresh_stack {
|
||||
StackPage {
|
||||
name: "button";
|
||||
child: Button refresh_button {
|
||||
icon-name: "view-refresh-symbolic";
|
||||
tooltip-text: _("Refresh");
|
||||
action-name: "win.reload";
|
||||
};
|
||||
}
|
||||
start-child: Adw.ToolbarView sidebar_toolbar {
|
||||
top-bar-style: raised;
|
||||
|
||||
StackPage {
|
||||
name: "spinner";
|
||||
child: Adw.Spinner {};
|
||||
}
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
show-start-title-buttons: false;
|
||||
show-end-title-buttons: false;
|
||||
|
||||
title-widget: Box {};
|
||||
|
||||
[start]
|
||||
Stack refresh_stack {
|
||||
StackPage {
|
||||
name: "button";
|
||||
child: Button refresh_button {
|
||||
icon-name: "view-refresh-symbolic";
|
||||
tooltip-text: _("Refresh");
|
||||
action-name: "win.reload";
|
||||
};
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton menu_button {
|
||||
icon-name: "open-menu-symbolic";
|
||||
primary: true;
|
||||
menu-model: primary_menu;
|
||||
StackPage {
|
||||
name: "spinner";
|
||||
child: Spinner {
|
||||
spinning: true;
|
||||
width-request: 16;
|
||||
height-request: 16;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Stack sidebar_content {
|
||||
StackPage {
|
||||
name: "placeholder";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("FeedTheMonkey");
|
||||
description: _("Log in to load your articles");
|
||||
};
|
||||
}
|
||||
[end]
|
||||
MenuButton menu_button {
|
||||
icon-name: "open-menu-symbolic";
|
||||
primary: true;
|
||||
menu-model: primary_menu;
|
||||
}
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "loading";
|
||||
child: Adw.StatusPage {
|
||||
paintable: Adw.SpinnerPaintable {};
|
||||
title: _("Loading…");
|
||||
};
|
||||
}
|
||||
Stack sidebar_content {
|
||||
styles ["sidebar-content"]
|
||||
|
||||
StackPage {
|
||||
name: "empty";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("No Unread Articles");
|
||||
};
|
||||
}
|
||||
StackPage {
|
||||
name: "placeholder";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("FeedTheMonkey");
|
||||
description: _("Log in to load your articles");
|
||||
};
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "error";
|
||||
child: Adw.StatusPage error_status {
|
||||
icon-name: "network-error-symbolic";
|
||||
title: _("Could Not Load Articles");
|
||||
StackPage {
|
||||
name: "loading";
|
||||
child: Adw.StatusPage {
|
||||
title: _("Loading…");
|
||||
};
|
||||
}
|
||||
|
||||
Button {
|
||||
label: _("Try Again");
|
||||
halign: center;
|
||||
action-name: "win.reload";
|
||||
styles ["pill", "suggested-action"]
|
||||
}
|
||||
};
|
||||
}
|
||||
StackPage {
|
||||
name: "empty";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("No Unread Articles");
|
||||
};
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "list";
|
||||
child: ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
ListView article_list_view {
|
||||
single-click-activate: true;
|
||||
}
|
||||
};
|
||||
}
|
||||
StackPage {
|
||||
name: "error";
|
||||
child: Adw.StatusPage error_status {
|
||||
icon-name: "network-error-symbolic";
|
||||
title: _("Could Not Load Articles");
|
||||
|
||||
Button {
|
||||
label: _("Try Again");
|
||||
halign: center;
|
||||
action-name: "win.reload";
|
||||
styles ["pill", "suggested-action"]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "list";
|
||||
child: ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
ListView article_list_view {
|
||||
single-click-activate: false;
|
||||
show-separators: true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
content: Adw.NavigationPage content_page {
|
||||
title: _("FeedTheMonkey");
|
||||
end-child: Adw.ToolbarView {
|
||||
top-bar-style: raised;
|
||||
|
||||
Adw.ToolbarView {
|
||||
top-bar-style: raised;
|
||||
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[end]
|
||||
MenuButton article_menu_button {
|
||||
icon-name: "view-more-symbolic";
|
||||
menu-model: article_menu;
|
||||
visible: false;
|
||||
}
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
Button toggle_sidebar_button {
|
||||
icon-name: "sidebar-show-symbolic";
|
||||
tooltip-text: _("Toggle Sidebar");
|
||||
action-name: "win.toggle-sidebar";
|
||||
}
|
||||
|
||||
Stack content_stack {
|
||||
StackPage {
|
||||
name: "empty";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "document-open-symbolic";
|
||||
title: _("No Article Selected");
|
||||
};
|
||||
}
|
||||
title-widget: Adw.WindowTitle {
|
||||
title: _("FeedTheMonkey");
|
||||
};
|
||||
|
||||
StackPage {
|
||||
name: "webview";
|
||||
child: WebKit.WebView web_view {};
|
||||
}
|
||||
[end]
|
||||
MenuButton article_menu_button {
|
||||
icon-name: "view-more-symbolic";
|
||||
menu-model: article_menu;
|
||||
visible: false;
|
||||
}
|
||||
}
|
||||
|
||||
Stack content_stack {
|
||||
StackPage {
|
||||
name: "empty";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "document-open-symbolic";
|
||||
title: _("No Article Selected");
|
||||
};
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "webview";
|
||||
child: WebKit.WebView web_view {};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -137,6 +156,13 @@ menu primary_menu {
|
|||
}
|
||||
}
|
||||
|
||||
section {
|
||||
item {
|
||||
label: _("Preferences");
|
||||
action: "win.preferences";
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
item {
|
||||
label: _("Keyboard Shortcuts");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue