Skip to content

Commit 46b88fc

Browse files
committed
colors, rewritten history, support forward
1 parent 4ca7aba commit 46b88fc

File tree

5 files changed

+195
-111
lines changed

5 files changed

+195
-111
lines changed

src/common/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use futures::prelude::*;
33
use gtk::glib;
44
use once_cell::sync::Lazy;
55
use std::borrow::Cow;
6+
use std::cell::RefCell;
7+
use std::rc::Rc;
68
use url::Url;
79

810
use crate::gemini;
@@ -74,7 +76,7 @@ pub enum PageElement {
7476
#[derive(Debug, Clone, PartialEq)]
7577
pub struct HistoryItem {
7678
pub url: url::Url,
77-
pub cache: Option<Vec<u8>>,
79+
pub cache: Rc<RefCell<Option<Vec<u8>>>>,
7880
pub scroll_progress: f64,
7981
}
8082

src/draw_ctx.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::config;
44
use glib::IsA;
55
use gtk::glib;
66
use gtk::prelude::*;
7-
use log::{debug, info};
87

98
#[derive(Debug, Clone)]
109
pub struct DrawCtx {
@@ -181,7 +180,6 @@ impl DrawCtx {
181180
link: String,
182181
label: Option<&str>,
183182
) {
184-
debug!("Inserting link");
185183
let start = text_iter.offset();
186184
let default_config = &config::DEFAULT_CONFIG;
187185

@@ -205,8 +203,6 @@ impl DrawCtx {
205203
Self::set_linkhandler(&tag, link.clone());
206204

207205
let label = label.unwrap_or(&link);
208-
info!("Setted url {:?} to tag", Self::linkhandler(&tag));
209-
debug!("Link set successfully");
210206
self.insert_paragraph(text_iter, label);
211207
self.insert_paragraph(text_iter, "\n");
212208

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,17 @@ fn main() {
8383
windows.borrow_mut().push(window);
8484
});
8585

86-
application.set_accels_for_action("win.back", &["<Alt>Left"]);
86+
application.set_accels_for_action("win.previous", &["<Alt>Left"]);
87+
application.set_accels_for_action("win.next", &["<Alt>Right"]);
8788
application.set_accels_for_action("win.show-bookmarks", &["<Ctrl>b"]);
8889
application.set_accels_for_action("win.bookmark-current", &["<Ctrl>d"]);
8990
application.set_accels_for_action("win.new-tab", &["<Ctrl>t"]);
9091
application.set_accels_for_action("win.close-tab", &["<Ctrl>w"]);
9192
application.set_accels_for_action("win.focus-url-bar", &["F6"]);
93+
application.set_accels_for_action("win.shortcuts", &["<Ctrl>question"]);
94+
// Sadly Tab doesn't work as an accelerator in gtk...
95+
application.set_accels_for_action("win.focus-next-tab", &["<Ctrl>Tab"]);
96+
application.set_accels_for_action("win.focus-previous-tab", &["<Ctrl><Shift>Tab"]);
9297
// FIXME: win.view-source
9398
let ret = application.run();
9499
std::process::exit(ret);

src/tab.rs

Lines changed: 102 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ use gtk::subclass::prelude::*;
1313
use log::{debug, error, info};
1414
use once_cell::sync::Lazy;
1515
use std::cell::RefCell;
16+
use std::marker::PhantomData;
17+
use std::pin::Pin;
18+
use std::rc::Rc;
1619
use url::Url;
1720

1821
use crate::common;
1922
use crate::common::{glibctx, HistoryItem, LossyTextRead, PageElement, RequestCtx};
2023
use crate::draw_ctx::DrawCtx;
2124
use crate::gemini;
2225

26+
#[derive(Clone, glib::Boxed, Default)]
27+
#[boxed_type(name = "GeopardHistoryStatus")]
28+
pub struct HistoryStatus {
29+
current: usize,
30+
available: usize,
31+
}
2332
pub mod imp {
2433

2534
pub use super::*;
@@ -28,11 +37,14 @@ pub mod imp {
2837
pub(crate) gemini_client: RefCell<gemini::Client>,
2938
pub(crate) draw_ctx: RefCell<Option<DrawCtx>>,
3039
pub(crate) history: RefCell<Vec<HistoryItem>>,
40+
pub(crate) current_hi: RefCell<Option<usize>>,
3141
pub(crate) scroll_win: gtk::ScrolledWindow,
3242
pub(crate) clamp: adw::Clamp,
3343
pub(crate) left_click_ctrl: RefCell<Option<gtk::GestureClick>>,
3444
pub(crate) right_click_ctrl: RefCell<Option<gtk::GestureClick>>,
3545
pub(crate) req_handle: RefCell<Option<RemoteHandle<()>>>,
46+
#[prop(get = Self::history_status, builder(HistoryStatus::static_type()))]
47+
pub(crate) history_status: PhantomData<HistoryStatus>,
3648
#[prop(get, set)]
3749
pub(crate) progress: RefCell<f64>,
3850
#[prop(get)]
@@ -107,6 +119,14 @@ pub mod imp {
107119
self.derived_property(obj, id, pspec).unwrap()
108120
}
109121
}
122+
impl Tab {
123+
fn history_status(&self) -> HistoryStatus {
124+
HistoryStatus {
125+
current: self.current_hi.borrow().unwrap_or(0),
126+
available: self.history.borrow().len(),
127+
}
128+
}
129+
}
110130
impl WidgetImpl for Tab {}
111131
}
112132
glib::wrapper! {
@@ -142,7 +162,7 @@ impl Tab {
142162
let imp = self.imp();
143163
&imp.scroll_win
144164
}
145-
pub fn build_request_ctx(&self, url: Url) -> RequestCtx {
165+
fn build_request_ctx(&self, url: Url) -> RequestCtx {
146166
let imp = self.imp();
147167
RequestCtx {
148168
draw_ctx: imp.draw_ctx.borrow().clone().unwrap(),
@@ -160,12 +180,6 @@ impl Tab {
160180
.url
161181
.clone())
162182
}
163-
pub fn add_cache(&self, cache: Vec<u8>) {
164-
let imp = self.imp();
165-
if let Some(item) = imp.history.borrow_mut().last_mut() {
166-
item.cache = Some(cache)
167-
}
168-
}
169183
pub fn handle_click(&self, x: f64, y: f64) -> Result<()> {
170184
let imp = self.imp();
171185
let draw_ctx = imp.draw_ctx.borrow();
@@ -200,12 +214,41 @@ impl Tab {
200214
text_view.set_extra_menu(Some(&menu));
201215
Ok(())
202216
}
217+
pub fn spawn_open_url(&self, url: Url) {
218+
let i = self.add_to_history(HistoryItem {
219+
url: url.clone(),
220+
cache: Default::default(),
221+
scroll_progress: 0.0,
222+
});
223+
let cache_space = Rc::downgrade(&self.imp().history.borrow()[i].cache);
224+
let this = self.clone();
225+
let fut = async move {
226+
let cache = this.open_url(url).await;
227+
cache_space.upgrade().map(|rc| rc.replace(cache));
228+
};
229+
self.spawn_request(fut);
230+
}
231+
fn add_to_history(&self, item: HistoryItem) -> usize {
232+
let imp = self.imp();
233+
let mut history = imp.history.borrow_mut();
234+
let i = *imp.current_hi.borrow();
235+
if let Some(i) = i {
236+
let scroll_progress = imp.scroll_win.vadjustment().value();
237+
history[i].scroll_progress = scroll_progress;
238+
history.truncate(i + 1);
239+
};
240+
history.push(item);
241+
let i = history.len() - 1;
242+
imp.current_hi.replace(Some(i));
243+
self.log_history_position();
244+
i
245+
}
203246
fn spawn_request(&self, fut: impl Future<Output = ()> + 'static) {
204247
let imp = self.imp();
205248
imp.req_handle
206249
.replace(Some(glibctx().spawn_local_with_handle(fut).unwrap()));
207250
}
208-
pub fn spawn_open_url(&self, url: Url) {
251+
fn open_url(&self, url: Url) -> impl Future<Output = Option<Vec<u8>>> {
209252
let imp = self.imp();
210253

211254
self.set_progress(0.0);
@@ -214,89 +257,95 @@ impl Tab {
214257
*imp.url.borrow_mut() = url.to_string();
215258
self.notify("url");
216259

217-
let scroll_progress = imp.scroll_win.vadjustment().value();
218-
let mut history = imp.history.borrow_mut();
219-
if let Some(item) = history.last_mut() {
220-
item.scroll_progress = scroll_progress;
221-
}
222-
history.push(HistoryItem {
223-
url: url.clone(),
224-
cache: None,
225-
scroll_progress: 0.0,
226-
});
227260
let mut req_ctx = self.build_request_ctx(url.clone());
228261

229262
let this = self.clone();
230263
let fut = async move {
231-
match Self::send_request(&mut req_ctx).await {
264+
let cache = match Self::send_request(&mut req_ctx).await {
232265
Ok(Some(cache)) => {
233-
this.add_cache(cache);
234-
info!("Page loaded and cached ({})", url.clone());
266+
info!("Page loaded, can be cached ({})", url.clone());
267+
Some(cache)
235268
}
236269
Ok(_) => {
237270
info!("Page loaded ({})", url.clone());
271+
None
238272
}
239273
Err(e) => {
240274
Self::display_error(&mut req_ctx.draw_ctx, e);
275+
None
241276
}
242-
}
277+
};
243278
this.set_progress(1.0);
279+
cache
244280
};
245281
self.set_progress(0.3);
246-
self.spawn_request(fut);
282+
fut
247283
}
248-
fn spawn_open_history(&self, item: HistoryItem) {
284+
fn open_history(&self, item: HistoryItem) -> Pin<Box<dyn Future<Output = ()>>> {
249285
let HistoryItem { url, cache, .. } = item;
250-
match cache {
251-
Some(cache) => self.spawn_open_cached(url, cache),
252-
None => self.spawn_open_url(url),
286+
let cache = cache.borrow();
287+
match &*cache {
288+
Some(cache) => Box::pin(self.open_cached(url, cache.clone())),
289+
None => Box::pin(self.open_url(url).map(|_| {})),
253290
}
254291
}
255-
fn spawn_open_cached(&self, url: Url, cache: Vec<u8>) {
292+
fn open_cached(&self, url: Url, cache: Vec<u8>) -> impl Future<Output = ()> {
256293
let imp = self.imp();
257-
imp.history.borrow_mut().push(HistoryItem {
258-
url: url.clone(),
259-
cache: None,
260-
scroll_progress: 0.0,
261-
});
262-
263294
let mut draw_ctx = imp.draw_ctx.borrow().clone().unwrap();
264-
let this = self.clone();
295+
265296
*self.imp().title.borrow_mut() = url.to_string();
266297
self.notify("title");
267298

268299
*self.imp().url.borrow_mut() = url.to_string();
269300
self.notify("url");
270301

271-
let fut = async move {
272-
let buf = BufReader::new(cache.as_slice());
302+
async move {
303+
let buf = BufReader::new(&*cache);
273304
draw_ctx.clear();
274305
let res = Self::display_gemini(&mut draw_ctx, buf).await;
275306
match res {
276-
Ok(cache) => {
307+
Ok(_) => {
277308
info!("Loaded {} from cache", &url);
278-
this.add_cache(cache);
279309
}
280310
Err(e) => Self::display_error(&mut draw_ctx, e),
281311
}
312+
}
313+
}
314+
fn log_history_position(&self) {
315+
let i = self.imp().current_hi.borrow();
316+
info!("history position: {i:?}");
317+
}
318+
pub fn previous(&self) -> Result<()> {
319+
let imp = self.imp();
320+
let i = {
321+
imp.current_hi
322+
.borrow()
323+
.map(|i| i.checked_sub(1))
324+
.flatten()
325+
.context("going back in history")?
282326
};
283-
self.spawn_request(fut);
327+
imp.current_hi.replace(Some(i));
328+
self.log_history_position();
329+
330+
let h = { imp.history.borrow_mut().get(i).cloned() };
331+
h.map(|x| self.spawn_request(self.open_history(x)))
332+
.context("retrieving previous item from history")
284333
}
285-
pub fn back(&self) -> Result<()> {
334+
pub fn next(&self) -> Result<()> {
286335
let imp = self.imp();
287-
let item = {
288-
let mut history = imp.history.borrow_mut();
289-
if history.len() <= 1 {
290-
bail!("Already at last item in history");
291-
}
292-
history.pop();
293-
history.pop()
336+
let i = {
337+
imp.current_hi
338+
.borrow()
339+
.map(|i| i + 1)
340+
.filter(|i| *i < imp.history.borrow().len())
341+
.context("going forward in history")?
294342
};
295-
match item {
296-
Some(item) => self.spawn_open_history(item),
297-
None => unreachable!(),
298-
}
299-
Ok(())
343+
imp.current_hi.replace(Some(i));
344+
self.log_history_position();
345+
346+
let h = { imp.history.borrow_mut().get(i).cloned() };
347+
h.map(|x| self.spawn_request(self.open_history(x)))
348+
.context("retrieving previous item from history")
300349
}
301350
pub fn display_error(ctx: &mut DrawCtx, error: anyhow::Error) {
302351
error!("{:?}", error);

0 commit comments

Comments
 (0)