From 25b63c0e02d0f725d12f5e151c87d290a987e618 Mon Sep 17 00:00:00 2001 From: yggverse Date: Fri, 8 Nov 2024 07:46:25 +0200 Subject: [PATCH] collect profile features into one shared struct --- src/app.rs | 35 ++++++++++----------------- src/app/browser.rs | 10 ++++---- src/main.rs | 50 +++++++++++++------------------------- src/profile.rs | 53 +++++++++++++++++++++++++++++++++++++++++ src/profile/database.rs | 25 +++++++++++++++++++ 5 files changed, 111 insertions(+), 62 deletions(-) create mode 100644 src/profile.rs create mode 100644 src/profile/database.rs diff --git a/src/app.rs b/src/app.rs index ad279e6a..d034c858 100644 --- a/src/app.rs +++ b/src/app.rs @@ -4,7 +4,7 @@ mod database; use browser::Browser; use database::Database; -use crate::action::Browser as BrowserAction; +use crate::{action::Browser as BrowserAction, Profile}; use adw::Application; use gtk::{ gio::SimpleAction, @@ -13,20 +13,19 @@ use gtk::{ ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt, ToVariant, }, }; -use sqlite::{Connection, Transaction}; - -use std::{path::PathBuf, rc::Rc, sync::RwLock}; +use sqlite::Transaction; +use std::rc::Rc; const APPLICATION_ID: &str = "io.github.yggverse.Yoda"; pub struct App { - profile_database_connection: Rc>, + profile: Rc, gobject: Application, } impl App { // Construct - pub fn new(profile_database_connection: Rc>, profile_path: PathBuf) -> Self { + pub fn new(profile: Rc) -> Self { // Init actions let browser_action = Rc::new(BrowserAction::new()); @@ -97,7 +96,7 @@ impl App { // Init components let browser = Rc::new(Browser::new( - profile_path, + profile.clone(), browser_action.clone(), action_page_new.clone(), action_page_close.clone(), @@ -120,10 +119,10 @@ impl App { gobject.connect_startup({ let browser = browser.clone(); - let profile_database_connection = profile_database_connection.clone(); + let profile = profile.clone(); move |this| { // Init readable connection - match profile_database_connection.read() { + match profile.database().connection().read() { Ok(connection) => { // Create transaction match connection.unchecked_transaction() { @@ -161,12 +160,11 @@ impl App { }); gobject.connect_shutdown({ - // let browser = browser.clone(); - let profile_database_connection = profile_database_connection.clone(); let browser = browser.clone(); + let profile = profile.clone(); move |_| { // Init writable connection - match profile_database_connection.write() { + match profile.database().connection().write() { Ok(mut connection) => { // Create transaction match connection.transaction() { @@ -219,16 +217,7 @@ impl App { }); // Return activated App struct - Self { - // database, - profile_database_connection, - // Actions (SimpleAction) - // action_update: action_update.simple(), - // Components - // browser, - // GTK - gobject, - } + Self { profile, gobject } } // Actions @@ -236,7 +225,7 @@ impl App { // Begin database migration @TODO { // Init writable connection - let mut connection = match self.profile_database_connection.try_write() { + let mut connection = match self.profile.database().connection().try_write() { Ok(connection) => connection, Err(e) => todo!("{e}"), }; diff --git a/src/app/browser.rs b/src/app/browser.rs index c81a73e1..e0929ba3 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -8,7 +8,7 @@ use database::Database; use widget::Widget; use window::Window; -use crate::action::Browser as BrowserAction; +use crate::{action::Browser as BrowserAction, Profile}; use adw::ApplicationWindow; use gtk::{ gio::{Cancellable, File, SimpleAction}, @@ -17,7 +17,7 @@ use gtk::{ FileLauncher, }; use sqlite::Transaction; -use std::{path::PathBuf, rc::Rc}; +use std::rc::Rc; pub struct Browser { window: Rc, @@ -27,9 +27,7 @@ pub struct Browser { impl Browser { // Construct pub fn new( - // Extras - profile_path: PathBuf, - // Actions + profile: Rc, browser_action: Rc, action_page_new: SimpleAction, action_page_close: SimpleAction, @@ -92,7 +90,7 @@ impl Browser { browser_action.profile().connect_activate({ move |_, _| { - FileLauncher::new(Some(&File::for_path(&profile_path))).launch( + FileLauncher::new(Some(&File::for_path(profile.config_path()))).launch( None::<>k::Window>, None::<&Cancellable>, |result| { diff --git a/src/main.rs b/src/main.rs index d0a51f2b..39eebd12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,46 +1,30 @@ mod action; mod app; +mod profile; +use crate::profile::Profile; use app::App; -use gtk::glib::{user_config_dir, ExitCode}; -use sqlite::Connection; -use std::{fs::create_dir_all, rc::Rc, sync::RwLock}; +use gtk::glib::ExitCode; +use std::rc::Rc; const VENDOR: &str = "YGGverse"; -const APP_ID: &str = "Yoda"; // env!("CARGO_PKG_NAME"); +const APP_ID: &str = "Yoda"; const BRANCH: &str = "master"; fn main() -> ExitCode { - // Init profile path - let mut profile_path = user_config_dir(); - - profile_path.push(VENDOR); - profile_path.push(APP_ID); - profile_path.push(BRANCH); - profile_path.push(format!( - "{}.{}", - env!("CARGO_PKG_VERSION_MAJOR"), - env!("CARGO_PKG_VERSION_MINOR") - )); // @TODO remove after auto-migrate feature implementation - - if let Err(e) = create_dir_all(&profile_path) { - panic!("Failed to create profile directory: {e}") - } - - // Init profile database path - let mut profile_database_path = profile_path.clone(); - - profile_database_path.push("profile.sqlite3"); - - // Init database connection - let profile_database_connection = match Connection::open(profile_database_path) { - Ok(connection) => Rc::new(RwLock::new(connection)), - Err(e) => panic!("Failed to connect profile database: {e}"), - }; - - // Init GTK, start application match gtk::init() { - Ok(_) => App::new(profile_database_connection, profile_path).run(), // @TODO common struct for profile data + Ok(_) => App::new(Rc::new(Profile::new( + VENDOR, + APP_ID, + BRANCH, + format!( + "{}.{}", + env!("CARGO_PKG_VERSION_MAJOR"), + env!("CARGO_PKG_VERSION_MINOR") + ) + .as_str(), + ))) + .run(), Err(_) => ExitCode::FAILURE, } } diff --git a/src/profile.rs b/src/profile.rs new file mode 100644 index 00000000..9a4a15ec --- /dev/null +++ b/src/profile.rs @@ -0,0 +1,53 @@ +mod database; +pub use database::Database; + +use gtk::glib::user_config_dir; +use std::{ + fs::create_dir_all, + path::{Path, PathBuf}, +}; + +const DB_NAME: &str = "profile.sqlite3"; + +pub struct Profile { + database: Database, + config_path: PathBuf, +} + +impl Profile { + // Constructors + + pub fn new(vendor: &str, app_id: &str, branch: &str, version: &str) -> Self { + // Init profile path + let mut config_path = user_config_dir(); + + config_path.push(vendor); + config_path.push(app_id); + config_path.push(branch); + config_path.push(version); // @TODO remove after auto-migrate feature implementation + + if let Err(e) = create_dir_all(&config_path) { + panic!("Failed to create profile directory: {e}") + } + + // Init database path + let mut database_path = config_path.clone(); + database_path.push(DB_NAME); + + // Result + Self { + database: Database::new(database_path.as_path()), + config_path, + } + } + + // Getters + + pub fn database(&self) -> &Database { + &self.database + } + + pub fn config_path(&self) -> &Path { + self.config_path.as_path() + } +} diff --git a/src/profile/database.rs b/src/profile/database.rs new file mode 100644 index 00000000..c4ad7822 --- /dev/null +++ b/src/profile/database.rs @@ -0,0 +1,25 @@ +use sqlite::Connection; +use std::{path::Path, rc::Rc, sync::RwLock}; + +pub struct Database { + connection: Rc>, +} + +impl Database { + // Constructors + + pub fn new(path: &Path) -> Self { + Self { + connection: match Connection::open(path) { + Ok(connection) => Rc::new(RwLock::new(connection)), + Err(e) => panic!("Failed to connect profile database: {e}"), + }, + } + } + + // Getters + + pub fn connection(&self) -> &Rc> { + &self.connection + } +}