diff --git a/src/app.rs b/src/app.rs index fc5a3873..91455b52 100644 --- a/src/app.rs +++ b/src/app.rs @@ -7,7 +7,7 @@ use crate::profile::Profile; use adw::Application; use gtk::{ glib::ExitCode, - prelude::{ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt}, + prelude::{ApplicationExt, ApplicationExtManual, GtkApplicationExt}, }; use sqlite::Transaction; use std::rc::Rc; @@ -41,7 +41,7 @@ impl App { let profile = profile.clone(); move |this| { // Init readable connection - match profile.database().read() { + match profile.database.connection.read() { Ok(connection) => { // Create transaction match connection.unchecked_transaction() { @@ -57,9 +57,6 @@ impl App { todo!("{e}") } } - - // Run initial features - browser.init(); } Err(e) => todo!("{e}"), } @@ -70,11 +67,8 @@ impl App { Err(e) => todo!("{e}"), } - // Assign browser window to this application - browser.gobject().set_application(Some(this)); - - // Show main widget - browser.gobject().present(); + // Run initial features, show widget + browser.init(Some(this)).present(); } }); @@ -83,7 +77,7 @@ impl App { let profile = profile.clone(); move |_| { // Init writable connection - match profile.database().write() { + match profile.database.connection.write() { Ok(mut connection) => { // Create transaction match connection.transaction() { @@ -240,7 +234,7 @@ impl App { // Begin database migration @TODO { // Init writable connection - let mut connection = match self.profile.database().try_write() { + let mut connection = match self.profile.database.connection.write() { Ok(connection) => connection, Err(e) => todo!("{e}"), }; diff --git a/src/app/browser.rs b/src/app/browser.rs index d41c9834..c5479498 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -12,11 +12,10 @@ use widget::Widget; use window::Window; use crate::profile::Profile; -use adw::ApplicationWindow; use gtk::{ gio::{Cancellable, File}, - prelude::GtkWindowExt, - FileLauncher, + prelude::{GtkWindowExt, IsA}, + Application, FileLauncher, }; use sqlite::Transaction; use std::rc::Rc; @@ -76,7 +75,7 @@ impl Browser { action.profile().connect_activate({ let profile = profile.clone(); move || { - FileLauncher::new(Some(&File::for_path(profile.config_path()))).launch( + FileLauncher::new(Some(&File::for_path(profile.config_path.as_path()))).launch( None::<>k::Window>, None::<&Cancellable>, |result| { @@ -163,12 +162,25 @@ impl Browser { Ok(()) } - pub fn init(&self) { - // Show welcome dialog on profile not selected yet (e.g. first launch) @TODO - // Welcome::new(self.profile.clone()).present(Some(self.widget.gobject())); + pub fn init(&self, application: Option<&impl IsA>) -> &Self { + // Assign browser window to this application + self.widget.gobject().set_application(application); // @TODO // Init main window self.window.init(); + self + } + + pub fn present(&self) -> &Self { + // Show main window + self.widget.gobject().present(); + + // Show welcome dialog on profile not selected yet (e.g. first launch) + if self.profile.database.selected().is_none() { + Welcome::new(self.profile.clone()).present(Some(self.widget.gobject())); + } + + self } pub fn update(&self) { @@ -181,10 +193,6 @@ impl Browser { &self.action } - pub fn gobject(&self) -> &ApplicationWindow { - self.widget.gobject() - } - pub fn window(&self) -> &Rc { &self.window } diff --git a/src/profile.rs b/src/profile.rs index a2e95fab..e1e5c4e9 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -3,24 +3,21 @@ mod database; mod history; mod identity; +use database::Database; + use gtk::glib::user_config_dir; use sqlite::{Connection, Transaction}; -use std::{ - fs::create_dir_all, - path::{Path, PathBuf}, - rc::Rc, - sync::RwLock, -}; +use std::{fs::create_dir_all, path::PathBuf, rc::Rc, sync::RwLock}; const VENDOR: &str = "YGGverse"; const APP_ID: &str = "Yoda"; const BRANCH: &str = "master"; -const DB_NAME: &str = "profile.sqlite3"; +const DB_NAME: &str = "database.sqlite3"; pub struct Profile { - database: Rc>, - config_path: PathBuf, + pub database: Rc, + pub config_path: PathBuf, } impl Profile { @@ -82,20 +79,10 @@ impl Profile { // Result Self { - database: connection, + database: Rc::new(Database::new(connection)), config_path, } } - - // Getters - - pub fn database(&self) -> &Rc> { - &self.database - } - - pub fn config_path(&self) -> &Path { - self.config_path.as_path() - } } pub fn migrate(tx: &Transaction) -> Result<(), String> { diff --git a/src/profile/database.rs b/src/profile/database.rs index 01a730b2..8e3186ae 100644 --- a/src/profile/database.rs +++ b/src/profile/database.rs @@ -1,22 +1,60 @@ -use sqlite::{Error, Transaction}; - use gtk::glib::DateTime; +use sqlite::{Connection, Error, Transaction}; +use std::{rc::Rc, sync::RwLock}; +#[derive(Debug)] pub struct Table { pub id: i64, - pub active: bool, + pub is_active: bool, pub time: DateTime, pub name: Option, } +pub struct Database { + pub connection: Rc>, +} + +impl Database { + // Constructors + + /// Create new `Self` + pub fn new(connection: Rc>) -> Self { + Self { connection } + } + + // Getters + + /// Get all records + pub fn records(&self) -> Vec { + let binding = self.connection.read().unwrap(); + let tx = binding.unchecked_transaction().unwrap(); + + records(&tx).unwrap() + } + + /// Get selected profile record if exist + pub fn selected(&self) -> Option
{ + let binding = self.connection.read().unwrap(); + let tx = binding.unchecked_transaction().unwrap(); + + for record in records(&tx).unwrap() { + if record.is_active { + return Some(record); + } + } + + None + } +} + pub fn init(tx: &Transaction) -> Result { tx.execute( "CREATE TABLE IF NOT EXISTS `profile` ( - `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - `active` INTEGER NOT NULL, - `time` INTEGER NOT NULL, - `name` VARCHAR(255) + `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + `is_active` INTEGER NOT NULL, + `time` INTEGER NOT NULL, + `name` VARCHAR(255) )", [], ) @@ -24,19 +62,19 @@ pub fn init(tx: &Transaction) -> Result { pub fn add( tx: &Transaction, - active: bool, + is_active: bool, time: &DateTime, name: Option<&str>, ) -> Result { - tx.execute("INSERT INTO `profile`", (active, time.to_unix(), name)) + tx.execute("INSERT INTO `profile`", (is_active, time.to_unix(), name)) } pub fn records(tx: &Transaction) -> Result, Error> { - let mut stmt = tx.prepare("SELECT `id`, `active`, `time`, `name` FROM `profile`")?; + let mut stmt = tx.prepare("SELECT `id`, `is_active`, `time`, `name` FROM `profile`")?; let result = stmt.query_map([], |row| { Ok(Table { id: row.get(0)?, - active: row.get(1)?, + is_active: row.get(1)?, time: DateTime::from_unix_local(row.get(2)?).unwrap(), name: row.get(3)?, })