From 70e03508cf1844227b5fe16ecc9ed61a441784c6 Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Sat, 10 Feb 2024 20:49:19 +0100
Subject: [PATCH 01/10] feat: implement bookmarks list window - add
`library-symbolic` to icons
---
data/resources/icons/library-symbolic.svg | 2 +
data/resources/meson.build | 1 +
data/resources/resources.gresource.xml | 5 +
data/resources/ui/bookmarks.blp | 68 ++++++++++++
src/widgets/bookmarks.rs | 129 ++++++++++++++++++++++
src/widgets/mod.rs | 1 +
6 files changed, 206 insertions(+)
create mode 100644 data/resources/icons/library-symbolic.svg
create mode 100644 data/resources/ui/bookmarks.blp
create mode 100644 src/widgets/bookmarks.rs
diff --git a/data/resources/icons/library-symbolic.svg b/data/resources/icons/library-symbolic.svg
new file mode 100644
index 0000000..4fdb7f8
--- /dev/null
+++ b/data/resources/icons/library-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/data/resources/meson.build b/data/resources/meson.build
index f13646b..03f009a 100644
--- a/data/resources/meson.build
+++ b/data/resources/meson.build
@@ -1,5 +1,6 @@
blueprints = custom_target('blueprints',
input: files(
+ 'ui/bookmarks.blp',
'ui/window.blp',
'ui/shortcuts.blp',
'ui/input_page.blp',
diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index 778c73a..d935220 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -3,9 +3,14 @@
ui/shortcuts.ui
+ ui/bookmarks.ui
ui/window.ui
ui/input_page.ui
ui/download_page.ui
ui/tab.ui
+
+
+ icons/library-symbolic.svg
+
diff --git a/data/resources/ui/bookmarks.blp b/data/resources/ui/bookmarks.blp
new file mode 100644
index 0000000..5da5dcf
--- /dev/null
+++ b/data/resources/ui/bookmarks.blp
@@ -0,0 +1,68 @@
+using Gtk 4.0;
+using Adw 1;
+
+template $GeopardBookmarksWindow : Adw.Window {
+ title: _("Bookmarks");
+ default-height: 400;
+ default-width: 500;
+ height-request: 290;
+ width-request: 360;
+ modal: true;
+
+ Adw.ToastOverlay toast_overlay {
+ Adw.ToolbarView {
+ [top]
+ Adw.HeaderBar {
+
+ [end]
+ Gtk.Button {
+ icon-name: "selection-mode-symbolic";
+ tooltip-text: _("Select Items");
+ }
+ }
+
+ content: Gtk.Stack stack {
+ transition-type: crossfade;
+
+ Gtk.StackPage {
+ name: "no_bookmarks_page";
+
+ child: Adw.StatusPage {
+ icon-name: "starred-symbolic";
+ title: _("No Bookmarks");
+ description: _("Bookmarked sites will appear here");
+ };
+ }
+
+ Gtk.StackPage {
+ name: "bookmarks_page";
+
+ child: Gtk.ScrolledWindow {
+ child: Gtk.Box {
+ orientation: vertical;
+ margin-top: 6;
+ margin-bottom: 6;
+ margin-start: 6;
+ margin-end: 6;
+ hexpand: true;
+ vexpand: true;
+
+ Adw.Clamp {
+ maximum-size: 1024;
+
+ child: Gtk.ListBox bookmarks_list {
+ activate-on-single-click: true;
+ selection-mode: none;
+
+ styles [
+ "boxed-list"
+ ]
+ };
+ }
+ };
+ };
+ }
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/widgets/bookmarks.rs b/src/widgets/bookmarks.rs
new file mode 100644
index 0000000..df26dc3
--- /dev/null
+++ b/src/widgets/bookmarks.rs
@@ -0,0 +1,129 @@
+use std::sync::OnceLock;
+
+use adw::prelude::*;
+use adw::subclass::prelude::*;
+
+use glib::subclass::{InitializingObject, Signal};
+use gtk::{
+ glib::{self, clone, Object},
+ CompositeTemplate,
+};
+
+pub mod imp {
+ use super::*;
+
+ #[derive(CompositeTemplate, Default)]
+ #[template(resource = "/com/ranfdev/Geopard/ui/bookmarks.ui")]
+ pub struct BookmarksWindow {
+ #[template_child]
+ pub toast_overlay: TemplateChild,
+ #[template_child]
+ pub stack: TemplateChild,
+ #[template_child]
+ pub bookmarks_list: TemplateChild,
+ }
+
+ #[glib::object_subclass]
+ impl ObjectSubclass for BookmarksWindow {
+ const NAME: &'static str = "GeopardBookmarksWindow";
+ type Type = super::BookmarksWindow;
+ type ParentType = adw::Window;
+
+ fn class_init(klass: &mut Self::Class) {
+ klass.bind_template();
+ }
+
+ fn instance_init(obj: &InitializingObject) {
+ obj.init_template();
+ }
+ }
+ impl ObjectImpl for BookmarksWindow {
+ fn signals() -> &'static [Signal] {
+ static SIGNALS: OnceLock> = OnceLock::new();
+ SIGNALS.get_or_init(|| {
+ vec![Signal::builder("open-bookmark-url")
+ .param_types([str::static_type()])
+ .build()]
+ })
+ }
+
+ fn constructed(&self) {
+ self.parent_constructed();
+ }
+ }
+ impl WidgetImpl for BookmarksWindow {}
+ impl WindowImpl for BookmarksWindow {}
+ impl AdwWindowImpl for BookmarksWindow {}
+}
+
+glib::wrapper! {
+ pub struct BookmarksWindow(ObjectSubclass)
+ @extends adw::Window, gtk::Window, gtk::Widget;
+}
+
+impl BookmarksWindow {
+ pub fn new(app: >k::Application) -> Self {
+ let this = Object::builder::()
+ .property("application", app)
+ .build();
+
+ this.setup();
+
+ this
+ }
+
+ fn setup(&self) {
+ let imp = self.imp();
+ // TODO: Set to bookmarks_page if there's at least one bookmark
+ imp.stack.set_visible_child_name("bookmarks_page");
+
+ for i in 0..10 {
+ self.add_row(
+ &format!("Bookmark {i}"),
+ &format!("gemini://geminispace.info/search?geopard"),
+ );
+ }
+ }
+
+ // TODO: create_new_row -> adw::ActionRow
+ fn add_row(&self, title: &str, url: &str) {
+ let imp = self.imp();
+ let title = title.to_string();
+ let url = url.to_string();
+
+ let check_button = gtk::CheckButton::builder()
+ .visible(false)
+ .css_classes(vec!["selection-mode"])
+ .valign(gtk::Align::Center)
+ .build();
+
+ let copy_button = gtk::Button::builder()
+ .icon_name("edit-copy-symbolic")
+ .css_classes(vec!["flat"])
+ .valign(gtk::Align::Center)
+ .build();
+
+ copy_button.connect_clicked(clone!(@weak imp => move |_| {
+ imp.toast_overlay.add_toast(adw::Toast::new("Copied to clipboard"));
+ }));
+
+ let row = adw::ActionRow::builder()
+ .activatable(true)
+ .title(&title)
+ .subtitle(&url)
+ .build();
+ row.add_prefix(&check_button);
+ row.add_suffix(©_button);
+
+ row.connect_activated(clone!(@weak self as this => move |_| {
+ this.on_row_activated(&url);
+ }));
+
+ imp.bookmarks_list.append(&row);
+ }
+
+ fn on_row_activated(&self, url: &str) {
+ let imp = self.imp().obj();
+ imp.emit_by_name::<()>("open-bookmark-url", &[&url]);
+ }
+}
diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs
index 03a0952..a9ce3b7 100644
--- a/src/widgets/mod.rs
+++ b/src/widgets/mod.rs
@@ -1,3 +1,4 @@
+mod bookmarks;
mod pages;
#[allow(clippy::await_holding_refcell_ref)]
mod tab;
From 35d0bcebc23e2f5f61d3e4dd37e697f0aeab2adb Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Sat, 10 Feb 2024 20:54:20 +0100
Subject: [PATCH 02/10] feat: add action for showing bookmarks window and add
`Bookmarks` button - modify `open_in_new_tab` to allow automatically
switching to opened tab - update `open-in-new-tab` signal in signals
vector (hypertext.rs)
---
data/resources/ui/window.blp | 15 +++++++++++++++
src/widgets/pages/hypertext.rs | 5 ++++-
src/widgets/window.rs | 33 +++++++++++++++++++++++++++++----
3 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/data/resources/ui/window.blp b/data/resources/ui/window.blp
index 8cb805a..b1f2b4e 100644
--- a/data/resources/ui/window.blp
+++ b/data/resources/ui/window.blp
@@ -82,6 +82,13 @@ template $GeopardWindow: Adw.ApplicationWindow {
primary: true;
}
+ [end]
+ Gtk.Button bookmarks_button {
+ icon-name: "library-symbolic";
+ action-name: "win.bookmarks";
+ tooltip-text: _("Bookmarks");
+ }
+
[end]
Gtk.Button desktop_tab_overview_btn {
icon-name: "view-grid-symbolic";
@@ -170,6 +177,13 @@ template $GeopardWindow: Adw.ApplicationWindow {
tooltip-text: _("View Open Tabs");
}
+ [end]
+ Gtk.Button {
+ icon-name: "library-symbolic";
+ action-name: "win.bookmarks";
+ tooltip-text: _("Bookmarks");
+ }
+
[end]
Gtk.Button {
icon-name: "system-search-symbolic";
@@ -190,6 +204,7 @@ template $GeopardWindow: Adw.ApplicationWindow {
next_box.visible: false;
refresh_btn.visible: false;
tab_new_btn.visible: false;
+ bookmarks_button.visible: false;
desktop_tab_overview_btn.visible: false;
toolbar_view.reveal-bottom-bars: true;
tab_bar_revealer.reveal-child: false;
diff --git a/src/widgets/pages/hypertext.rs b/src/widgets/pages/hypertext.rs
index 7175542..bfafa46 100644
--- a/src/widgets/pages/hypertext.rs
+++ b/src/widgets/pages/hypertext.rs
@@ -195,7 +195,10 @@ pub mod imp {
.param_types([SignalType::from(glib::types::Type::STRING)])
.build(),
Signal::builder("open-in-new-tab")
- .param_types([SignalType::from(glib::types::Type::STRING)])
+ .param_types([
+ SignalType::from(glib::types::Type::STRING),
+ SignalType::from(glib::types::Type::BOOL),
+ ])
.build(),
Signal::builder("open-background-tab")
.param_types([SignalType::from(glib::types::Type::STRING)])
diff --git a/src/widgets/window.rs b/src/widgets/window.rs
index c6187ac..7af86b5 100644
--- a/src/widgets/window.rs
+++ b/src/widgets/window.rs
@@ -7,7 +7,7 @@ use adw::subclass::application_window::AdwApplicationWindowImpl;
use anyhow::Context;
use config::APP_ID;
use futures::prelude::*;
-use glib::{clone, Properties};
+use glib::{clone, closure_local, Properties};
use gtk::subclass::prelude::*;
use gtk::{gdk, gio, glib, CompositeTemplate, TemplateChild};
use log::{error, info, warn};
@@ -15,6 +15,7 @@ use url::Url;
use crate::common::{bookmarks_url, glibctx, BOOKMARK_FILE_PATH};
use crate::session_provider::SessionProvider;
+use crate::widgets::bookmarks::BookmarksWindow;
use crate::widgets::tab::{HistoryItem, HistoryStatus, Tab};
use crate::{build_config, config, self_action};
@@ -222,6 +223,8 @@ impl Window {
self_action!(self, "close-tab", close_tab);
self_action!(self, "focus-url-bar", focus_url_bar);
self_action!(self, "shortcuts", present_shortcuts);
+ // TODO: Switch later to 'show-bookmarks' action
+ self_action!(self, "bookmarks", present_bookmarks);
self_action!(self, "about", present_about);
self_action!(self, "focus-previous-tab", focus_previous_tab);
self_action!(self, "focus-next-tab", focus_next_tab);
@@ -245,7 +248,7 @@ impl Window {
let act_open_in_new_tab =
gio::SimpleAction::new("open-in-new-tab", Some(glib::VariantTy::STRING));
act_open_in_new_tab.connect_activate(
- clone!(@weak self as this => move |_,v| this.open_in_new_tab(v.unwrap().get::().unwrap().as_str())),
+ clone!(@weak self as this => move |_,v| this.open_in_new_tab(v.unwrap().get::().unwrap().as_str(), false)),
);
self.add_action(&act_open_in_new_tab);
@@ -372,7 +375,7 @@ impl Window {
clone!(@weak self as this => @default-return false, move |_, value, _, _| {
if let Ok(files) = value.get::() {
for f in files.files() {
- this.open_in_new_tab(&format!("file://{}", f.path().unwrap().to_str().unwrap()));
+ this.open_in_new_tab(&format!("file://{}", f.path().unwrap().to_str().unwrap()), false);
}
}
false
@@ -651,9 +654,15 @@ impl Window {
Err(e) => error!("Failed to parse url: {:?}", e),
}
}
- fn open_in_new_tab(&self, v: &str) {
+ fn open_in_new_tab(&self, v: &str, select_page: bool) {
+ let imp = self.imp();
let w = self.add_tab();
let url = Url::parse(v);
+
+ if select_page {
+ imp.tab_view.set_selected_page(&w);
+ }
+
match url {
Ok(url) => self.inner_tab(&w).spawn_open_url(url),
Err(e) => error!("Failed to parse url: {:?}", e),
@@ -722,6 +731,22 @@ impl Window {
fn present_shortcuts(&self) {
gtk::Builder::from_resource("/com/ranfdev/Geopard/ui/shortcuts.ui");
}
+
+ fn present_bookmarks(&self) {
+ let bookmarks = BookmarksWindow::new(&self.application().unwrap());
+ bookmarks.set_transient_for(Some(self));
+
+ bookmarks.connect_closure(
+ "open-bookmark-url",
+ false,
+ closure_local!(@watch self as this => move |_: BookmarksWindow, url: &str| {
+ this.open_in_new_tab(url, true);
+ }),
+ );
+
+ bookmarks.present();
+ }
+
fn present_about(&self) {
let about = adw::AboutWindow::builder()
.application_icon(build_config::APP_ID)
From d46bc1a76b5951c10048df2776006e0a89eae544 Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Thu, 15 Feb 2024 23:32:59 +0100
Subject: [PATCH 03/10] feat: Implement bookmark model structures
---
src/bookmarks.rs | 116 +++++++++++++++++++++++++++++++++++++++++++++++
src/main.rs | 1 +
2 files changed, 117 insertions(+)
create mode 100644 src/bookmarks.rs
diff --git a/src/bookmarks.rs b/src/bookmarks.rs
new file mode 100644
index 0000000..d296ba3
--- /dev/null
+++ b/src/bookmarks.rs
@@ -0,0 +1,116 @@
+use std::path::Path;
+
+use anyhow::{Context, Ok};
+use serde::{Deserialize, Serialize};
+use toml;
+
+#[derive(Clone, Default, Serialize, Deserialize, Debug)]
+pub struct Bookmark {
+ title: String,
+ description: Option,
+ url: String,
+}
+
+#[derive(Clone, Default, Debug)]
+pub struct BookmarkBuilder {
+ title: String,
+ description: Option,
+ url: String,
+}
+
+#[derive(Clone, Default, Serialize, Deserialize, Debug)]
+pub struct Bookmarks {
+ pub bookmarks: Vec,
+}
+
+impl BookmarkBuilder {
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ pub fn title(mut self, title: &str) -> Self {
+ self.title = String::from(title);
+ self
+ }
+
+ pub fn description(mut self, description: Option<&str>) -> Self {
+ match description {
+ Some(desc) => self.description = Some(String::from(desc)),
+ None => self.description = None,
+ }
+ self
+ }
+
+ pub fn url(mut self, url: &str) -> Self {
+ self.url = String::from(url);
+ self
+ }
+
+ pub fn build(self) -> Bookmark {
+ Bookmark {
+ title: self.title,
+ description: self.description,
+ url: self.url,
+ }
+ }
+}
+
+impl Bookmark {
+ pub fn title(&self) -> String {
+ self.title.clone()
+ }
+
+ pub fn set_title(&mut self, title: &str) {
+ self.title = String::from(title);
+ }
+
+ pub fn description(&self) -> Option {
+ self.description.as_ref().cloned()
+ }
+
+ pub fn set_description(&mut self, description: &str) {
+ self.description = Some(String::from(description));
+ }
+
+ pub fn url(&self) -> String {
+ self.url.clone()
+ }
+
+ pub fn set_url(&mut self, url: &str) {
+ self.url = String::from(url);
+ }
+}
+
+impl Bookmarks {
+ pub async fn from_file(&self, path: &Path) -> anyhow::Result {
+ let file_str = async_fs::read_to_string(path)
+ .await
+ .context("Reading bookmarks file")?;
+
+ let bookmarks = toml::from_str(&file_str)?;
+
+ Ok(bookmarks)
+ }
+
+ pub async fn to_file(&self, path: &Path) -> anyhow::Result<()> {
+ let toml = toml::to_string(self)?;
+
+ async_fs::write(path, toml)
+ .await
+ .context("Writting data to bookmarks file")?;
+
+ Ok(())
+ }
+
+ pub fn insert_bookmark(&mut self, bookmark: Bookmark) {
+ self.bookmarks.push(bookmark);
+ }
+
+ pub fn remove_bookmark(&mut self, index: usize) {
+ if self.bookmarks.is_empty() {
+ return;
+ }
+
+ self.bookmarks.remove(index);
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 00f4d30..95e08fc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
#[rustfmt::skip]
mod build_config;
+mod bookmarks;
mod common;
mod config;
mod lossy_text_read;
From 7bcfc0cbb9ada8deb3934f9845d03c07bb0ad25f Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Mon, 19 Feb 2024 23:29:39 +0100
Subject: [PATCH 04/10] feat: add `NEW_BOOKMARK_FILE_PATH` path constant
---
src/common/mod.rs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/common/mod.rs b/src/common/mod.rs
index 51159be..9eb6f38 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -23,15 +23,21 @@ pub static KNOWN_HOSTS_PATH: Lazy =
pub static CONFIG_DIR_PATH: Lazy =
Lazy::new(|| glib::user_config_dir().join("geopard"));
+//todo!(common): Rename this to OLD_BOOKMARK_FILE_PATH
pub static BOOKMARK_FILE_PATH: Lazy =
Lazy::new(|| DATA_DIR_PATH.join("bookmarks.gemini"));
+//todo!(common): Rename this to BOOKMARK_FILE_PATH
+pub static NEW_BOOKMARK_FILE_PATH: Lazy =
+ Lazy::new(|| DATA_DIR_PATH.join("bookmarks.toml"));
+
pub static SETTINGS_FILE_PATH: Lazy =
Lazy::new(|| CONFIG_DIR_PATH.join("config.toml"));
pub static HISTORY_FILE_PATH: Lazy =
Lazy::new(|| DATA_DIR_PATH.join("history.gemini"));
+//todo!(common): Remove this after implementing new format
pub static DEFAULT_BOOKMARKS: &str = r"# Bookmarks
This is a gemini file where you can put all your bookmarks.
@@ -50,6 +56,7 @@ should remove bookmarks.
pub const STREAMABLE_EXTS: [&str; 8] = ["mp3", "mp4", "webm", "opus", "wav", "ogg", "mkv", "flac"];
+//todo!(common): Remove this
pub fn bookmarks_url() -> Url {
Url::parse(&format!("file://{}", BOOKMARK_FILE_PATH.to_str().unwrap())).unwrap()
}
From 17e86ce1eda9bb5aeb6ed7e1bf11cb093b76027d Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Mon, 19 Feb 2024 23:32:58 +0100
Subject: [PATCH 05/10] feat: switch to `BTreeMap` and add `DEFAULT_BOOKMARKS`
constant
---
src/bookmarks.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/src/bookmarks.rs b/src/bookmarks.rs
index d296ba3..bd021bd 100644
--- a/src/bookmarks.rs
+++ b/src/bookmarks.rs
@@ -1,9 +1,42 @@
+use std::collections::BTreeMap;
use std::path::Path;
use anyhow::{Context, Ok};
+use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use toml;
+// todo!(bookmarks): replace bookmarks.bookmarks.insert() with bookmarks.insert_bookmark()
+pub static DEFAULT_BOOKMARKS: Lazy = Lazy::new(|| {
+ let mut bookmarks = Bookmarks::default();
+
+ bookmarks.bookmarks.insert(
+ 1.to_string(),
+ BookmarkBuilder::new()
+ .title("Gemini Project")
+ .url("gemini://geminiprotocol.net")
+ .build(),
+ );
+
+ bookmarks.bookmarks.insert(
+ 2.to_string(),
+ BookmarkBuilder::new()
+ .title("Spacewalk aggregator")
+ .url("gemini://rawtext.club:1965/~sloum/spacewalk.gmi")
+ .build(),
+ );
+
+ bookmarks.bookmarks.insert(
+ 3.to_string(),
+ BookmarkBuilder::new()
+ .title("About geopard + help")
+ .url("about:help")
+ .build(),
+ );
+
+ bookmarks
+});
+
#[derive(Clone, Default, Serialize, Deserialize, Debug)]
pub struct Bookmark {
title: String,
@@ -20,7 +53,8 @@ pub struct BookmarkBuilder {
#[derive(Clone, Default, Serialize, Deserialize, Debug)]
pub struct Bookmarks {
- pub bookmarks: Vec,
+ #[serde(rename = "bookmark")]
+ pub bookmarks: BTreeMap,
}
impl BookmarkBuilder {
@@ -81,6 +115,7 @@ impl Bookmark {
}
}
+//todo!(bookmarks): Add from_gmi() method for migrations
impl Bookmarks {
pub async fn from_file(&self, path: &Path) -> anyhow::Result {
let file_str = async_fs::read_to_string(path)
@@ -102,15 +137,20 @@ impl Bookmarks {
Ok(())
}
+ //todo!(bookmarks): key must be the biggest current key + 1
pub fn insert_bookmark(&mut self, bookmark: Bookmark) {
- self.bookmarks.push(bookmark);
+ self.bookmarks.insert(1.to_string(), bookmark);
+ }
+
+ pub fn update_bookmark(&mut self, key: u32, new_bookmark: Bookmark) {
+ self.bookmarks.insert(key.to_string(), new_bookmark);
}
- pub fn remove_bookmark(&mut self, index: usize) {
+ pub fn remove_bookmark(&mut self, key: u32) {
if self.bookmarks.is_empty() {
return;
}
- self.bookmarks.remove(index);
+ self.bookmarks.remove(&key.to_string());
}
}
From 2bb6fe0ef64fd6073baf5d20f3151756cbf295d3 Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Mon, 19 Feb 2024 23:35:23 +0100
Subject: [PATCH 06/10] feat: implement support for bookmarks in
`BookmarksWindow` - update `BookmarksWindow` UI file
---
data/resources/ui/bookmarks.blp | 13 +++++++++++--
src/widgets/bookmarks.rs | 18 ++++++++++++------
2 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/data/resources/ui/bookmarks.blp b/data/resources/ui/bookmarks.blp
index 5da5dcf..e3473ae 100644
--- a/data/resources/ui/bookmarks.blp
+++ b/data/resources/ui/bookmarks.blp
@@ -13,9 +13,18 @@ template $GeopardBookmarksWindow : Adw.Window {
Adw.ToolbarView {
[top]
Adw.HeaderBar {
+ centering-policy: strict;
[end]
- Gtk.Button {
+ Gtk.ToggleButton search_button {
+ visible: false; // TODO: Remove
+ icon-name: "edit-find-symbolic";
+ tooltip-text: _("Search");
+ }
+
+ [end]
+ Gtk.Button select_items_button {
+ visible: false; // TODO: Remove
icon-name: "selection-mode-symbolic";
tooltip-text: _("Select Items");
}
@@ -65,4 +74,4 @@ template $GeopardBookmarksWindow : Adw.Window {
};
}
}
-}
\ No newline at end of file
+}
diff --git a/src/widgets/bookmarks.rs b/src/widgets/bookmarks.rs
index df26dc3..a598e1b 100644
--- a/src/widgets/bookmarks.rs
+++ b/src/widgets/bookmarks.rs
@@ -1,3 +1,4 @@
+use std::cell::RefCell;
use std::sync::OnceLock;
use adw::prelude::*;
@@ -9,6 +10,8 @@ use gtk::{
CompositeTemplate,
};
+use crate::bookmarks;
+
pub mod imp {
use super::*;
@@ -21,6 +24,7 @@ pub mod imp {
pub stack: TemplateChild,
#[template_child]
pub bookmarks_list: TemplateChild,
+ pub(crate) bookmarks: RefCell,
}
#[glib::object_subclass]
@@ -62,10 +66,12 @@ glib::wrapper! {
}
impl BookmarksWindow {
- pub fn new(app: >k::Application) -> Self {
+ pub fn new(app: >k::Application, bookmarks: bookmarks::Bookmarks) -> Self {
let this = Object::builder::()
.property("application", app)
.build();
+ let imp = this.imp();
+ imp.bookmarks.replace(bookmarks);
this.setup();
@@ -77,11 +83,10 @@ impl BookmarksWindow {
// TODO: Set to bookmarks_page if there's at least one bookmark
imp.stack.set_visible_child_name("bookmarks_page");
- for i in 0..10 {
- self.add_row(
- &format!("Bookmark {i}"),
- &format!("gemini://geminispace.info/search?geopard"),
- );
+ let bookmarks_map = imp.bookmarks.borrow().clone().bookmarks;
+
+ for (_, bookmark) in bookmarks_map.iter() {
+ self.add_row(&bookmark.title(), &bookmark.url());
}
}
@@ -99,6 +104,7 @@ impl BookmarksWindow {
let copy_button = gtk::Button::builder()
.icon_name("edit-copy-symbolic")
+ .tooltip_text("Copy URL")
.css_classes(vec!["flat"])
.valign(gtk::Align::Center)
.build();
From 015c36d33ffd52e78698ce4f6ac5a9962fd72664 Mon Sep 17 00:00:00 2001
From: tfuxu <73042332+tfuxu@users.noreply.github.com>
Date: Mon, 19 Feb 2024 23:38:08 +0100
Subject: [PATCH 07/10] feat: load bookmarks at init and connect structs to
`BookmarksWindow`
---
src/main.rs | 14 ++++++++++++--
src/widgets/window.rs | 14 +++++++++++---
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 95e08fc..9a4d991 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -22,7 +22,7 @@ use log::error;
use crate::common::{
BOOKMARK_FILE_PATH, CONFIG_DIR_PATH, DATA_DIR_PATH, DEFAULT_BOOKMARKS, HISTORY_FILE_PATH,
- SETTINGS_FILE_PATH,
+ NEW_BOOKMARK_FILE_PATH, SETTINGS_FILE_PATH,
};
async fn read_config() -> anyhow::Result {
@@ -30,6 +30,12 @@ async fn read_config() -> anyhow::Result {
.context("Reading config file")
}
+async fn read_bookmarks() -> anyhow::Result {
+ let bookmarks = bookmarks::Bookmarks::default();
+
+ Ok(bookmarks.from_file(&NEW_BOOKMARK_FILE_PATH).await?)
+}
+
async fn create_dir_if_not_exists(path: &std::path::Path) -> anyhow::Result<()> {
if !path.exists() {
async_fs::create_dir_all(path)
@@ -61,9 +67,11 @@ async fn init_file_if_not_exists(
async fn create_base_files() -> anyhow::Result<()> {
let default_config = toml::to_string(&*config::DEFAULT_CONFIG).unwrap();
+ let default_bookmarks = toml::to_string(&*bookmarks::DEFAULT_BOOKMARKS).unwrap();
create_dir_if_not_exists(&DATA_DIR_PATH).await?;
create_dir_if_not_exists(&CONFIG_DIR_PATH).await?;
+ init_file_if_not_exists(&NEW_BOOKMARK_FILE_PATH, Some(default_bookmarks.as_bytes())).await?;
init_file_if_not_exists(&BOOKMARK_FILE_PATH, Some(DEFAULT_BOOKMARKS.as_bytes())).await?;
init_file_if_not_exists(&HISTORY_FILE_PATH, None).await?;
init_file_if_not_exists(&SETTINGS_FILE_PATH, Some(default_config.as_bytes())).await?;
@@ -110,13 +118,15 @@ fn main() {
read_config().await.unwrap()
});
+ let bookmarks = futures::executor::block_on(async { read_bookmarks().await.unwrap() });
+
let windows = Rc::new(RefCell::new(vec![]));
application
.connect_activate(move |app| app.open(&[gio::File::for_uri(bookmarks_url().as_str())], ""));
application.connect_open(move |app, files, _| {
- let window = widgets::Window::new(app, config.clone());
+ let window = widgets::Window::new(app, config.clone(), bookmarks.clone());
window.present();
windows.borrow_mut().push(window.clone());
diff --git a/src/widgets/window.rs b/src/widgets/window.rs
index 0b561a4..43f16f2 100644
--- a/src/widgets/window.rs
+++ b/src/widgets/window.rs
@@ -17,7 +17,7 @@ use crate::common::{bookmarks_url, glibctx, BOOKMARK_FILE_PATH};
use crate::session_provider::SessionProvider;
use crate::widgets::bookmarks::BookmarksWindow;
use crate::widgets::tab::{HistoryItem, HistoryStatus, Tab};
-use crate::{build_config, config, self_action};
+use crate::{bookmarks, build_config, config, self_action};
const ZOOM_CHANGE_FACTOR: f64 = 1.15;
const ZOOM_MAX_FACTOR: f64 = 5.0;
@@ -74,6 +74,7 @@ pub mod imp {
#[template_child]
pub(crate) main_menu_button: TemplateChild,
pub(crate) config: RefCell,
+ pub(crate) bookmarks: RefCell,
pub(crate) progress_animation: RefCell