move profile components to separated namespace

This commit is contained in:
yggverse 2024-11-13 03:40:29 +02:00
parent 61010e0a42
commit b12f5e8b8f
13 changed files with 332 additions and 214 deletions

View File

@ -21,10 +21,7 @@ pub struct App {
impl App {
// Construct
pub fn new() -> Self {
// Init profile
let profile = Rc::new(Profile::new());
pub fn new(profile: Rc<Profile>) -> Self {
// Init GTK
let gobject = Application::builder()
.application_id(APPLICATION_ID)
@ -44,7 +41,7 @@ impl App {
let profile = profile.clone();
move |this| {
// Init readable connection
match profile.database().connection().read() {
match profile.database().read() {
Ok(connection) => {
// Create transaction
match connection.unchecked_transaction() {
@ -86,7 +83,7 @@ impl App {
let profile = profile.clone();
move |_| {
// Init writable connection
match profile.database().connection().write() {
match profile.database().write() {
Ok(mut connection) => {
// Create transaction
match connection.transaction() {
@ -243,7 +240,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().try_write() {
Ok(connection) => connection,
Err(e) => todo!("{e}"),
};

View File

@ -2,11 +2,14 @@ mod app;
mod profile;
use app::App;
use profile::Profile;
use gtk::glib::ExitCode;
use std::rc::Rc;
fn main() -> ExitCode {
match gtk::init() {
Ok(_) => App::new().run(),
Ok(_) => App::new(Rc::new(Profile::new())).run(),
Err(_) => ExitCode::FAILURE,
}
}

View File

@ -1,10 +1,15 @@
mod bookmark;
mod database;
use database::Database;
mod history;
mod identity;
use gtk::glib::user_config_dir;
use sqlite::{Connection, Transaction};
use std::{
fs::create_dir_all,
path::{Path, PathBuf},
rc::Rc,
sync::RwLock,
};
const VENDOR: &str = "YGGverse";
@ -14,7 +19,7 @@ const BRANCH: &str = "master";
const DB_NAME: &str = "profile.sqlite3";
pub struct Profile {
database: Database,
database: Rc<RwLock<Connection>>,
config_path: PathBuf,
}
@ -42,16 +47,49 @@ impl Profile {
let mut database_path = config_path.clone();
database_path.push(DB_NAME);
// Init database connection
let connection = match Connection::open(database_path.as_path()) {
Ok(connection) => Rc::new(RwLock::new(connection)),
Err(reason) => panic!("{reason}"),
};
// Init profile components
{
// Init writable connection
let mut connection = match connection.write() {
Ok(connection) => connection,
Err(e) => todo!("{e}"),
};
// Init new transaction
let transaction = match connection.transaction() {
Ok(transaction) => transaction,
Err(e) => todo!("{e}"),
};
// Begin migration
match migrate(&transaction) {
Ok(_) => {
// Confirm changes
match transaction.commit() {
Ok(_) => {} // @TODO
Err(e) => todo!("{e}"),
}
}
Err(e) => todo!("{e}"),
}
} // unlock database
// Result
Self {
database: Database::new(database_path.as_path()),
database: connection,
config_path,
}
}
// Getters
pub fn database(&self) -> &Database {
pub fn database(&self) -> &Rc<RwLock<Connection>> {
&self.database
}
@ -59,3 +97,18 @@ impl Profile {
self.config_path.as_path()
}
}
pub fn migrate(tx: &Transaction) -> Result<(), String> {
// Migrate self components
if let Err(e) = database::init(tx) {
return Err(e.to_string());
}
// Delegate migration to children components
bookmark::migrate(tx)?;
history::migrate(tx)?;
identity::migrate(tx)?;
// Success
Ok(())
}

18
src/profile/bookmark.rs Normal file
View File

@ -0,0 +1,18 @@
mod database;
use sqlite::Transaction;
// Tools
pub fn migrate(tx: &Transaction) -> Result<(), String> {
// Migrate self components
if let Err(e) = database::init(tx) {
return Err(e.to_string());
}
// Delegate migration to childs
// nothing yet..
// Success
Ok(())
}

View File

@ -0,0 +1,81 @@
use gtk::glib::DateTime;
use sqlite::{Error, Transaction};
pub struct Table {
pub id: i64,
pub profile_id: i64,
pub time: DateTime,
pub request: String,
}
pub struct Bookmark {
// nothing yet..
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `profile_bookmark`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`profile_id` INTEGER NOT NULL,
`time` INTEGER NOT NULL,
`request` TEXT NOT NULL
)",
[],
)
}
pub fn add(
tx: &Transaction,
profile_id: &i64,
time: &DateTime,
request: &str,
) -> Result<usize, Error> {
tx.execute(
"INSERT INTO `profile_bookmark` (
`profile_id`,
`time`,
`request`
) VALUES (?, ?, ?)",
(profile_id, time.to_unix(), request),
)
}
pub fn records(
tx: &Transaction,
profile_id: &i64,
request: Option<&str>,
) -> Result<Vec<Table>, Error> {
let mut stmt = tx.prepare(
"SELECT `id`, `profile_id`, `time`, `request`
FROM `profile_bookmark`
WHERE `profile_id` = ? AND `request` LIKE ?",
)?;
let filter = match request {
Some(value) => value,
None => "%",
};
let result = stmt.query_map((profile_id, filter), |row| {
Ok(Table {
id: row.get(0)?,
profile_id: row.get(1)?,
time: DateTime::from_unix_local(row.get(2)?).unwrap(),
request: row.get(3)?,
})
})?;
let mut records = Vec::new();
for record in result {
let table = record?;
records.push(table);
}
Ok(records)
}
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
tx.execute("DELETE FROM `profile_bookmark` WHERE `id` = ?", [id])
}

View File

@ -1,63 +1,41 @@
mod bookmark;
mod history;
mod identity;
use sqlite::{Error, Transaction};
use sqlite::{Connection, Error};
use std::{
path::Path,
rc::Rc,
sync::{RwLock, RwLockWriteGuard},
};
pub struct Database {
connection: Rc<RwLock<Connection>>,
pub struct Table {
pub id: i64,
}
impl Database {
// Constructors
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `profile`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
)",
[],
)
}
/// Create new connected `Self`
pub fn new(path: &Path) -> Self {
// Init database connection
let connection = match Connection::open(path) {
Ok(connection) => Rc::new(RwLock::new(connection)),
Err(reason) => panic!("{reason}"),
};
pub fn add(tx: &Transaction) -> Result<usize, Error> {
tx.execute("INSERT INTO `profile` DEFAULT VALUES", [])
}
// Init profile components
match connection.write() {
Ok(writable) => {
if let Err(reason) = init(writable) {
panic!("{reason}")
}
}
Err(reason) => panic!("{reason}"),
};
pub fn records(tx: &Transaction) -> Result<Vec<Table>, Error> {
let mut stmt = tx.prepare("SELECT `profile_id` FROM `profile`")?;
let result = stmt.query_map([], |row| Ok(Table { id: row.get(0)? }))?;
// Result
Self { connection }
let mut records = Vec::new();
for record in result {
let table = record?;
records.push(table);
}
// Getters
pub fn connection(&self) -> &Rc<RwLock<Connection>> {
&self.connection
}
Ok(records)
}
// Tools
fn init(mut connection: RwLockWriteGuard<'_, Connection>) -> Result<(), Error> {
// Begin transaction
let transaction = connection.transaction()?;
// Init profile components
bookmark::init(&transaction)?;
history::init(&transaction)?;
identity::init(&transaction)?;
// Apply changes
transaction.commit()?;
Ok(())
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
tx.execute("DELETE FROM `profile` WHERE `id` = ?", [id])
}
pub fn last_insert_id(tx: &Transaction) -> i64 {
tx.last_insert_rowid()
}

View File

@ -1,65 +0,0 @@
use gtk::glib::DateTime;
use sqlite::{Error, Transaction};
pub struct Table {
pub id: i64,
pub time: DateTime,
pub request: String,
}
pub struct Bookmark {
// nothing yet..
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `bookmark`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`request` TEXT NOT NULL
)",
[],
)
}
pub fn add(tx: &Transaction, time: &DateTime, request: &str) -> Result<usize, Error> {
tx.execute(
"INSERT INTO `bookmark` (
`time`,
`request`
) VALUES (?, ?)",
(time.to_unix(), request),
)
}
pub fn records(tx: &Transaction, request: Option<&str>) -> Result<Vec<Table>, Error> {
let mut stmt =
tx.prepare("SELECT `id`, `time`, `request` FROM `bookmark` WHERE `request` LIKE ?")?;
let filter = match request {
Some(value) => value,
None => "%",
};
let result = stmt.query_map([filter], |row| {
Ok(Table {
id: row.get(0)?,
time: DateTime::from_unix_local(row.get(1)?).unwrap(),
request: row.get(2)?,
})
})?;
let mut records = Vec::new();
for record in result {
let table = record?;
records.push(table);
}
Ok(records)
}
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
tx.execute("DELETE FROM `bookmark` WHERE `id` = ?", [id])
}

View File

@ -1,65 +0,0 @@
use gtk::glib::DateTime;
use sqlite::{Error, Transaction};
pub struct Table {
pub id: i64,
pub time: DateTime,
pub request: String,
}
pub struct History {
// nothing yet..
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `history`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`request` TEXT NOT NULL
)",
[],
)
}
pub fn add(tx: &Transaction, time: &DateTime, request: &str) -> Result<usize, Error> {
tx.execute(
"INSERT INTO `history` (
`time`,
`request`
) VALUES (?, ?)",
(time.to_unix(), request),
)
}
pub fn records(tx: &Transaction, request: Option<&str>) -> Result<Vec<Table>, Error> {
let mut stmt =
tx.prepare("SELECT `id`, `time`, `request` FROM `history` WHERE `request` LIKE ?")?;
let filter = match request {
Some(value) => value,
None => "%",
};
let result = stmt.query_map([filter], |row| {
Ok(Table {
id: row.get(0)?,
time: DateTime::from_unix_local(row.get(1)?).unwrap(),
request: row.get(2)?,
})
})?;
let mut records = Vec::new();
for record in result {
let table = record?;
records.push(table);
}
Ok(records)
}
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
tx.execute("DELETE FROM `history` WHERE `id` = ?", [id])
}

View File

@ -1,20 +0,0 @@
use sqlite::{Error, Transaction};
pub struct Table {
pub id: i64,
// pub app_id: i64,
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `identity`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`name` VARCHAR(255),
`crt` TEXT NOT NULL,
`key` TEXT NOT NULL
)",
[],
)
}

18
src/profile/history.rs Normal file
View File

@ -0,0 +1,18 @@
mod database;
use sqlite::Transaction;
// Tools
pub fn migrate(tx: &Transaction) -> Result<(), String> {
// Migrate self components
if let Err(e) = database::init(tx) {
return Err(e.to_string());
}
// Delegate migration to childs
// nothing yet..
// Success
Ok(())
}

View File

@ -0,0 +1,81 @@
use gtk::glib::DateTime;
use sqlite::{Error, Transaction};
pub struct Table {
pub id: i64,
pub profile_id: i64,
pub time: DateTime,
pub request: String,
}
pub struct History {
// nothing yet..
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `profile_history`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`profile_id` INTEGER NOT NULL,
`time` INTEGER NOT NULL,
`request` TEXT NOT NULL
)",
[],
)
}
pub fn add(
tx: &Transaction,
profile_id: &i64,
time: &DateTime,
request: &str,
) -> Result<usize, Error> {
tx.execute(
"INSERT INTO `history` (
`profile_id`,
`time`,
`request`
) VALUES (?, ?, ?)",
(profile_id, time.to_unix(), request),
)
}
pub fn records(
tx: &Transaction,
profile_id: &i64,
request: Option<&str>,
) -> Result<Vec<Table>, Error> {
let mut stmt = tx.prepare(
"SELECT `id`, `profile_id`, `time`, `request`
FROM `profile_history`
WHERE `profile_id` = ? AND `request` LIKE ?",
)?;
let filter = match request {
Some(value) => value,
None => "%",
};
let result = stmt.query_map((profile_id, filter), |row| {
Ok(Table {
id: row.get(0)?,
profile_id: row.get(1)?,
time: DateTime::from_unix_local(row.get(2)?).unwrap(),
request: row.get(3)?,
})
})?;
let mut records = Vec::new();
for record in result {
let table = record?;
records.push(table);
}
Ok(records)
}
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
tx.execute("DELETE FROM `profile_history` WHERE `id` = ?", [id])
}

18
src/profile/identity.rs Normal file
View File

@ -0,0 +1,18 @@
mod database;
use sqlite::Transaction;
// Tools
pub fn migrate(tx: &Transaction) -> Result<(), String> {
// Migrate self components
if let Err(e) = database::init(tx) {
return Err(e.to_string());
}
// Delegate migration to childs
// nothing yet..
// Success
Ok(())
}

View File

@ -0,0 +1,21 @@
use sqlite::{Error, Transaction};
pub struct Table {
pub id: i64,
//pub profile_id: i64,
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `profile_identity`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`profile_id` INTEGER NOT NULL,
`time` INTEGER NOT NULL,
`name` VARCHAR(255),
`certificate` TEXT NOT NULL,
`key` TEXT NOT NULL
)",
[],
)
}