app: implement Epics 2–10
Add the full application logic on top of the Epic 1 skeleton:
Epic 2 — Authentication
- LoginDialog (AdwDialog, Blueprint template) with server URL,
username, and password fields; emits logged-in signal on submit
- credentials.rs: store/load/clear via libsecret (password_store_sync /
password_search_sync / password_clear_sync, v0_19 feature)
- api.rs: Api::login() parses Auth= token from ClientLogin response;
fetch_write_token() fetches the write token
- Auto-login on startup from stored credentials; logout with
AdwAlertDialog confirmation; login errors shown in AdwAlertDialog
Epic 3 — Article fetching
- model.rs: Article struct and ArticleObject GObject wrapper with
unread property for list store binding
- Api::fetch_unread() deserializes Google Reader JSON, derives unread
from categories, generates plain-text excerpt
- Sidebar uses a GtkStack with placeholder / loading / empty / error /
list pages; AdwSpinnerPaintable while fetching; Try Again button
Epic 4 — Sidebar
- article_row.blp: composite template with feed title, date, title,
and excerpt labels
- ArticleRow GObject subclass; binds ArticleObject, watches unread
notify to apply .dim-label on the title; relative timestamp format
Epic 5 — Content pane
- content.html updated: setArticle(), checkKey(), feedthemonkey: URI
navigation scheme; dark mode via prefers-color-scheme
- content.css: proper article layout, dark mode, code blocks
- WebView loaded from GResource; decide-policy intercepts
feedthemonkey:{next,previous,open} and all external links
Epic 6 — Read state
- Api::mark_read() / mark_unread() via edit-tag endpoint
- Optimistic unread toggle on ArticleObject; background API calls;
mark_unread_guard prevents re-marking on navigation
- AdwToast shown on mark-unread
Epic 7 — Keyboard shortcuts
- GtkShortcutController on window for all shortcuts from the backlog
- shortcuts.blp: AdwShortcutsWindow documenting all shortcuts
- F1 opens shortcuts dialog; Ctrl+W closes window; Ctrl+Q quits
Epic 8 — Zoom
- zoom_in/zoom_out/zoom_reset wired to Ctrl+±/0; zoom level saved to
and restored from GSettings zoom-level key
Epic 9 — Window state persistence
- Window width/height/maximized saved on close, restored on open
- (Sidebar width deferred — AdwNavigationSplitView fraction binding)
Epic 10 — Polish
- AdwAboutDialog with app name, version, GPL-3.0, website
- Logout confirmation AdwAlertDialog with destructive button
- Win.toggle-fullscreen action (F11)
- Api dropped on window close to cancel in-flight requests
This commit is contained in:
parent
8db0b16954
commit
813dda3579
22 changed files with 1838 additions and 42 deletions
42
data/ui/article_row.blp
Normal file
42
data/ui/article_row.blp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $ArticleRow : Gtk.Box {
|
||||
orientation: vertical;
|
||||
margin-top: 12;
|
||||
margin-bottom: 12;
|
||||
margin-start: 12;
|
||||
margin-end: 12;
|
||||
spacing: 4;
|
||||
|
||||
Box {
|
||||
orientation: horizontal;
|
||||
spacing: 4;
|
||||
|
||||
Label feed_title_label {
|
||||
hexpand: true;
|
||||
xalign: 0;
|
||||
ellipsize: end;
|
||||
styles ["dim-label", "caption"]
|
||||
}
|
||||
|
||||
Label date_label {
|
||||
xalign: 1;
|
||||
styles ["dim-label", "caption"]
|
||||
}
|
||||
}
|
||||
|
||||
Label title_label {
|
||||
xalign: 0;
|
||||
wrap: true;
|
||||
lines: 2;
|
||||
ellipsize: end;
|
||||
}
|
||||
|
||||
Label excerpt_label {
|
||||
xalign: 0;
|
||||
ellipsize: end;
|
||||
lines: 1;
|
||||
styles ["dim-label", "caption"]
|
||||
}
|
||||
}
|
||||
62
data/ui/article_row.ui
Normal file
62
data/ui/article_row.ui
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
DO NOT EDIT!
|
||||
This file was @generated by blueprint-compiler. Instead, edit the
|
||||
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
-->
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="ArticleRow" parent="GtkBox">
|
||||
<property name="orientation">1</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">0</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="feed_title_label">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="ellipsize">3</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
<class name="caption"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="date_label">
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
<class name="caption"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title_label">
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">true</property>
|
||||
<property name="lines">2</property>
|
||||
<property name="ellipsize">3</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="excerpt_label">
|
||||
<property name="xalign">0</property>
|
||||
<property name="ellipsize">3</property>
|
||||
<property name="lines">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
<class name="caption"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
41
data/ui/login_dialog.blp
Normal file
41
data/ui/login_dialog.blp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $LoginDialog : Adw.Dialog {
|
||||
title: _("Log In");
|
||||
content-width: 360;
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {}
|
||||
|
||||
Adw.Clamp {
|
||||
margin-top: 12;
|
||||
margin-bottom: 24;
|
||||
margin-start: 12;
|
||||
margin-end: 12;
|
||||
|
||||
Adw.PreferencesGroup {
|
||||
Adw.EntryRow server_url_row {
|
||||
title: _("Server URL");
|
||||
input-hints: no_spellcheck;
|
||||
input-purpose: url;
|
||||
}
|
||||
|
||||
Adw.EntryRow username_row {
|
||||
title: _("Username");
|
||||
input-hints: no_spellcheck;
|
||||
}
|
||||
|
||||
Adw.PasswordEntryRow password_row {
|
||||
title: _("Password");
|
||||
}
|
||||
|
||||
Adw.ButtonRow login_button {
|
||||
title: _("Log In");
|
||||
styles ["suggested-action"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
data/ui/login_dialog.ui
Normal file
58
data/ui/login_dialog.ui
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
DO NOT EDIT!
|
||||
This file was @generated by blueprint-compiler. Instead, edit the
|
||||
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
-->
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="LoginDialog" parent="AdwDialog">
|
||||
<property name="title" translatable="yes">Log In</property>
|
||||
<property name="content-width">360</property>
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar"></object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwClamp">
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-bottom">24</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="server_url_row">
|
||||
<property name="title" translatable="yes">Server URL</property>
|
||||
<property name="input-hints">2</property>
|
||||
<property name="input-purpose">5</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="username_row">
|
||||
<property name="title" translatable="yes">Username</property>
|
||||
<property name="input-hints">2</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPasswordEntryRow" id="password_row">
|
||||
<property name="title" translatable="yes">Password</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwButtonRow" id="login_button">
|
||||
<property name="title" translatable="yes">Log In</property>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
107
data/ui/shortcuts.blp
Normal file
107
data/ui/shortcuts.blp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
ShortcutsWindow help_overlay {
|
||||
modal: true;
|
||||
|
||||
ShortcutsSection {
|
||||
section-name: "shortcuts";
|
||||
max-height: 10;
|
||||
|
||||
ShortcutsGroup {
|
||||
title: _("Navigation");
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Next article");
|
||||
accelerator: "j Right";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Previous article");
|
||||
accelerator: "k Left";
|
||||
}
|
||||
}
|
||||
|
||||
ShortcutsGroup {
|
||||
title: _("Article");
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Open in browser");
|
||||
accelerator: "Return n";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Mark as unread");
|
||||
accelerator: "u";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Reload articles");
|
||||
accelerator: "r";
|
||||
}
|
||||
}
|
||||
|
||||
ShortcutsGroup {
|
||||
title: _("View");
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Scroll down");
|
||||
accelerator: "space Page_Down";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Scroll up");
|
||||
accelerator: "Page_Up";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Scroll to top");
|
||||
accelerator: "Home";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Scroll to bottom");
|
||||
accelerator: "End";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Zoom in");
|
||||
accelerator: "<Control>plus";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Zoom out");
|
||||
accelerator: "<Control>minus";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Reset zoom");
|
||||
accelerator: "<Control>0";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Toggle fullscreen");
|
||||
accelerator: "F11";
|
||||
}
|
||||
}
|
||||
|
||||
ShortcutsGroup {
|
||||
title: _("Application");
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Keyboard shortcuts");
|
||||
accelerator: "F1";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Close window");
|
||||
accelerator: "<Control>w";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: _("Quit");
|
||||
accelerator: "<Control>q";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
134
data/ui/shortcuts.ui
Normal file
134
data/ui/shortcuts.ui
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
DO NOT EDIT!
|
||||
This file was @generated by blueprint-compiler. Instead, edit the
|
||||
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
-->
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="GtkShortcutsWindow" id="help_overlay">
|
||||
<property name="modal">true</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsSection">
|
||||
<property name="section-name">shortcuts</property>
|
||||
<property name="max-height">10</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">Navigation</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Next article</property>
|
||||
<property name="accelerator">j Right</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Previous article</property>
|
||||
<property name="accelerator">k Left</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">Article</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Open in browser</property>
|
||||
<property name="accelerator">Return n</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Mark as unread</property>
|
||||
<property name="accelerator">u</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Reload articles</property>
|
||||
<property name="accelerator">r</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">View</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Scroll down</property>
|
||||
<property name="accelerator">space Page_Down</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Scroll up</property>
|
||||
<property name="accelerator">Page_Up</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Scroll to top</property>
|
||||
<property name="accelerator">Home</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Scroll to bottom</property>
|
||||
<property name="accelerator">End</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Zoom in</property>
|
||||
<property name="accelerator"><Control>plus</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Zoom out</property>
|
||||
<property name="accelerator"><Control>minus</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Reset zoom</property>
|
||||
<property name="accelerator"><Control>0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Toggle fullscreen</property>
|
||||
<property name="accelerator">F11</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">Application</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Keyboard shortcuts</property>
|
||||
<property name="accelerator">F1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Close window</property>
|
||||
<property name="accelerator"><Control>w</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes">Quit</property>
|
||||
<property name="accelerator"><Control>q</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
using WebKit 6.0;
|
||||
|
||||
template $FeedTheMonkeyWindow : Adw.ApplicationWindow {
|
||||
default-width: 900;
|
||||
|
|
@ -38,10 +39,56 @@ template $FeedTheMonkeyWindow : Adw.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
Adw.StatusPage placeholder_page {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("FeedTheMonkey");
|
||||
description: _("Log in to load your articles");
|
||||
Stack sidebar_content {
|
||||
StackPage {
|
||||
name: "placeholder";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("FeedTheMonkey");
|
||||
description: _("Log in to load your articles");
|
||||
};
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "loading";
|
||||
child: Adw.StatusPage {
|
||||
paintable: Adw.SpinnerPaintable {};
|
||||
title: _("Loading…");
|
||||
};
|
||||
}
|
||||
|
||||
StackPage {
|
||||
name: "empty";
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "rss-symbolic";
|
||||
title: _("No Unread Articles");
|
||||
};
|
||||
}
|
||||
|
||||
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: true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -62,9 +109,19 @@ template $FeedTheMonkeyWindow : Adw.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
Adw.StatusPage {
|
||||
icon-name: "document-open-symbolic";
|
||||
title: _("No Article Selected");
|
||||
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 {};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,10 +54,80 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
|||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwStatusPage" id="placeholder_page">
|
||||
<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 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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</object>
|
||||
</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">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
@ -82,9 +152,26 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
|||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
<property name="title" translatable="yes">No Article Selected</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>
|
||||
</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>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue