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
|
|
@ -12,166 +12,182 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
|||
<child>
|
||||
<object class="AdwToastOverlay" id="toast_overlay">
|
||||
<child>
|
||||
<object class="AdwNavigationSplitView" id="split_view">
|
||||
<property name="sidebar">
|
||||
<object class="AdwNavigationPage">
|
||||
<property name="title" translatable="yes">FeedTheMonkey</property>
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<child type="start">
|
||||
<object class="GtkStack" id="refresh_stack">
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">button</property>
|
||||
<property name="child">
|
||||
<object class="GtkButton" id="refresh_button">
|
||||
<property name="icon-name">view-refresh-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Refresh</property>
|
||||
<property name="action-name">win.reload</property>
|
||||
</object>
|
||||
</property>
|
||||
<object class="GtkPaned" id="paned">
|
||||
<property name="focusable">false</property>
|
||||
<property name="shrink-start-child">false</property>
|
||||
<property name="resize-start-child">false</property>
|
||||
<property name="start-child">
|
||||
<object class="AdwToolbarView" id="sidebar_toolbar">
|
||||
<property name="top-bar-style">1</property>
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<property name="show-start-title-buttons">false</property>
|
||||
<property name="show-end-title-buttons">false</property>
|
||||
<property name="title-widget">
|
||||
<object class="GtkBox"></object>
|
||||
</property>
|
||||
<child type="start">
|
||||
<object class="GtkStack" id="refresh_stack">
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">button</property>
|
||||
<property name="child">
|
||||
<object class="GtkButton" id="refresh_button">
|
||||
<property name="icon-name">view-refresh-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Refresh</property>
|
||||
<property name="action-name">win.reload</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">spinner</property>
|
||||
<property name="child">
|
||||
<object class="AdwSpinner"></object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="primary">true</property>
|
||||
<property name="menu-model">primary_menu</property>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">spinner</property>
|
||||
<property name="child">
|
||||
<object class="GtkSpinner">
|
||||
<property name="spinning">true</property>
|
||||
<property name="width-request">16</property>
|
||||
<property name="height-request">16</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="primary">true</property>
|
||||
<property name="menu-model">primary_menu</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStack" id="sidebar_content">
|
||||
<style>
|
||||
<class name="sidebar-content"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkStack" id="sidebar_content">
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">placeholder</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">rss-symbolic</property>
|
||||
<property name="title" translatable="yes">FeedTheMonkey</property>
|
||||
<property name="description" translatable="yes">Log in to load your articles</property>
|
||||
</object>
|
||||
</property>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">placeholder</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">rss-symbolic</property>
|
||||
<property name="title" translatable="yes">FeedTheMonkey</property>
|
||||
<property name="description" translatable="yes">Log in to load your articles</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">loading</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="paintable">
|
||||
<object class="AdwSpinnerPaintable"></object>
|
||||
</property>
|
||||
<property name="title" translatable="yes">Loading…</property>
|
||||
</object>
|
||||
</property>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">loading</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="title" translatable="yes">Loading…</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">empty</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">rss-symbolic</property>
|
||||
<property name="title" translatable="yes">No Unread Articles</property>
|
||||
</object>
|
||||
</property>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">empty</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">rss-symbolic</property>
|
||||
<property name="title" translatable="yes">No Unread Articles</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">error</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage" id="error_status">
|
||||
<property name="icon-name">network-error-symbolic</property>
|
||||
<property name="title" translatable="yes">Could Not Load Articles</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Try Again</property>
|
||||
<property name="halign">3</property>
|
||||
<property name="action-name">win.reload</property>
|
||||
<style>
|
||||
<class name="pill"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">error</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage" id="error_status">
|
||||
<property name="icon-name">network-error-symbolic</property>
|
||||
<property name="title" translatable="yes">Could Not Load Articles</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Try Again</property>
|
||||
<property name="halign">3</property>
|
||||
<property name="action-name">win.reload</property>
|
||||
<style>
|
||||
<class name="pill"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</property>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">list</property>
|
||||
<property name="child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">2</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="article_list_view">
|
||||
<property name="single-click-activate">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">list</property>
|
||||
<property name="child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">2</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="article_list_view">
|
||||
<property name="single-click-activate">false</property>
|
||||
<property name="show-separators">true</property>
|
||||
</object>
|
||||
</property>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="content">
|
||||
<object class="AdwNavigationPage" id="content_page">
|
||||
<property name="title" translatable="yes">FeedTheMonkey</property>
|
||||
<property name="end-child">
|
||||
<object class="AdwToolbarView">
|
||||
<property name="top-bar-style">1</property>
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<child type="start">
|
||||
<object class="GtkButton" id="toggle_sidebar_button">
|
||||
<property name="icon-name">sidebar-show-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Toggle Sidebar</property>
|
||||
<property name="action-name">win.toggle-sidebar</property>
|
||||
</object>
|
||||
</child>
|
||||
<property name="title-widget">
|
||||
<object class="AdwWindowTitle">
|
||||
<property name="title" translatable="yes">FeedTheMonkey</property>
|
||||
</object>
|
||||
</property>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="article_menu_button">
|
||||
<property name="icon-name">view-more-symbolic</property>
|
||||
<property name="menu-model">article_menu</property>
|
||||
<property name="visible">false</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<property name="top-bar-style">1</property>
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="article_menu_button">
|
||||
<property name="icon-name">view-more-symbolic</property>
|
||||
<property name="menu-model">article_menu</property>
|
||||
<property name="visible">false</property>
|
||||
<object class="GtkStack" id="content_stack">
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">empty</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
<property name="title" translatable="yes">No Article Selected</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStack" id="content_stack">
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">empty</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
<property name="title" translatable="yes">No Article Selected</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">webview</property>
|
||||
<property name="child">
|
||||
<object class="WebKitWebView" id="web_view"></object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">webview</property>
|
||||
<property name="child">
|
||||
<object class="WebKitWebView" id="web_view"></object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
@ -190,6 +206,12 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
|||
<attribute name="action">win.logout</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Preferences</attribute>
|
||||
<attribute name="action">win.preferences</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Keyboard Shortcuts</attribute>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue