scaffold: Epic 1 — project scaffold

Add the full Rust + GTK4 + libadwaita project skeleton:
- Cargo.toml with all dependencies (gtk4 0.11, libadwaita 0.9,
  webkit6 0.6, reqwest, serde, tokio, libsecret)
- build.rs that compiles Blueprint .blp files and bundles a GResource
- data/ui/window.blp — AdwApplicationWindow with AdwNavigationSplitView,
  sidebar with refresh button/spinner and primary menu,
  content page with article menu
- data/resources.gresource.xml bundling UI, HTML, and CSS
- data/net.jeena.FeedTheMonkey.gschema.xml with all GSettings keys
- html/content.html and html/content.css (minimal placeholders)
- src/main.rs, src/app.rs — AdwApplication with APP_ID net.jeena.FeedTheMonkey
- src/window.rs — AdwApplicationWindow GObject subclass loading the
  Blueprint template and persisting window size in GSettings
- COPYING (GPL-3.0) restored from master

The app compiles and the binary is ready to open a blank window.
This commit is contained in:
Jeena 2026-03-20 11:22:19 +00:00
parent 3196988c98
commit 3339bb5ec8
15 changed files with 3761 additions and 2 deletions

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id="net.jeena.FeedTheMonkey" path="/net/jeena/FeedTheMonkey/">
<key name="window-width" type="i">
<default>900</default>
<summary>Window width</summary>
</key>
<key name="window-height" type="i">
<default>600</default>
<summary>Window height</summary>
</key>
<key name="window-maximized" type="b">
<default>false</default>
<summary>Window maximized state</summary>
</key>
<key name="sidebar-width" type="i">
<default>280</default>
<summary>Sidebar width in pixels</summary>
</key>
<key name="zoom-level" type="d">
<default>1.0</default>
<summary>WebView zoom level</summary>
</key>
</schema>
</schemalist>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/net/jeena/FeedTheMonkey">
<file preprocess="xml-stripblanks">ui/window.ui</file>
<file>html/content.html</file>
<file>html/content.css</file>
</gresource>
</gresources>

108
data/ui/window.blp Normal file
View file

@ -0,0 +1,108 @@
using Gtk 4.0;
using Adw 1;
template $FeedTheMonkeyWindow : Adw.ApplicationWindow {
default-width: 900;
default-height: 600;
Adw.ToastOverlay toast_overlay {
Adw.NavigationSplitView split_view {
sidebar: Adw.NavigationPage {
title: _("FeedTheMonkey");
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";
};
}
StackPage {
name: "spinner";
child: Adw.Spinner {};
}
}
[end]
MenuButton menu_button {
icon-name: "open-menu-symbolic";
primary: true;
menu-model: primary_menu;
}
}
Adw.StatusPage placeholder_page {
icon-name: "rss-symbolic";
title: _("FeedTheMonkey");
description: _("Log in to load your articles");
}
}
};
content: Adw.NavigationPage content_page {
title: _("FeedTheMonkey");
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;
}
}
Adw.StatusPage {
icon-name: "document-open-symbolic";
title: _("No Article Selected");
}
}
};
}
}
}
menu primary_menu {
section {
item {
label: _("Log Out");
action: "win.logout";
}
}
section {
item {
label: _("Keyboard Shortcuts");
action: "win.show-help-overlay";
}
item {
label: _("About FeedTheMonkey");
action: "app.about";
}
}
}
menu article_menu {
section {
item {
label: _("Mark Unread");
action: "win.mark-unread";
}
item {
label: _("Open in Browser");
action: "win.open-in-browser";
}
}
}

129
data/ui/window.ui Normal file
View file

@ -0,0 +1,129 @@
<?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="FeedTheMonkeyWindow" parent="AdwApplicationWindow">
<property name="default-width">900</property>
<property name="default-height">600</property>
<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>
</child>
<child>
<object class="GtkStackPage">
<property name="name">spinner</property>
<property name="child">
<object class="AdwSpinner"></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="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>
</child>
</object>
</child>
</object>
</property>
<property name="content">
<object class="AdwNavigationPage" id="content_page">
<property name="title" translatable="yes">FeedTheMonkey</property>
<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>
</child>
</object>
</child>
<child>
<object class="AdwStatusPage">
<property name="icon-name">document-open-symbolic</property>
<property name="title" translatable="yes">No Article Selected</property>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">Log Out</attribute>
<attribute name="action">win.logout</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">About FeedTheMonkey</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
<menu id="article_menu">
<section>
<item>
<attribute name="label" translatable="yes">Mark Unread</attribute>
<attribute name="action">win.mark-unread</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Open in Browser</attribute>
<attribute name="action">win.open-in-browser</attribute>
</item>
</section>
</menu>
</interface>