-- Leo's gemini proxy
-- Connecting to typed-hole.org:1965...
-- Connected
-- Sending request
-- Meta line: 20 text/gemini
commit 79c1ee3df272f463cbf56bde730c493dd721733e
Author: Julien Blanchard <julien@sideburns.eu>
Date: Mon Dec 23 18:16:42 2019 +0100
Add bookmarks
diff --git a/.gitignore b/.gitignore
index 53eaa21..35be495 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/target
**/*.rs.bk
+/src/castor.glade~
diff --git a/Cargo.toml b/Cargo.toml
index d07e2e4..9d15c9f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,4 +24,4 @@ lazy_static = "*"
[dependencies.gtk]
version = "0.8.0"
-features = ["v3_16"]
\ No newline at end of file
+features = ["v3_22"]
\ No newline at end of file
diff --git a/src/bookmarks.rs b/src/bookmarks.rs
new file mode 100644
index 0000000..0515e27
--- /dev/null
+++ b/src/bookmarks.rs
@@ -0,0 +1,34 @@
+extern crate dirs;
+use std::fs::File;
+use std::fs::OpenOptions;
+use std::io::{Read, Write};
+
+
+pub fn add(url: &str) {
+ let mut file = bookmarks_file();
+ let entry = format!("=> {}\n", url);
+ file.write_all(entry.as_bytes())
+ .expect("Unable to write file");
+}
+
+pub fn content() -> String {
+ let mut file = bookmarks_file();
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("Unable to read file");
+
+ content
+}
+
+fn bookmarks_file() -> File {
+ let mut bookmarks = dirs::data_local_dir().unwrap();
+ bookmarks.push("castor_bookmarks");
+ let file_path = bookmarks.into_os_string();
+
+ OpenOptions::new()
+ .create(true)
+ .append(true)
+ .read(true)
+ .open(file_path)
+ .expect("file not found")
+}
diff --git a/src/castor.glade b/src/castor.glade
index e1ef420..fd58cea 100644
--- a/src/castor.glade
+++ b/src/castor.glade
@@ -4,6 +4,23 @@
<requires lib="gtk+" version="3.16"/>
<object class="GtkTextBuffer"/>
<object class="GtkTextBuffer"/>
+ <object class="GtkImage" id="image1">
+ <property name="name">add_bookmark</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-add</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Show Bookmarks</property>
+ <property name="stock">gtk-justify-fill</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-go-back</property>
+ </object>
<object class="GtkApplicationWindow" id="window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Castor - Gemini Browser</property>
@@ -25,11 +42,12 @@
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="back_button">
- <property name="label" translatable="yes">Back</property>
<property name="name">back_button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go back</property>
+ <property name="image">image3</property>
<property name="always_show_image">True</property>
</object>
<packing>
@@ -40,12 +58,13 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="forward_button">
- <property name="label" translatable="yes">Bookmarks</property>
- <property name="name">forward_button</property>
+ <object class="GtkButton" id="add_bookmark_button">
+ <property name="name">add_bookmark_button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Add to Bookmarks</property>
+ <property name="image">image1</property>
<property name="always_show_image">True</property>
</object>
<packing>
@@ -56,6 +75,21 @@
</packing>
</child>
<child>
+ <object class="GtkButton" id="show_bookmarks_button">
+ <property name="name">show_bookmarks_button</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Show Bookmarks</property>
+ <property name="image">image2</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkEntry" id="url_bar">
<property name="name">url_bar</property>
<property name="visible">True</property>
@@ -67,7 +101,7 @@
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">1</property>
- <property name="position">2</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
diff --git a/src/gui.rs b/src/gui.rs
index bbda792..8ae2f17 100644
--- a/src/gui.rs
+++ b/src/gui.rs
@@ -7,6 +7,8 @@ pub struct Gui {
url_bar: Entry,
content_view: TextView,
back_button: Button,
+ add_bookmark_button: Button,
+ show_bookmarks_button: Button,
}
impl Gui {
@@ -20,38 +22,26 @@ impl Gui {
let url_bar: Entry = builder.get_object("url_bar").expect("Couldn't get url_bar");
let content_view: TextView = builder.get_object("content_view").expect("Couldn't get content_view");
let back_button: Button = builder.get_object("back_button").expect("Couldn't get back_button");
+ let add_bookmark_button: Button = builder.get_object("add_bookmark_button").expect("Couldn't get add_bookmark_button");
+ let show_bookmarks_button: Button = builder.get_object("show_bookmarks_button").expect("Couldn't get show_bookmarks_button");
Gui {
window,
url_bar,
content_view,
back_button,
+ add_bookmark_button,
+ show_bookmarks_button,
}
}
- // Set up naming for the window and show it to the user.
pub fn start(&self) {
- glib::set_application_name("Castor");
- self.window.set_wmclass("Castor", "Castor");
+ glib::set_application_name("Castor - Gemini Browser");
+ self.window.set_role("Castor - Gemini Browser");
self.window.connect_delete_event(|_, _| { gtk::main_quit(); Inhibit(false) });
self.window.show_all();
}
- // pub fn update_from(&self, state: &State) {
- // if let Some(ref err) = state.error {
- // self.error_label.set_text(
- // &format!("The dice expression entered is not valid:\n{}", err)
- // );
- // self.popover.show_all();
- // } else {
- // // The popover will hide itself anyway when the user clicks
- // // outside of it, but we shouldn't leave an error indicator in it.
- // self.error_label.set_text("");
- // }
-
- // self.result.set_text(&format!("{}", state.value));
- // }
-
pub fn window(&self) -> &ApplicationWindow {
&self.window
}
@@ -67,4 +57,12 @@ impl Gui {
pub fn back_button(&self) -> &Button {
&self.back_button
}
+
+ pub fn add_bookmark_button(&self) -> &Button {
+ &self.add_bookmark_button
+ }
+
+ pub fn show_bookmarks_button(&self) -> &Button {
+ &self.show_bookmarks_button
+ }
}
diff --git a/src/main.rs b/src/main.rs
index 1b51095..2dde5b5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -16,6 +16,7 @@ use url::{Position, Url};
mod gui;
use gui::Gui;
mod absolute;
+mod bookmarks;
mod content;
mod history;
mod link;
@@ -43,6 +44,24 @@ fn main() {
});
}
+ // Bind add_bookmark button
+ {
+ let button = gui.add_bookmark_button();
+ let gui = gui.clone();
+ button.connect_clicked(move |_| {
+ add_bookmark(&gui);
+ });
+ }
+
+ // Bind show_bookmarks button
+ {
+ let button = gui.show_bookmarks_button();
+ let gui = gui.clone();
+ button.connect_clicked(move |_| {
+ show_bookmarks(&gui);
+ });
+ }
+
// Bind URL bar
{
let gui_clone = gui.clone();
@@ -78,10 +97,37 @@ fn update_url_field(gui: &Arc<Gui>, url: &str) {
url_bar.get_buffer().set_text(url);
}
+fn add_bookmark(gui: &Arc<Gui>) {
+ let current_url = history::get_current_url();
+ if let Some(url) = current_url {
+ bookmarks::add(&url);
+ info_dialog(&gui, "Bookmark added.");
+ }
+}
+
+fn show_bookmarks(gui: &Arc<Gui>) {
+ let content_view = gui.content_view();
+
+ let bookmarks_list = format!("# Bookmarks\n\n{}", bookmarks::content());
+ let parsed_content = parser::parse(bookmarks_list);
+
+ clear_buffer(&content_view);
+ draw_content(&gui, parsed_content);
+
+ update_url_field(&gui, "::bookmarks");
+
+ content_view.show_all();
+}
+
fn visit_url(gui: &Arc<Gui>, url: String) {
{
let content_view = gui.content_view();
+ if url == String::from("gemini://::bookmarks") {
+ show_bookmarks(&gui);
+ return
+ }
+
match absolute::make(url.as_str()) {
Ok(url) => match content::get_data(&url) {
Ok((meta, new_content)) => {
@@ -272,6 +318,23 @@ fn insert_external_button(gui: &Arc<Gui>, url: Url, label: &str) {
buffer.insert(&mut end_iter, "\n");
}
+fn info_dialog(gui: &Arc<Gui>, message: &str) {
+ let dialog = gtk::Dialog::new_with_buttons(
+ Some("Info"),
+ Some(gui.window()),
+ gtk::DialogFlags::MODAL,
+ &[("Close", ResponseType::Close)],
+ );
+ dialog.set_default_response(ResponseType::Close);
+ dialog.connect_response(|dialog, _| dialog.destroy());
+
+ let content_area = dialog.get_content_area();
+ let message = gtk::Label::new(Some(message));
+ content_area.add(&message);
+
+ dialog.show_all();
+}
+
fn error_dialog(gui: &Arc<Gui>, message: &str) {
let dialog = gtk::Dialog::new_with_buttons(
Some("Error"),
---
Served by Pollux Gemini Server.
-- Response ended
-- Page fetched on Sun May 19 07:23:28 2024