Skip to content

Commit ebb3800

Browse files
author
yggverse
committed
implement separated dialogs for the Bookmarks and History menu items
1 parent e548efc commit ebb3800

14 files changed

Lines changed: 378 additions & 171 deletions

File tree

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ anyhow = "1.0.97"
3434
async-channel = "2.5.0"
3535
ggemini = "0.19.0"
3636
ggemtext = "0.7.0"
37-
indexmap = "2.7.0"
3837
itertools = "0.14.0"
3938
# libspelling = "0.4.0"
4039
maxminddb = "0.26.0"

src/app/browser.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
mod about;
22
mod action;
3+
mod bookmarks;
34
mod database;
5+
mod history;
46
mod proxy;
57
mod widget;
68
pub mod window;
79

810
use about::About;
911
use action::Action;
12+
use bookmarks::Bookmarks;
13+
use history::History;
1014
use proxy::Proxy;
1115
use widget::Widget;
1216
use window::Window;
@@ -93,6 +97,22 @@ impl Browser {
9397
}
9498
});
9599

100+
action.history.connect_activate({
101+
let profile = profile.clone();
102+
let window = window.clone();
103+
move || {
104+
PreferencesDialog::history(&window.action, &profile).present(Some(&window.g_box))
105+
}
106+
});
107+
108+
action.bookmarks.connect_activate({
109+
let profile = profile.clone();
110+
let window = window.clone();
111+
move || {
112+
PreferencesDialog::bookmarks(&window.action, &profile).present(Some(&window.g_box))
113+
}
114+
});
115+
96116
action.proxy.connect_activate({
97117
let profile = profile.clone();
98118
let window = window.clone();

src/app/browser/action.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
mod about;
2+
mod bookmarks;
23
mod close;
34
mod debug;
5+
mod history;
46
mod profile;
57
mod proxy;
68

79
use about::About;
10+
use bookmarks::Bookmarks;
811
use close::Close;
912
use debug::Debug;
13+
use history::History;
1014
use profile::Profile;
1115
use proxy::Proxy;
1216

@@ -21,8 +25,10 @@ use std::rc::Rc;
2125
pub struct Action {
2226
// Actions
2327
pub about: Rc<About>,
28+
pub bookmarks: Rc<Bookmarks>,
2429
pub close: Rc<Close>,
2530
pub debug: Rc<Debug>,
31+
pub history: Rc<History>,
2632
pub profile: Rc<Profile>,
2733
pub proxy: Rc<Proxy>,
2834
// Group
@@ -43,8 +49,10 @@ impl Action {
4349
pub fn new() -> Self {
4450
// Init actions
4551
let about = Rc::new(About::new());
52+
let bookmarks = Rc::new(Bookmarks::new());
4653
let close = Rc::new(Close::new());
4754
let debug = Rc::new(Debug::new());
55+
let history = Rc::new(History::new());
4856
let profile = Rc::new(Profile::new());
4957
let proxy = Rc::new(Proxy::new());
5058

@@ -56,18 +64,22 @@ impl Action {
5664

5765
// Add action to given group
5866
simple_action_group.add_action(&about.simple_action);
67+
simple_action_group.add_action(&bookmarks.simple_action);
5968
simple_action_group.add_action(&close.simple_action);
6069
simple_action_group.add_action(&debug.simple_action);
70+
simple_action_group.add_action(&history.simple_action);
6171
simple_action_group.add_action(&profile.simple_action);
6272
simple_action_group.add_action(&proxy.simple_action);
6373

6474
// Done
6575
Self {
6676
about,
77+
bookmarks,
6778
close,
6879
debug,
6980
profile,
7081
proxy,
82+
history,
7183
id,
7284
simple_action_group,
7385
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use gtk::{gio::SimpleAction, glib::uuid_string_random};
2+
3+
/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Profile` action of `Browser` group
4+
pub struct Bookmarks {
5+
pub simple_action: SimpleAction,
6+
}
7+
8+
impl Default for Bookmarks {
9+
fn default() -> Self {
10+
Self::new()
11+
}
12+
}
13+
14+
impl Bookmarks {
15+
// Constructors
16+
17+
/// Create new `Self`
18+
pub fn new() -> Self {
19+
Self {
20+
simple_action: SimpleAction::new(&uuid_string_random(), None),
21+
}
22+
}
23+
24+
// Events
25+
26+
/// Define callback function for
27+
/// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
28+
pub fn connect_activate(&self, callback: impl Fn() + 'static) {
29+
self.simple_action.connect_activate(move |_, _| callback());
30+
}
31+
}

src/app/browser/action/history.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use gtk::{gio::SimpleAction, glib::uuid_string_random};
2+
3+
/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Profile` action of `Browser` group
4+
pub struct History {
5+
pub simple_action: SimpleAction,
6+
}
7+
8+
impl Default for History {
9+
fn default() -> Self {
10+
Self::new()
11+
}
12+
}
13+
14+
impl History {
15+
// Constructors
16+
17+
/// Create new `Self`
18+
pub fn new() -> Self {
19+
Self {
20+
simple_action: SimpleAction::new(&uuid_string_random(), None),
21+
}
22+
}
23+
24+
// Events
25+
26+
/// Define callback function for
27+
/// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
28+
pub fn connect_activate(&self, callback: impl Fn() + 'static) {
29+
self.simple_action.connect_activate(move |_, _| callback());
30+
}
31+
}

src/app/browser/bookmarks.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//! Browser bookmarks dialog
2+
3+
use super::Profile;
4+
use crate::app::browser::window::action::{Action as WindowAction, Position};
5+
use adw::{
6+
ActionRow, PreferencesGroup, PreferencesPage,
7+
prelude::{
8+
ActionRowExt, AdwDialogExt, ExpanderRowExt, PreferencesDialogExt, PreferencesGroupExt,
9+
PreferencesPageExt,
10+
},
11+
};
12+
use gtk::glib::{DateTime, GString, Uri, UriFlags};
13+
use std::{collections::HashMap, rc::Rc};
14+
15+
struct Record {
16+
time: DateTime,
17+
request: String,
18+
title: Option<String>,
19+
}
20+
21+
pub trait Bookmarks {
22+
fn bookmarks(window_action: &Rc<WindowAction>, profile: &Rc<Profile>) -> Self;
23+
}
24+
25+
impl Bookmarks for adw::PreferencesDialog {
26+
fn bookmarks(window_action: &Rc<WindowAction>, profile: &Rc<Profile>) -> Self {
27+
let mut index: HashMap<GString, Vec<Record>> = HashMap::new();
28+
for bookmark in profile.bookmark.recent(None) {
29+
match Uri::parse(&bookmark.request, UriFlags::NONE) {
30+
Ok(uri) => index
31+
.entry(match uri.host() {
32+
Some(host) => host,
33+
None => uri.to_str(),
34+
})
35+
.or_default()
36+
.push(Record {
37+
request: bookmark.request,
38+
time: bookmark.time,
39+
title: bookmark.title,
40+
}),
41+
Err(_) => continue, // @TODO
42+
}
43+
}
44+
45+
let d = adw::PreferencesDialog::builder()
46+
.search_enabled(true)
47+
.title("Bookmarks")
48+
.build();
49+
50+
d.add(&{
51+
let p = PreferencesPage::builder()
52+
.icon_name("document-open-recent-symbolic")
53+
.title("All")
54+
.build();
55+
56+
for (group, records) in index {
57+
p.add(&{
58+
let g = PreferencesGroup::new();
59+
g.add(&{
60+
let e = adw::ExpanderRow::builder()
61+
.enable_expansion(true)
62+
.expanded(false)
63+
.subtitle(
64+
records
65+
.iter()
66+
.max_by_key(|r| r.time.to_unix())
67+
.unwrap()
68+
.time
69+
.format_iso8601()
70+
.unwrap(),
71+
)
72+
.title_selectable(true)
73+
.title(group)
74+
.build();
75+
76+
for record in records {
77+
e.add_row(&{
78+
let a = ActionRow::builder()
79+
.activatable(true)
80+
// @TODO use button widget to open the links on click
81+
//.title_selectable(true)
82+
.title(match record.title {
83+
Some(title) => title,
84+
None => record.time.format_iso8601().unwrap().to_string(),
85+
})
86+
.subtitle_selectable(true)
87+
.subtitle(&record.request)
88+
.build();
89+
90+
a.connect_activated({
91+
let a = window_action.clone();
92+
let d = d.clone();
93+
move |_| {
94+
a.append.activate_stateful_once(
95+
Position::After,
96+
Some(record.request.clone()),
97+
false,
98+
true,
99+
true,
100+
true,
101+
);
102+
d.close();
103+
}
104+
});
105+
a
106+
})
107+
}
108+
e
109+
});
110+
g
111+
});
112+
}
113+
p
114+
});
115+
d
116+
}
117+
}

0 commit comments

Comments
 (0)