diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 00000000..a522a5ab --- /dev/null +++ b/src/app.rs @@ -0,0 +1,125 @@ +mod action; +mod browser; + +use action::Action; +use browser::Browser; + +use gtk::{ + glib::{user_config_dir, ExitCode}, + prelude::{ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt}, + Application, +}; + +use std::{fs::create_dir_all, sync::Arc}; + +const APPLICATION_ID: &str = "io.github.yggverse.Yoda"; + +pub struct App { + // GTK + app: Application, + // Components + //browser: Arc, +} + +impl App { + // Construct + pub fn new() -> Self { + // Init profile directory + let mut fs = user_config_dir(); + + fs.push(APPLICATION_ID); + + if let Err(e) = create_dir_all(&fs) { + panic!("Failed to create profile directory: {e}") + } + + // Init profile database + /* @TODO + let mut db = fs.clone(); + + db.push("database.sqlite3"); + + let db = match sqlite::open(db) { + Ok(db) => Arc::new(db), + Err(e) => panic!("Failed to connect profile database: {e}"), + };*/ + + // Init actions + let action_debug = Action::new("win", true); + let action_quit = Action::new("win", true); + let action_update = Action::new("win", true); + let action_tab_append = Action::new("win", true); + let action_tab_close = Action::new("win", true); + let action_tab_close_all = Action::new("win", true); + let action_tab_page_navigation_base = Action::new("win", false); + let action_tab_page_navigation_history_back = Action::new("win", false); + let action_tab_page_navigation_history_forward = Action::new("win", false); + let action_tab_page_navigation_reload = Action::new("win", true); + let action_tab_pin = Action::new("win", true); + + // Init GTK + let app = Application::builder() + .application_id(APPLICATION_ID) + .build(); + + // Init accels + app.set_accels_for_action(&action_debug.detailed_name(), &["i"]); + app.set_accels_for_action(&action_update.detailed_name(), &["u"]); + app.set_accels_for_action(&action_quit.detailed_name(), &["Escape"]); + app.set_accels_for_action(&action_tab_append.detailed_name(), &["t"]); + app.set_accels_for_action(&action_tab_pin.detailed_name(), &["p"]); + app.set_accels_for_action(&action_tab_close.detailed_name(), &["q"]); + app.set_accels_for_action( + &action_tab_page_navigation_base.detailed_name(), + &["h"], + ); + app.set_accels_for_action( + &action_tab_page_navigation_history_back.detailed_name(), + &["Left"], + ); + app.set_accels_for_action( + &action_tab_page_navigation_history_forward.detailed_name(), + &["Right"], + ); + app.set_accels_for_action( + &action_tab_page_navigation_reload.detailed_name(), + &["r"], + ); + + // Init events + app.connect_activate({ + move |application| { + // Init components + let browser = Arc::new(Browser::new( + &application, + /*db.clone(),*/ + action_debug.simple(), + action_quit.simple(), + action_update.simple(), + action_tab_append.simple(), + action_tab_close.simple(), + action_tab_close_all.simple(), + action_tab_page_navigation_base.simple(), + action_tab_page_navigation_history_back.simple(), + action_tab_page_navigation_history_forward.simple(), + action_tab_page_navigation_reload.simple(), + action_tab_pin.simple(), + )); + + // Show main widget + browser.widget().present(); + + // Make initial update + action_update.simple().activate(None); + } + }); + + // Return activated struct + Self { app } + } + + // Actions + pub fn run(&self) -> ExitCode { + self.app.run() + } +} diff --git a/src/app/action.rs b/src/app/action.rs new file mode 100644 index 00000000..53103b0b --- /dev/null +++ b/src/app/action.rs @@ -0,0 +1,42 @@ +// This helper created as the attempt to drop static names usage +// and replace them with objects (to follow encapsulation for children mods) +// @TODO find alternative implementation, if exist for GTK 4 + +use std::sync::Arc; + +use gtk::{ + gio::SimpleAction, + glib::{gformat, uuid_string_random, GString}, + prelude::ActionExt, +}; + +pub struct Action { + group: GString, + simple: Arc, +} + +impl Action { + // Construct + pub fn new(group: &str, is_enabled: bool) -> Self { + // Create random action name as no static values should be in use + let simple = Arc::new(SimpleAction::new(&uuid_string_random(), None)); + simple.set_enabled(is_enabled); + + // Assign action to the group + let group = GString::from(group); + + // Return new Action + Self { group, simple } + } + + // Getters + pub fn detailed_name(&self) -> GString { + gformat!("{}.{}", self.group, self.simple.name()) // @TODO find the way to ident parent group + // from SimpleAction object + } + + // App mods work with simple and system-wide data types, let them take it + pub fn simple(&self) -> Arc { + self.simple.clone() + } +} diff --git a/src/browser.rs b/src/app/browser.rs similarity index 97% rename from src/browser.rs rename to src/app/browser.rs index 229ed581..fd5df39a 100644 --- a/src/browser.rs +++ b/src/app/browser.rs @@ -1,4 +1,3 @@ -mod db; mod header; mod main; @@ -27,7 +26,9 @@ pub struct Browser { impl Browser { // Construct pub fn new( - app: &Application, + // Dependencies + application: &Application, + // Extras // connection: Arc, // Actions action_debug: Arc, @@ -69,7 +70,7 @@ impl Browser { // Init widget let widget = ApplicationWindow::builder() - .application(app) + .application(application) .titlebar(header.widget()) .child(main.widget()) .default_height(DEFAULT_HEIGHT) diff --git a/src/browser/db.rs b/src/app/browser/db.rs similarity index 100% rename from src/browser/db.rs rename to src/app/browser/db.rs diff --git a/src/browser/header.rs b/src/app/browser/header.rs similarity index 100% rename from src/browser/header.rs rename to src/app/browser/header.rs diff --git a/src/browser/header/subject.rs b/src/app/browser/header/subject.rs similarity index 100% rename from src/browser/header/subject.rs rename to src/app/browser/header/subject.rs diff --git a/src/browser/header/subject/description.rs b/src/app/browser/header/subject/description.rs similarity index 100% rename from src/browser/header/subject/description.rs rename to src/app/browser/header/subject/description.rs diff --git a/src/browser/header/subject/title.rs b/src/app/browser/header/subject/title.rs similarity index 100% rename from src/browser/header/subject/title.rs rename to src/app/browser/header/subject/title.rs diff --git a/src/browser/header/tray.rs b/src/app/browser/header/tray.rs similarity index 100% rename from src/browser/header/tray.rs rename to src/app/browser/header/tray.rs diff --git a/src/browser/header/tray/menu.rs b/src/app/browser/header/tray/menu.rs similarity index 98% rename from src/browser/header/tray/menu.rs rename to src/app/browser/header/tray/menu.rs index 5b4dcc79..1062ba9b 100644 --- a/src/browser/header/tray/menu.rs +++ b/src/app/browser/header/tray/menu.rs @@ -76,4 +76,5 @@ impl Menu { fn detailed_action_name(action: Arc) -> GString { gformat!("win.{}", action.name()) // @TODO find the way to ident parent group // without application-wide dependencies import + // see also src/app/action.rs } diff --git a/src/browser/header/tray/tab.rs b/src/app/browser/header/tray/tab.rs similarity index 100% rename from src/browser/header/tray/tab.rs rename to src/app/browser/header/tray/tab.rs diff --git a/src/browser/main.rs b/src/app/browser/main.rs similarity index 100% rename from src/browser/main.rs rename to src/app/browser/main.rs diff --git a/src/browser/main/tab.rs b/src/app/browser/main/tab.rs similarity index 100% rename from src/browser/main/tab.rs rename to src/app/browser/main/tab.rs diff --git a/src/browser/main/tab/label.rs b/src/app/browser/main/tab/label.rs similarity index 100% rename from src/browser/main/tab/label.rs rename to src/app/browser/main/tab/label.rs diff --git a/src/browser/main/tab/label/pin.rs b/src/app/browser/main/tab/label/pin.rs similarity index 100% rename from src/browser/main/tab/label/pin.rs rename to src/app/browser/main/tab/label/pin.rs diff --git a/src/browser/main/tab/label/title.rs b/src/app/browser/main/tab/label/title.rs similarity index 100% rename from src/browser/main/tab/label/title.rs rename to src/app/browser/main/tab/label/title.rs diff --git a/src/browser/main/tab/page.rs b/src/app/browser/main/tab/page.rs similarity index 100% rename from src/browser/main/tab/page.rs rename to src/app/browser/main/tab/page.rs diff --git a/src/browser/main/tab/page/content.rs b/src/app/browser/main/tab/page/content.rs similarity index 100% rename from src/browser/main/tab/page/content.rs rename to src/app/browser/main/tab/page/content.rs diff --git a/src/browser/main/tab/page/content/text.rs b/src/app/browser/main/tab/page/content/text.rs similarity index 100% rename from src/browser/main/tab/page/content/text.rs rename to src/app/browser/main/tab/page/content/text.rs diff --git a/src/browser/main/tab/page/content/text/gemini.rs b/src/app/browser/main/tab/page/content/text/gemini.rs similarity index 100% rename from src/browser/main/tab/page/content/text/gemini.rs rename to src/app/browser/main/tab/page/content/text/gemini.rs diff --git a/src/browser/main/tab/page/content/text/gemini/reader.rs b/src/app/browser/main/tab/page/content/text/gemini/reader.rs similarity index 100% rename from src/browser/main/tab/page/content/text/gemini/reader.rs rename to src/app/browser/main/tab/page/content/text/gemini/reader.rs diff --git a/src/browser/main/tab/page/content/text/gemini/reader/default.css b/src/app/browser/main/tab/page/content/text/gemini/reader/default.css similarity index 100% rename from src/browser/main/tab/page/content/text/gemini/reader/default.css rename to src/app/browser/main/tab/page/content/text/gemini/reader/default.css diff --git a/src/browser/main/tab/page/content/text/gemini/reader/parser.rs b/src/app/browser/main/tab/page/content/text/gemini/reader/parser.rs similarity index 100% rename from src/browser/main/tab/page/content/text/gemini/reader/parser.rs rename to src/app/browser/main/tab/page/content/text/gemini/reader/parser.rs diff --git a/src/browser/main/tab/page/content/text/gemini/reader/parser/header.rs b/src/app/browser/main/tab/page/content/text/gemini/reader/parser/header.rs similarity index 100% rename from src/browser/main/tab/page/content/text/gemini/reader/parser/header.rs rename to src/app/browser/main/tab/page/content/text/gemini/reader/parser/header.rs diff --git a/src/browser/main/tab/page/content/text/gemini/reader/parser/link.rs b/src/app/browser/main/tab/page/content/text/gemini/reader/parser/link.rs similarity index 100% rename from src/browser/main/tab/page/content/text/gemini/reader/parser/link.rs rename to src/app/browser/main/tab/page/content/text/gemini/reader/parser/link.rs diff --git a/src/browser/main/tab/page/content/text/gemini/reader/parser/plain.rs b/src/app/browser/main/tab/page/content/text/gemini/reader/parser/plain.rs similarity index 100% rename from src/browser/main/tab/page/content/text/gemini/reader/parser/plain.rs rename to src/app/browser/main/tab/page/content/text/gemini/reader/parser/plain.rs diff --git a/src/browser/main/tab/page/content/text/plain/reader.rs b/src/app/browser/main/tab/page/content/text/plain/reader.rs similarity index 100% rename from src/browser/main/tab/page/content/text/plain/reader.rs rename to src/app/browser/main/tab/page/content/text/plain/reader.rs diff --git a/src/browser/main/tab/page/meta.rs b/src/app/browser/main/tab/page/meta.rs similarity index 100% rename from src/browser/main/tab/page/meta.rs rename to src/app/browser/main/tab/page/meta.rs diff --git a/src/browser/main/tab/page/navigation.rs b/src/app/browser/main/tab/page/navigation.rs similarity index 100% rename from src/browser/main/tab/page/navigation.rs rename to src/app/browser/main/tab/page/navigation.rs diff --git a/src/browser/main/tab/page/navigation/base.rs b/src/app/browser/main/tab/page/navigation/base.rs similarity index 100% rename from src/browser/main/tab/page/navigation/base.rs rename to src/app/browser/main/tab/page/navigation/base.rs diff --git a/src/browser/main/tab/page/navigation/bookmark.rs b/src/app/browser/main/tab/page/navigation/bookmark.rs similarity index 100% rename from src/browser/main/tab/page/navigation/bookmark.rs rename to src/app/browser/main/tab/page/navigation/bookmark.rs diff --git a/src/browser/main/tab/page/navigation/history.rs b/src/app/browser/main/tab/page/navigation/history.rs similarity index 100% rename from src/browser/main/tab/page/navigation/history.rs rename to src/app/browser/main/tab/page/navigation/history.rs diff --git a/src/browser/main/tab/page/navigation/history/back.rs b/src/app/browser/main/tab/page/navigation/history/back.rs similarity index 100% rename from src/browser/main/tab/page/navigation/history/back.rs rename to src/app/browser/main/tab/page/navigation/history/back.rs diff --git a/src/browser/main/tab/page/navigation/history/forward.rs b/src/app/browser/main/tab/page/navigation/history/forward.rs similarity index 100% rename from src/browser/main/tab/page/navigation/history/forward.rs rename to src/app/browser/main/tab/page/navigation/history/forward.rs diff --git a/src/browser/main/tab/page/navigation/reload.rs b/src/app/browser/main/tab/page/navigation/reload.rs similarity index 100% rename from src/browser/main/tab/page/navigation/reload.rs rename to src/app/browser/main/tab/page/navigation/reload.rs diff --git a/src/browser/main/tab/page/navigation/request.rs b/src/app/browser/main/tab/page/navigation/request.rs similarity index 100% rename from src/browser/main/tab/page/navigation/request.rs rename to src/app/browser/main/tab/page/navigation/request.rs diff --git a/src/main.rs b/src/main.rs index 987795cf..fc1492e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,112 +1,8 @@ -mod browser; +mod app; -use browser::Browser; - -use gtk::{ - gio::SimpleAction, - glib::{user_config_dir, ExitCode}, - prelude::{ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt}, - Application, -}; - -use std::{fs::create_dir_all, sync::Arc}; - -const APP_ID: &str = "io.github.yggverse.Yoda"; +use app::App; +use gtk::glib::ExitCode; fn main() -> ExitCode { - // Init app - let app = Application::builder().application_id(APP_ID).build(); - - // Init actions - let action_debug = Arc::new(SimpleAction::new("debug", None)); - let action_quit = Arc::new(SimpleAction::new("quit", None)); - let action_update = Arc::new(SimpleAction::new("update", None)); - - let action_tab_append = Arc::new(SimpleAction::new("tab_append", None)); - let action_tab_close = Arc::new(SimpleAction::new("tab_close", None)); - let action_tab_close_all = Arc::new(SimpleAction::new("tab_close_all", None)); - - let action_tab_page_navigation_base = - Arc::new(SimpleAction::new("tab_page_navigation_base", None)); - action_tab_page_navigation_base.set_enabled(false); - - let action_tab_page_navigation_history_back = - Arc::new(SimpleAction::new("tab_page_navigation_history_back", None)); - action_tab_page_navigation_history_back.set_enabled(false); - - let action_tab_page_navigation_history_forward = Arc::new(SimpleAction::new( - "tab_page_navigation_history_forward", - None, - )); - action_tab_page_navigation_history_forward.set_enabled(false); - - let action_tab_page_navigation_reload = - Arc::new(SimpleAction::new("tab_page_navigation_reload", None)); - let action_tab_pin = Arc::new(SimpleAction::new("tab_pin", None)); - - // Init accels - app.set_accels_for_action("win.debug", &["i"]); - app.set_accels_for_action("win.update", &["u"]); - app.set_accels_for_action("win.quit", &["Escape"]); - - app.set_accels_for_action("win.tab_append", &["t"]); - app.set_accels_for_action("win.tab_pin", &["p"]); - app.set_accels_for_action("win.tab_close", &["q"]); - app.set_accels_for_action("win.tab_page_navigation_base", &["h"]); - app.set_accels_for_action("win.tab_page_navigation_history_back", &["Left"]); - app.set_accels_for_action( - "win.tab_page_navigation_history_forward", - &["Right"], - ); - app.set_accels_for_action("win.tab_page_navigation_reload", &["r"]); - //app.set_accels_for_action("win.tab_page_bookmark", &["b"]); - - // Create new window - app.connect_activate({ - // Init profile directory - let mut fs = user_config_dir(); - - fs.push(APP_ID); - - if let Err(e) = create_dir_all(&fs) { - panic!("Failed to create profile directory: {e}") - } - - // Init profile database - /* @TODO - let mut db = fs.clone(); - - db.push("database.sqlite3"); - - let db = match sqlite::open(db) { - Ok(db) => Arc::new(db), - Err(e) => panic!("Failed to connect profile database: {e}"), - };*/ - - move |this: &Application| { - Browser::new( - this, - /*db.clone(),*/ - action_debug.clone(), - action_quit.clone(), - action_update.clone(), - action_tab_append.clone(), - action_tab_close.clone(), - action_tab_close_all.clone(), - action_tab_page_navigation_base.clone(), - action_tab_page_navigation_history_back.clone(), - action_tab_page_navigation_history_forward.clone(), - action_tab_page_navigation_reload.clone(), - action_tab_pin.clone(), - ) - .widget() - .present(); - - // Make initial update - action_update.activate(None); - } - }); - - // Start - app.run() + App::new().run() }