mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-03-13 06:01:21 +00:00
use anyhow crate, return id on insert
This commit is contained in:
parent
e859b97d79
commit
5effd63575
@ -30,6 +30,7 @@ version = "0.9.1"
|
||||
|
||||
[dependencies]
|
||||
ansi-parser = "0.9.1"
|
||||
anyhow = "1.0.97"
|
||||
ggemini = "0.17.0"
|
||||
ggemtext = "0.3.1"
|
||||
indexmap = "2.7.0"
|
||||
|
10
src/app.rs
10
src/app.rs
@ -1,10 +1,10 @@
|
||||
pub mod browser;
|
||||
mod database;
|
||||
|
||||
use browser::Browser;
|
||||
|
||||
use crate::profile::Profile;
|
||||
use adw::Application;
|
||||
use anyhow::Result;
|
||||
use browser::Browser;
|
||||
use gtk::{
|
||||
glib::ExitCode,
|
||||
prelude::{ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt},
|
||||
@ -294,11 +294,9 @@ impl App {
|
||||
}
|
||||
|
||||
// Tools
|
||||
fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
browser::migrate(tx)?;
|
||||
|
@ -11,6 +11,7 @@ use window::Window;
|
||||
|
||||
use crate::Profile;
|
||||
use adw::{prelude::AdwDialogExt, AboutDialog, Application};
|
||||
use anyhow::Result;
|
||||
use gtk::{
|
||||
gio::{Cancellable, File},
|
||||
prelude::GtkWindowExt,
|
||||
@ -109,70 +110,43 @@ impl Browser {
|
||||
|
||||
// Actions
|
||||
|
||||
pub fn clean(&self, transaction: &Transaction, app_id: i64) -> Result<(), String> {
|
||||
match database::select(transaction, app_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
self.window.clean(transaction, record.id)?;
|
||||
self.widget.clean(transaction, record.id)?;
|
||||
|
||||
/* @TODO
|
||||
self.header.clean(transaction, &record.id)?; */
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn clean(&self, transaction: &Transaction, app_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_id)? {
|
||||
database::delete(transaction, record.id)?;
|
||||
// Delegate clean action to childs
|
||||
self.window.clean(transaction, record.id)?;
|
||||
self.widget.clean(transaction, record.id)?;
|
||||
/* @TODO
|
||||
self.header.clean(transaction, &record.id)?; */
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(&self, transaction: &Transaction, app_id: i64) -> Result<(), String> {
|
||||
match database::select(transaction, app_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Delegate restore action to childs
|
||||
self.widget.restore(transaction, record.id)?;
|
||||
self.window.restore(transaction, record.id)?;
|
||||
|
||||
/* @TODO
|
||||
self.header.restore(transaction, &record.id)?; */
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn restore(&self, transaction: &Transaction, app_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_id)? {
|
||||
// Delegate restore action to childs
|
||||
self.widget.restore(transaction, record.id)?;
|
||||
self.window.restore(transaction, record.id)?;
|
||||
/* @TODO
|
||||
self.header.restore(transaction, &record.id)?; */
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_id: i64) -> Result<(), String> {
|
||||
match database::insert(transaction, app_id) {
|
||||
Ok(_) => {
|
||||
let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
self.widget.save(transaction, id)?;
|
||||
self.window.save(transaction, id)?;
|
||||
|
||||
/* @TODO
|
||||
self.header.save(transaction, &id)?; */
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_id: i64) -> Result<()> {
|
||||
let id = database::insert(transaction, app_id)?;
|
||||
// Delegate save action to childs
|
||||
self.widget.save(transaction, id)?;
|
||||
self.window.save(transaction, id)?;
|
||||
/* @TODO
|
||||
self.header.save(transaction, &id)?; */
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init(&self, application: Option<&Application>) -> &Self {
|
||||
// Assign browser window to this application
|
||||
self.widget.application_window.set_application(application); // @TODO
|
||||
|
||||
// Init main window
|
||||
// Init main window
|
||||
self.window.init();
|
||||
self
|
||||
}
|
||||
@ -184,11 +158,9 @@ impl Browser {
|
||||
}
|
||||
|
||||
// Tools
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
/* @TODO
|
||||
|
@ -1,12 +1,13 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
// pub app_id: i64, not in use
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -15,14 +16,15 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_id`) REFERENCES `app`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_id: i64) -> Result<usize, Error> {
|
||||
tx.execute("INSERT INTO `app_browser` (`app_id`) VALUES (?)", [app_id])
|
||||
pub fn insert(tx: &Transaction, app_id: i64) -> Result<i64> {
|
||||
tx.execute("INSERT INTO `app_browser` (`app_id`) VALUES (?)", [app_id])?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare("SELECT `id`, `app_id` FROM `app_browser` WHERE `app_id` = ?")?;
|
||||
|
||||
let result = stmt.query_map([app_id], |row| {
|
||||
@ -42,10 +44,6 @@ pub fn select(tx: &Transaction, app_id: i64) -> Result<Vec<Table>, Error> {
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `app_browser` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ mod database;
|
||||
|
||||
use super::Window;
|
||||
use adw::ApplicationWindow;
|
||||
use anyhow::Result;
|
||||
use gtk::{
|
||||
gio::SimpleActionGroup,
|
||||
glib::GString,
|
||||
@ -59,74 +60,44 @@ impl Widget {
|
||||
}
|
||||
|
||||
// Actions
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
// nothing yet..
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_id)? {
|
||||
database::delete(transaction, record.id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Restore widget
|
||||
self.application_window.set_maximized(record.is_maximized);
|
||||
self.application_window
|
||||
.set_default_size(record.default_width, record.default_height);
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_id)? {
|
||||
// Restore widget
|
||||
self.application_window.set_maximized(record.is_maximized);
|
||||
self.application_window
|
||||
.set_default_size(record.default_width, record.default_height);
|
||||
|
||||
// Delegate restore action to childs
|
||||
// nothing yet..
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
// Delegate restore action to childs
|
||||
// nothing yet..
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::insert(
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> {
|
||||
database::insert(
|
||||
transaction,
|
||||
app_browser_id,
|
||||
self.application_window.default_width(),
|
||||
self.application_window.default_height(),
|
||||
self.application_window.is_maximized(),
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Delegate save action to childs
|
||||
// let id = self.database.last_insert_id(transaction);
|
||||
// nothing yet..
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Tools
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
|
||||
database::init(tx)?;
|
||||
// Delegate migration to childs
|
||||
// nothing yet..
|
||||
|
||||
// Success
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
@ -8,8 +9,8 @@ pub struct Table {
|
||||
pub is_maximized: bool,
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_widget`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -21,7 +22,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_id`) REFERENCES `app_browser`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
@ -30,7 +31,7 @@ pub fn insert(
|
||||
default_width: i32,
|
||||
default_height: i32,
|
||||
is_maximized: bool,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_widget` (
|
||||
`app_browser_id`,
|
||||
@ -44,10 +45,11 @@ pub fn insert(
|
||||
default_height as i64,
|
||||
is_maximized as i64,
|
||||
],
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_browser_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_browser_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_id`,
|
||||
@ -76,11 +78,6 @@ pub fn select(tx: &Transaction, app_browser_id: i64) -> Result<Vec<Table>, Error
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser_widget` WHERE `id` = ?", [id])
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `app_browser_widget` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
||||
/* not in use
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
} */
|
||||
|
@ -3,16 +3,16 @@ mod database;
|
||||
mod header;
|
||||
pub mod tab;
|
||||
|
||||
use action::{Action, Position};
|
||||
use adw::ToolbarView;
|
||||
use header::Header;
|
||||
use sqlite::Transaction;
|
||||
use tab::Tab;
|
||||
|
||||
use super::Action as BrowserAction;
|
||||
use crate::Profile;
|
||||
use action::{Action, Position};
|
||||
use adw::ToolbarView;
|
||||
use anyhow::Result;
|
||||
use gtk::{prelude::BoxExt, Box, Orientation};
|
||||
use header::Header;
|
||||
use sqlite::Transaction;
|
||||
use std::rc::Rc;
|
||||
use tab::Tab;
|
||||
|
||||
pub struct Window {
|
||||
pub action: Rc<Action>,
|
||||
@ -145,52 +145,26 @@ impl Window {
|
||||
self.tab.escape();
|
||||
}
|
||||
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
self.tab.clean(transaction, record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_id)? {
|
||||
database::delete(transaction, record.id)?;
|
||||
// Delegate clean action to childs
|
||||
self.tab.clean(transaction, record.id)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Delegate restore action to childs
|
||||
self.tab.restore(transaction, record.id)?;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_id)? {
|
||||
// Delegate restore action to childs
|
||||
self.tab.restore(transaction, record.id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::insert(transaction, app_browser_id) {
|
||||
Ok(_) => {
|
||||
// Delegate save action to childs
|
||||
if let Err(e) = self
|
||||
.tab
|
||||
.save(transaction, database::last_insert_id(transaction))
|
||||
{
|
||||
return Err(e.to_string());
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> {
|
||||
self.tab
|
||||
.save(transaction, database::insert(transaction, app_browser_id)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -200,11 +174,9 @@ impl Window {
|
||||
}
|
||||
|
||||
// Tools
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
tab::migrate(tx)?;
|
||||
|
@ -1,12 +1,13 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
// pub app_browser_id: i64, not in use
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -15,17 +16,18 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_id`) REFERENCES `app_browser`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_browser_id: i64) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, app_browser_id: i64) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window` (`app_browser_id`) VALUES (?)",
|
||||
[app_browser_id],
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_browser_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_browser_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_id` FROM `app_browser_window`
|
||||
@ -49,10 +51,6 @@ pub fn select(tx: &Transaction, app_browser_id: i64) -> Result<Vec<Table>, Error
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser_window` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `app_browser_window` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use super::{Action as WindowAction, BrowserAction, Position};
|
||||
use crate::Profile;
|
||||
use action::Action;
|
||||
use adw::{TabPage, TabView};
|
||||
use anyhow::Result;
|
||||
use error::Error;
|
||||
use gtk::{
|
||||
gio::Icon,
|
||||
@ -309,102 +310,68 @@ impl Tab {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
for (_, item) in self.index.borrow().iter() {
|
||||
item.clean(transaction, record.id)?
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_window_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_id)? {
|
||||
database::delete(transaction, record.id)?;
|
||||
// Delegate clean action to childs
|
||||
for (_, item) in self.index.borrow().iter() {
|
||||
item.clean(transaction, record.id)?
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_id) {
|
||||
Ok(tab_records) => {
|
||||
for tab_record in tab_records {
|
||||
for item_record in item::restore(transaction, tab_record.id)? {
|
||||
// Generate new `TabPage` with blank `Widget`
|
||||
let (tab_page, target_child) = new_tab_page(
|
||||
&self.tab_view,
|
||||
Position::Number(item_record.page_position),
|
||||
);
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_window_id: i64) -> Result<()> {
|
||||
for tab_record in database::select(transaction, app_browser_window_id)? {
|
||||
for item_record in item::restore(transaction, tab_record.id)? {
|
||||
// Generate new `TabPage` with blank `Widget`
|
||||
let (tab_page, target_child) =
|
||||
new_tab_page(&self.tab_view, Position::Number(item_record.page_position));
|
||||
|
||||
// Init new tab item
|
||||
let item = Rc::new(Item::build(
|
||||
(&tab_page, &target_child),
|
||||
&self.profile,
|
||||
// Actions
|
||||
(&self.browser_action, &self.window_action, &self.action),
|
||||
// Options
|
||||
None,
|
||||
false,
|
||||
));
|
||||
// Init new tab item
|
||||
let item = Rc::new(Item::build(
|
||||
(&tab_page, &target_child),
|
||||
&self.profile,
|
||||
// Actions
|
||||
(&self.browser_action, &self.window_action, &self.action),
|
||||
// Options
|
||||
None,
|
||||
false,
|
||||
));
|
||||
|
||||
// Relate with GTK `TabPage` with app `Item`
|
||||
self.index
|
||||
.borrow_mut()
|
||||
.insert(item.tab_page.clone(), item.clone());
|
||||
// Relate with GTK `TabPage` with app `Item`
|
||||
self.index
|
||||
.borrow_mut()
|
||||
.insert(item.tab_page.clone(), item.clone());
|
||||
|
||||
// Setup
|
||||
self.tab_view
|
||||
.set_page_pinned(&item.tab_page, item_record.is_pinned);
|
||||
// Setup
|
||||
self.tab_view
|
||||
.set_page_pinned(&item.tab_page, item_record.is_pinned);
|
||||
|
||||
if item_record.is_selected {
|
||||
self.tab_view.set_selected_page(&item.tab_page);
|
||||
}
|
||||
|
||||
// Forcefully update global actions on HashMap index build complete
|
||||
// * `selected_page_notify` runs this action also, just before Item init @TODO
|
||||
update_actions(
|
||||
&self.tab_view,
|
||||
self.tab_view.selected_page().as_ref(),
|
||||
&self.index,
|
||||
&self.window_action,
|
||||
);
|
||||
|
||||
// Restore children components
|
||||
item.page.restore(transaction, item_record.id)?;
|
||||
}
|
||||
if item_record.is_selected {
|
||||
self.tab_view.set_selected_page(&item.tab_page);
|
||||
}
|
||||
|
||||
// Forcefully update global actions on HashMap index build complete
|
||||
// * `selected_page_notify` runs this action also, just before Item init @TODO
|
||||
update_actions(
|
||||
&self.tab_view,
|
||||
self.tab_view.selected_page().as_ref(),
|
||||
&self.index,
|
||||
&self.window_action,
|
||||
);
|
||||
|
||||
// Restore children components
|
||||
item.page.restore(transaction, item_record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::insert(transaction, app_browser_window_id) {
|
||||
Ok(_) => {
|
||||
// Delegate save action to childs
|
||||
let id = database::last_insert_id(transaction);
|
||||
for (_, item) in self.index.borrow().iter() {
|
||||
item.save(transaction, id, self.tab_view.page_position(&item.tab_page))?;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_window_id: i64) -> Result<()> {
|
||||
let id = database::insert(transaction, app_browser_window_id)?;
|
||||
for (_, item) in self.index.borrow().iter() {
|
||||
item.save(transaction, id, self.tab_view.page_position(&item.tab_page))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -430,11 +397,9 @@ impl Tab {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
item::migrate(tx)?;
|
||||
|
@ -1,12 +1,13 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
// pub app_browser_window_id: i64, not in use
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window_tab`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -15,19 +16,20 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_window_id`) REFERENCES `app_browser_window`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_browser_window_id: i64) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, app_browser_window_id: i64) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab` (
|
||||
`app_browser_window_id`
|
||||
) VALUES (?)",
|
||||
[app_browser_window_id],
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_browser_window_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_browser_window_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_id` FROM `app_browser_window_tab`
|
||||
@ -51,10 +53,6 @@ pub fn select(tx: &Transaction, app_browser_window_id: i64) -> Result<Vec<Table>
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser_window_tab` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `app_browser_window_tab` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use super::{Action as TabAction, BrowserAction, WindowAction};
|
||||
use crate::Profile;
|
||||
use action::Action;
|
||||
use adw::TabPage;
|
||||
use anyhow::Result;
|
||||
use client::Client;
|
||||
use gtk::{
|
||||
prelude::{ActionExt, ActionMapExt, BoxExt},
|
||||
@ -164,26 +165,12 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
self.page.clean(transaction, record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_window_tab_id: i64) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_tab_id)? {
|
||||
database::delete(transaction, record.id)?;
|
||||
// Delegate clean action to the item childs
|
||||
self.page.clean(transaction, record.id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -192,32 +179,23 @@ impl Item {
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_id: i64,
|
||||
page_position: i32,
|
||||
) -> Result<(), String> {
|
||||
match database::insert(
|
||||
) -> Result<()> {
|
||||
let id = database::insert(
|
||||
transaction,
|
||||
app_browser_window_tab_id,
|
||||
page_position,
|
||||
self.tab_page.is_pinned(),
|
||||
self.tab_page.is_selected(),
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Delegate save action to childs
|
||||
let id = database::last_insert_id(transaction);
|
||||
self.page.save(transaction, id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
)?;
|
||||
self.page.save(transaction, id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Tools
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
page::migrate(tx)?;
|
||||
@ -231,9 +209,6 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn restore(
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_id: i64,
|
||||
) -> Result<Vec<database::Table>, String> {
|
||||
match database::select(transaction, app_browser_window_tab_id) {
|
||||
Ok(records) => Ok(records),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
) -> Result<Vec<database::Table>> {
|
||||
database::select(transaction, app_browser_window_tab_id)
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
@ -8,8 +9,8 @@ pub struct Table {
|
||||
pub is_selected: bool,
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -21,7 +22,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_window_tab_id`) REFERENCES `app_browser_window_tab` (`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
@ -30,7 +31,7 @@ pub fn insert(
|
||||
page_position: i32,
|
||||
is_pinned: bool,
|
||||
is_selected: bool,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item` (
|
||||
`app_browser_window_tab_id`,
|
||||
@ -44,10 +45,11 @@ pub fn insert(
|
||||
is_pinned as i64,
|
||||
is_selected as i64,
|
||||
],
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_browser_window_tab_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_browser_window_tab_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_id`,
|
||||
@ -79,13 +81,9 @@ pub fn select(tx: &Transaction, app_browser_window_tab_id: i64) -> Result<Vec<Ta
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item` WHERE `id` = ?",
|
||||
[id],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
)?)
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ mod search;
|
||||
|
||||
use super::{Action as ItemAction, BrowserAction, Profile, TabAction, WindowAction};
|
||||
use adw::TabPage;
|
||||
use anyhow::Result;
|
||||
use content::Content;
|
||||
use error::Error;
|
||||
use input::Input;
|
||||
@ -104,20 +105,11 @@ impl Page {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_item_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
self.navigation.clean(transaction, &record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_tab_item_id)? {
|
||||
database::delete(transaction, record.id)?;
|
||||
// Delegate clean action to the item childs
|
||||
self.navigation.clean(transaction, &record.id)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -127,25 +119,20 @@ impl Page {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<()> {
|
||||
// Begin page restore
|
||||
match database::select(transaction, app_browser_window_tab_item_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Restore `Self`
|
||||
if let Some(title) = record.title {
|
||||
self.set_title(title.as_str());
|
||||
}
|
||||
self.set_needs_attention(record.is_needs_attention);
|
||||
// Restore child components
|
||||
self.navigation.restore(transaction, &record.id)?;
|
||||
// Make initial page history snap using `navigation` values restored
|
||||
if let Some(uri) = self.navigation.uri() {
|
||||
self.profile.history.memory.request.set(uri);
|
||||
}
|
||||
}
|
||||
for record in database::select(transaction, app_browser_window_tab_item_id)? {
|
||||
// Restore `Self`
|
||||
if let Some(title) = record.title {
|
||||
self.set_title(title.as_str());
|
||||
}
|
||||
self.set_needs_attention(record.is_needs_attention);
|
||||
// Restore child components
|
||||
self.navigation.restore(transaction, &record.id)?;
|
||||
// Make initial page history snap using `navigation` values restored
|
||||
if let Some(uri) = self.navigation.uri() {
|
||||
self.profile.history.memory.request.set(uri);
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -155,10 +142,10 @@ impl Page {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<()> {
|
||||
// Keep value in memory until operation complete
|
||||
let title = self.tab_page.title();
|
||||
match database::insert(
|
||||
let id = database::insert(
|
||||
transaction,
|
||||
app_browser_window_tab_item_id,
|
||||
self.tab_page.needs_attention(),
|
||||
@ -166,15 +153,9 @@ impl Page {
|
||||
true => None,
|
||||
false => Some(title.as_str()),
|
||||
},
|
||||
) {
|
||||
Ok(_) => {
|
||||
let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
self.navigation.save(transaction, &id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
)?;
|
||||
// Delegate save action to childs
|
||||
self.navigation.save(transaction, &id)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -198,11 +179,9 @@ impl Page {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
navigation::migrate(tx)?;
|
||||
|
@ -1,4 +1,5 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
@ -7,8 +8,8 @@ pub struct Table {
|
||||
pub title: Option<String>,
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -19,7 +20,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_window_tab_item_id`) REFERENCES `app_browser_window_tab_item` (`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
@ -27,7 +28,7 @@ pub fn insert(
|
||||
app_browser_window_tab_item_id: i64,
|
||||
is_needs_attention: bool,
|
||||
title: Option<&str>,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item_page` (
|
||||
`app_browser_window_tab_item_id`,
|
||||
@ -35,10 +36,11 @@ pub fn insert(
|
||||
`title`
|
||||
) VALUES (?, ?, ?)",
|
||||
(app_browser_window_tab_item_id, is_needs_attention, title),
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_browser_window_tab_item_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_browser_window_tab_item_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_item_id`,
|
||||
@ -67,13 +69,9 @@ pub fn select(tx: &Transaction, app_browser_window_tab_item_id: i64) -> Result<V
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item_page` WHERE `id` = ?",
|
||||
[id],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
)?)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ mod reload;
|
||||
mod request;
|
||||
|
||||
use super::{ItemAction, Profile, TabAction, WindowAction};
|
||||
use anyhow::Result;
|
||||
use bookmark::Bookmark;
|
||||
use gtk::{
|
||||
glib::{GString, Uri},
|
||||
@ -72,22 +73,12 @@ impl Navigation {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_item_page_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, &record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
self.request.clean(transaction, &record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_tab_item_page_id)? {
|
||||
database::delete(transaction, &record.id)?;
|
||||
// Delegate clean action to the item childs
|
||||
self.request.clean(transaction, &record.id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -95,17 +86,11 @@ impl Navigation {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_item_page_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Delegate restore action to the item childs
|
||||
self.request.restore(transaction, &record.id)?;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_tab_item_page_id)? {
|
||||
// Delegate restore action to the item childs
|
||||
self.request.restore(transaction, &record.id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -113,17 +98,10 @@ impl Navigation {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::insert(transaction, app_browser_window_tab_item_page_id) {
|
||||
Ok(_) => {
|
||||
let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
self.request.save(transaction, &id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
) -> Result<()> {
|
||||
let id = database::insert(transaction, app_browser_window_tab_item_page_id)?;
|
||||
// Delegate save action to childs
|
||||
self.request.save(transaction, &id)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -173,11 +151,9 @@ impl Navigation {
|
||||
}
|
||||
|
||||
// Tools
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
request::migrate(tx)?;
|
||||
|
@ -48,7 +48,7 @@ impl Bookmark for Button {
|
||||
}
|
||||
|
||||
fn update(&self, profile: &Profile, request: &Entry) {
|
||||
let has_bookmark = profile.bookmark.get(&request.text()).is_ok();
|
||||
let has_bookmark = profile.bookmark.get(&request.text()).is_some();
|
||||
self.set_icon_name(icon_name(has_bookmark));
|
||||
self.set_tooltip_text(Some(tooltip_text(has_bookmark)));
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
// pub app_browser_window_tab_item_page_id: i64, not in use
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page_navigation`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -15,22 +16,20 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_window_tab_item_page_id`) REFERENCES `app_browser_window_tab_item_page`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_browser_window_tab_item_page_id: &i64) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, app_browser_window_tab_item_page_id: &i64) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item_page_navigation` (
|
||||
`app_browser_window_tab_item_page_id`
|
||||
) VALUES (?)",
|
||||
[app_browser_window_tab_item_page_id],
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_item_page_id: &i64,
|
||||
) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_browser_window_tab_item_page_id: &i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_item_page_id`
|
||||
@ -55,13 +54,9 @@ pub fn select(
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item_page_navigation` WHERE `id` = ?",
|
||||
[id],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
)?)
|
||||
}
|
||||
|
@ -3,15 +3,15 @@ mod identity;
|
||||
mod primary_icon;
|
||||
mod search;
|
||||
|
||||
use adw::{prelude::AdwDialogExt, AlertDialog};
|
||||
use primary_icon::PrimaryIcon;
|
||||
|
||||
use super::{ItemAction, Profile};
|
||||
use adw::{prelude::AdwDialogExt, AlertDialog};
|
||||
use anyhow::Result;
|
||||
use gtk::{
|
||||
glib::{gformat, GString, Uri, UriFlags},
|
||||
prelude::{EditableExt, EntryExt, WidgetExt},
|
||||
Entry, EntryIconPosition, StateFlags,
|
||||
};
|
||||
use primary_icon::PrimaryIcon;
|
||||
use sqlite::Transaction;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
@ -29,19 +29,19 @@ pub trait Request {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<(), String>;
|
||||
) -> Result<()>;
|
||||
|
||||
fn restore(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<(), String>;
|
||||
) -> Result<()>;
|
||||
|
||||
fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<(), String>;
|
||||
) -> Result<()>;
|
||||
|
||||
fn update_primary_icon(&self, profile: &Profile);
|
||||
fn update_secondary_icon(&self);
|
||||
@ -147,22 +147,13 @@ impl Request for Entry {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_item_page_navigation_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
match database::delete(transaction, &record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
// nothing yet..
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_tab_item_page_navigation_id)?
|
||||
{
|
||||
database::delete(transaction, &record.id)?;
|
||||
// Delegate clean action to the item childs
|
||||
// nothing yet..
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -170,21 +161,15 @@ impl Request for Entry {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_item_page_navigation_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
if let Some(text) = record.text {
|
||||
self.set_text(&text);
|
||||
}
|
||||
|
||||
// Delegate restore action to the item childs
|
||||
// nothing yet..
|
||||
}
|
||||
) -> Result<()> {
|
||||
for record in database::select(transaction, app_browser_window_tab_item_page_navigation_id)?
|
||||
{
|
||||
if let Some(text) = record.text {
|
||||
self.set_text(&text);
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
// Delegate restore action to the item childs
|
||||
// nothing yet..
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -192,27 +177,19 @@ impl Request for Entry {
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<()> {
|
||||
// Keep value in memory until operation complete
|
||||
let text = self.text();
|
||||
|
||||
match database::insert(
|
||||
let _id = database::insert(
|
||||
transaction,
|
||||
app_browser_window_tab_item_page_navigation_id,
|
||||
match text.is_empty() {
|
||||
true => None,
|
||||
false => Some(text.as_str()),
|
||||
},
|
||||
) {
|
||||
Ok(_) => {
|
||||
// let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
// nothing yet..
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
)?;
|
||||
// Delegate save action to childs
|
||||
// nothing yet..
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -369,11 +346,9 @@ impl Request for Entry {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
// nothing yet..
|
||||
|
@ -1,4 +1,5 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
@ -6,8 +7,8 @@ pub struct Table {
|
||||
pub text: Option<String>, // can be stored as NULL
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok( tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page_navigation_request`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -17,27 +18,28 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`app_browser_window_tab_item_page_navigation_id`) REFERENCES `app_browser_window_tab_item_page_navigation`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
text: Option<&str>,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item_page_navigation_request` (
|
||||
`app_browser_window_tab_item_page_navigation_id`,
|
||||
`text`
|
||||
) VALUES (?, ?)",
|
||||
(app_browser_window_tab_item_page_navigation_id, text),
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_item_page_navigation_id: &i64,
|
||||
) -> Result<Vec<Table>, Error> {
|
||||
) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_item_page_navigation_id`,
|
||||
@ -64,14 +66,9 @@ pub fn select(
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item_page_navigation_request` WHERE `id` = ?",
|
||||
[id],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
/* not in use
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
} */
|
||||
|
@ -9,7 +9,7 @@ use std::rc::Rc;
|
||||
|
||||
fn main() -> ExitCode {
|
||||
match gtk::init() {
|
||||
Ok(_) => App::build(&Rc::new(Profile::new())).run(),
|
||||
Ok(_) => App::build(&Rc::new(Profile::new().unwrap())).run(),
|
||||
Err(_) => ExitCode::FAILURE,
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use history::History;
|
||||
use identity::Identity;
|
||||
use search::Search;
|
||||
|
||||
use anyhow::Result;
|
||||
use gtk::glib::{user_config_dir, DateTime};
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{fs::create_dir_all, path::PathBuf, rc::Rc, sync::RwLock};
|
||||
@ -29,16 +30,10 @@ pub struct Profile {
|
||||
pub config_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for Profile {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
// Constructors
|
||||
|
||||
pub fn new() -> Self {
|
||||
pub fn new() -> Result<Self> {
|
||||
// Init profile path
|
||||
let mut config_path = user_config_dir();
|
||||
|
||||
@ -51,44 +46,26 @@ impl Profile {
|
||||
env!("CARGO_PKG_VERSION_MINOR")
|
||||
)); // @TODO remove after auto-migrate feature implementation
|
||||
|
||||
if let Err(e) = create_dir_all(&config_path) {
|
||||
panic!("{e}")
|
||||
}
|
||||
create_dir_all(&config_path)?;
|
||||
|
||||
// Init database path
|
||||
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(e) => panic!("{e}"),
|
||||
};
|
||||
let connection = Rc::new(RwLock::new(Connection::open(database_path.as_path())?));
|
||||
|
||||
// Init profile components
|
||||
{
|
||||
// Init writable connection
|
||||
let mut connection = match connection.write() {
|
||||
Ok(connection) => connection,
|
||||
Err(e) => todo!("{e}"),
|
||||
};
|
||||
let mut connection = connection.write().unwrap(); // @TODO handle
|
||||
|
||||
// Init new transaction
|
||||
let transaction = match connection.transaction() {
|
||||
Ok(transaction) => transaction,
|
||||
Err(e) => todo!("{e}"),
|
||||
};
|
||||
let transaction = connection.transaction()?;
|
||||
|
||||
// Begin migration
|
||||
match migrate(&transaction) {
|
||||
Ok(_) => {
|
||||
// Confirm changes
|
||||
if let Err(e) = transaction.commit() {
|
||||
todo!("{e}")
|
||||
}
|
||||
}
|
||||
Err(e) => todo!("{e}"),
|
||||
}
|
||||
migrate(&transaction)?;
|
||||
transaction.commit()?;
|
||||
} // unlock database
|
||||
|
||||
// Init model
|
||||
@ -104,7 +81,7 @@ impl Profile {
|
||||
});
|
||||
|
||||
// Init components
|
||||
let bookmark = Rc::new(Bookmark::build(&connection, &profile_id));
|
||||
let bookmark = Rc::new(Bookmark::build(&connection, &profile_id)?);
|
||||
let history = Rc::new(History::build(&connection, &profile_id));
|
||||
let search = Rc::new(Search::build(&connection, &profile_id).unwrap()); // @TODO handle
|
||||
let identity = Rc::new(match Identity::build(&connection, &profile_id) {
|
||||
@ -113,22 +90,20 @@ impl Profile {
|
||||
});
|
||||
|
||||
// Result
|
||||
Self {
|
||||
Ok(Self {
|
||||
bookmark,
|
||||
database,
|
||||
history,
|
||||
identity,
|
||||
search,
|
||||
config_path,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to children components
|
||||
bookmark::migrate(tx)?;
|
||||
|
@ -1,12 +1,10 @@
|
||||
mod database;
|
||||
mod error;
|
||||
mod memory;
|
||||
|
||||
use anyhow::Result;
|
||||
use database::Database;
|
||||
use error::Error;
|
||||
use memory::Memory;
|
||||
|
||||
use gtk::glib::DateTime;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
@ -19,48 +17,38 @@ impl Bookmark {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: &Rc<i64>) -> Self {
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: &Rc<i64>) -> Result<Self> {
|
||||
// Init children components
|
||||
let database = Rc::new(Database::new(connection, profile_id));
|
||||
let memory = Rc::new(Memory::new());
|
||||
|
||||
// Build initial index
|
||||
match database.records(None) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
if let Err(e) = memory.add(record.request, record.id) {
|
||||
todo!("{}", e.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => todo!("{}", e.to_string()),
|
||||
for record in database.records(None)? {
|
||||
memory.add(record.request, record.id)?;
|
||||
}
|
||||
|
||||
// Return new `Self`
|
||||
Self { database, memory }
|
||||
Ok(Self { database, memory })
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Get record `id` by `request` from memory index
|
||||
pub fn get(&self, request: &str) -> Result<i64, Error> {
|
||||
match self.memory.get(request) {
|
||||
Ok(id) => Ok(id),
|
||||
Err(_) => Err(Error::MemoryNotFound),
|
||||
}
|
||||
pub fn get(&self, request: &str) -> Option<i64> {
|
||||
self.memory.get(request)
|
||||
}
|
||||
|
||||
/// Toggle record in `database` and `memory` index
|
||||
/// * return `true` on bookmark created, `false` on deleted
|
||||
pub fn toggle(&self, request: &str) -> Result<bool, Error> {
|
||||
pub fn toggle(&self, request: &str) -> Result<bool> {
|
||||
// Delete record if exists
|
||||
if let Ok(id) = self.get(request) {
|
||||
if let Some(id) = self.get(request) {
|
||||
match self.database.delete(id) {
|
||||
Ok(_) => match self.memory.delete(request) {
|
||||
Ok(_) => Ok(false),
|
||||
Err(_) => Err(Error::MemoryDelete),
|
||||
Err(_) => panic!(), // unexpected
|
||||
},
|
||||
Err(_) => Err(Error::DatabaseDelete),
|
||||
Err(_) => panic!(), // unexpected
|
||||
}
|
||||
// Otherwise, create new record
|
||||
} else {
|
||||
@ -70,9 +58,9 @@ impl Bookmark {
|
||||
{
|
||||
Ok(id) => match self.memory.add(request.into(), id) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(_) => Err(Error::MemoryAdd),
|
||||
Err(_) => panic!(), // unexpected
|
||||
},
|
||||
Err(_) => Err(Error::DatabaseAdd),
|
||||
Err(_) => panic!(), // unexpected
|
||||
}
|
||||
} // @TODO return affected rows on success?
|
||||
}
|
||||
@ -80,11 +68,9 @@ impl Bookmark {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
// nothing yet..
|
||||
|
@ -1,5 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use gtk::glib::DateTime;
|
||||
use sqlite::{Connection, Error, Transaction};
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
pub struct Table {
|
||||
@ -28,7 +29,7 @@ impl Database {
|
||||
// Getters
|
||||
|
||||
/// Get bookmark records from database with optional filter by `request`
|
||||
pub fn records(&self, request: Option<&str>) -> Result<Vec<Table>, Error> {
|
||||
pub fn records(&self, request: Option<&str>) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx, *self.profile_id, request)
|
||||
@ -38,45 +39,28 @@ impl Database {
|
||||
|
||||
/// Create new bookmark record in database
|
||||
/// * return last insert ID on success
|
||||
pub fn add(&self, time: DateTime, request: String) -> Result<i64, Error> {
|
||||
// Begin new transaction
|
||||
pub fn add(&self, time: DateTime, request: String) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
// Create new record
|
||||
insert(&tx, *self.profile_id, time, request)?;
|
||||
|
||||
// Hold insert ID for result
|
||||
let id = last_insert_id(&tx);
|
||||
|
||||
// Done
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(id),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
let id = insert(&tx, *self.profile_id, time, request)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Delete bookmark record from database
|
||||
pub fn delete(&self, id: i64) -> Result<(), Error> {
|
||||
// Begin new transaction
|
||||
pub fn delete(&self, id: i64) -> Result<usize> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
// Delete record by ID
|
||||
match delete(&tx, id) {
|
||||
Ok(_) => match tx.commit() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
let usize = delete(&tx, id)?;
|
||||
tx.commit()?;
|
||||
Ok(usize)
|
||||
}
|
||||
}
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_bookmark`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -87,15 +71,10 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`profile_id`) REFERENCES `profile`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
profile_id: i64,
|
||||
time: DateTime,
|
||||
request: String,
|
||||
) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, profile_id: i64, time: DateTime, request: String) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `profile_bookmark` (
|
||||
`profile_id`,
|
||||
@ -103,14 +82,11 @@ pub fn insert(
|
||||
`request`
|
||||
) VALUES (?, ?, ?)",
|
||||
(profile_id, time.to_unix(), request),
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn select(
|
||||
tx: &Transaction,
|
||||
profile_id: i64,
|
||||
request: Option<&str>,
|
||||
) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, profile_id: i64, request: Option<&str>) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`, `profile_id`, `time`, `request`
|
||||
FROM `profile_bookmark`
|
||||
@ -136,10 +112,6 @@ pub fn select(
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `profile_bookmark` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `profile_bookmark` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
DatabaseAdd,
|
||||
DatabaseDelete,
|
||||
MemoryAdd,
|
||||
MemoryDelete,
|
||||
MemoryNotFound,
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
mod error;
|
||||
use error::Error;
|
||||
|
||||
use anyhow::Result;
|
||||
use itertools::Itertools;
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
|
||||
@ -29,37 +27,34 @@ impl Memory {
|
||||
|
||||
/// Add new record with `request` as key and `id` as value
|
||||
/// * validate record with same key does not exist yet
|
||||
pub fn add(&self, request: String, id: i64) -> Result<(), Error> {
|
||||
pub fn add(&self, request: String, id: i64) -> Result<()> {
|
||||
// Borrow shared index access
|
||||
let mut index = self.index.borrow_mut();
|
||||
|
||||
// Prevent existing key overwrite
|
||||
if index.contains_key(&request) {
|
||||
return Err(Error::Overwrite(request));
|
||||
panic!() // unexpected
|
||||
}
|
||||
|
||||
// Slot should be free, let check it twice
|
||||
match index.insert(request, id) {
|
||||
Some(_) => Err(Error::Unexpected),
|
||||
Some(_) => panic!(), // unexpected
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete record from index by `request`
|
||||
/// * validate record key is exist
|
||||
pub fn delete(&self, request: &str) -> Result<(), Error> {
|
||||
pub fn delete(&self, request: &str) -> Result<()> {
|
||||
match self.index.borrow_mut().remove(request) {
|
||||
Some(_) => Ok(()),
|
||||
None => Err(Error::Unexpected), // @TODO
|
||||
None => panic!(), // unexpected
|
||||
}
|
||||
}
|
||||
|
||||
/// Get `id` by `request` from memory index
|
||||
pub fn get(&self, request: &str) -> Result<i64, Error> {
|
||||
match self.index.borrow().get(request) {
|
||||
Some(&value) => Ok(value),
|
||||
None => Err(Error::Unexpected), // @TODO
|
||||
}
|
||||
pub fn get(&self, request: &str) -> Option<i64> {
|
||||
self.index.borrow().get(request).copied()
|
||||
}
|
||||
|
||||
/// Get recent requests vector sorted by `ID` DESC
|
||||
|
@ -1,18 +0,0 @@
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Overwrite(String),
|
||||
Unexpected,
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Overwrite(key) => {
|
||||
write!(f, "Overwrite attempt for existing record `{key}`")
|
||||
}
|
||||
Self::Unexpected => write!(f, "Unexpected error"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use gtk::glib::DateTime;
|
||||
use sqlite::{Connection, Error, Transaction};
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
pub struct Table {
|
||||
@ -26,14 +27,14 @@ impl Database {
|
||||
// Getters
|
||||
|
||||
/// Get all records
|
||||
pub fn records(&self) -> Result<Vec<Table>, Error> {
|
||||
pub fn records(&self) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap();
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx)
|
||||
}
|
||||
|
||||
/// Get active profile record if exist
|
||||
pub fn active(&self) -> Result<Option<Table>, Error> {
|
||||
pub fn active(&self) -> Result<Option<Table>> {
|
||||
let records = self.records()?;
|
||||
Ok(records.into_iter().find(|record| record.is_active))
|
||||
}
|
||||
@ -41,36 +42,24 @@ impl Database {
|
||||
// Setters
|
||||
|
||||
/// Create new record in `Self` database connected
|
||||
pub fn add(&self, is_active: bool, time: DateTime, name: Option<String>) -> Result<i64, Error> {
|
||||
// Begin new transaction
|
||||
pub fn add(&self, is_active: bool, time: DateTime, name: Option<String>) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap();
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
// New record has active status
|
||||
if is_active {
|
||||
// Deactivate other records as only one profile should be active
|
||||
for record in select(&tx)? {
|
||||
update(&tx, record.id, false, record.time, record.name)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new record
|
||||
insert(&tx, is_active, time, name)?;
|
||||
|
||||
// Hold insert ID for result
|
||||
let id = last_insert_id(&tx);
|
||||
|
||||
// Done
|
||||
let id = insert(&tx, is_active, time, name)?;
|
||||
tx.commit()?;
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -79,7 +68,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
`name` VARCHAR(255)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
@ -87,7 +76,7 @@ pub fn insert(
|
||||
is_active: bool,
|
||||
time: DateTime,
|
||||
name: Option<String>,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `profile` (
|
||||
`is_active`,
|
||||
@ -95,7 +84,8 @@ pub fn insert(
|
||||
`name`
|
||||
) VALUES (?, ?, ?)",
|
||||
(is_active, time.to_unix(), name),
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
@ -104,14 +94,14 @@ pub fn update(
|
||||
is_active: bool,
|
||||
time: DateTime,
|
||||
name: Option<String>,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"UPDATE `profile` SET `is_active` = ?, `time` = ?, `name` = ? WHERE `id` = ?",
|
||||
(is_active, time.to_unix(), name, id),
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare("SELECT `id`, `is_active`, `time`, `name` FROM `profile`")?;
|
||||
let result = stmt.query_map([], |row| {
|
||||
Ok(Table {
|
||||
@ -131,7 +121,3 @@ pub fn select(tx: &Transaction) -> Result<Vec<Table>, Error> {
|
||||
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
}
|
||||
|
@ -1,80 +0,0 @@
|
||||
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 Database {
|
||||
// nothing yet..
|
||||
}
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
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,
|
||||
|
||||
FOREIGN KEY (`profile_id`) REFERENCES `profile`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
profile_id: i64,
|
||||
time: DateTime,
|
||||
request: String,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `history` (
|
||||
`profile_id`,
|
||||
`time`,
|
||||
`request`
|
||||
) VALUES (?, ?, ?)",
|
||||
(profile_id, time.to_unix(), request),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn select(
|
||||
tx: &Transaction,
|
||||
profile_id: i64,
|
||||
request: Option<String>,
|
||||
) -> 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 result = stmt.query_map((profile_id, request.unwrap_or("%".to_string())), |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])
|
||||
}
|
@ -1,18 +1,15 @@
|
||||
mod auth;
|
||||
mod certificate;
|
||||
mod database;
|
||||
mod error;
|
||||
mod item;
|
||||
mod memory;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use auth::Auth;
|
||||
use database::Database;
|
||||
pub use error::Error;
|
||||
use item::Item;
|
||||
|
||||
use memory::Memory;
|
||||
|
||||
use gtk::glib::DateTime;
|
||||
use item::Item;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
@ -32,11 +29,11 @@ impl Identity {
|
||||
pub fn build(
|
||||
connection: &Rc<RwLock<Connection>>,
|
||||
profile_identity_id: &Rc<i64>,
|
||||
) -> Result<Self, Error> {
|
||||
) -> Result<Self> {
|
||||
// Init components
|
||||
let auth = match Auth::build(connection) {
|
||||
Ok(auth) => Rc::new(auth),
|
||||
Err(e) => return Err(Error::Auth(e)),
|
||||
Err(e) => bail!("Could not create auth: {e}"),
|
||||
};
|
||||
let database = Rc::new(Database::build(connection, profile_identity_id));
|
||||
let memory = Rc::new(Memory::new());
|
||||
@ -58,33 +55,23 @@ impl Identity {
|
||||
|
||||
/// Add new record to database, update memory index
|
||||
/// * return new `profile_identity_id` on success
|
||||
pub fn add(&self, pem: &str) -> Result<i64, Error> {
|
||||
match self.database.add(pem) {
|
||||
Ok(profile_identity_id) => {
|
||||
self.index()?;
|
||||
Ok(profile_identity_id)
|
||||
}
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
}
|
||||
pub fn add(&self, pem: &str) -> Result<i64> {
|
||||
let profile_identity_id = self.database.add(pem)?;
|
||||
self.index()?;
|
||||
Ok(profile_identity_id)
|
||||
}
|
||||
|
||||
/// Delete record from database including children dependencies, update memory index
|
||||
pub fn delete(&self, profile_identity_id: i64) -> Result<(), Error> {
|
||||
match self.auth.remove_ref(profile_identity_id) {
|
||||
Ok(_) => match self.database.delete(profile_identity_id) {
|
||||
Ok(_) => {
|
||||
self.index()?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
},
|
||||
Err(e) => Err(Error::Auth(e)),
|
||||
}
|
||||
pub fn delete(&self, profile_identity_id: i64) -> Result<()> {
|
||||
self.auth.remove_ref(profile_identity_id)?;
|
||||
self.database.delete(profile_identity_id)?;
|
||||
self.index()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate new certificate and insert record to DB, update memory index
|
||||
/// * return new `profile_identity_id` on success
|
||||
pub fn make(&self, time: Option<(DateTime, DateTime)>, name: &str) -> Result<i64, Error> {
|
||||
pub fn make(&self, time: Option<(DateTime, DateTime)>, name: &str) -> Result<i64> {
|
||||
// Generate new certificate
|
||||
match certificate::generate(
|
||||
match time {
|
||||
@ -97,29 +84,17 @@ impl Identity {
|
||||
name,
|
||||
) {
|
||||
Ok(pem) => self.add(&pem),
|
||||
Err(e) => Err(Error::Certificate(e)),
|
||||
Err(e) => bail!("Could not create certificate: {e}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new `Memory` index from `Database` for `Self`
|
||||
pub fn index(&self) -> Result<(), Error> {
|
||||
pub fn index(&self) -> Result<()> {
|
||||
// Clear previous records
|
||||
if let Err(e) = self.memory.clear() {
|
||||
return Err(Error::Memory(e));
|
||||
self.memory.clear()?;
|
||||
for record in self.database.records()? {
|
||||
self.memory.add(record.id, record.pem)?;
|
||||
}
|
||||
|
||||
// Build new index
|
||||
match self.database.records() {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
if let Err(e) = self.memory.add(record.id, record.pem) {
|
||||
return Err(Error::Memory(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(Error::Database(e)),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -144,11 +119,9 @@ impl Identity {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
auth::migrate(tx)?;
|
||||
|
@ -1,13 +1,11 @@
|
||||
//! Controller for children `database` and `memory` components
|
||||
|
||||
mod database;
|
||||
mod error;
|
||||
mod memory;
|
||||
|
||||
use anyhow::Result;
|
||||
use database::Database;
|
||||
pub use error::Error;
|
||||
use memory::Memory;
|
||||
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
@ -21,7 +19,7 @@ impl Auth {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>) -> Result<Self, Error> {
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>) -> Result<Self> {
|
||||
// Init `Self`
|
||||
let this = Self {
|
||||
database: Rc::new(Database::build(connection)),
|
||||
@ -41,18 +39,14 @@ impl Auth {
|
||||
/// * deactivate active auth by remove previous records from `Self` database
|
||||
/// * reindex `Self` memory index on success
|
||||
/// * return last insert `profile_identity_auth_id` on success
|
||||
pub fn apply(&self, profile_identity_id: i64, request: &str) -> Result<i64, Error> {
|
||||
pub fn apply(&self, profile_identity_id: i64, request: &str) -> Result<i64> {
|
||||
// Cleanup records match `scope` (unauthorize)
|
||||
self.remove(request)?;
|
||||
|
||||
// Create new record (auth)
|
||||
let profile_identity_auth_id = match self
|
||||
let profile_identity_auth_id = self
|
||||
.database
|
||||
.add(profile_identity_id, &filter_scope(request))
|
||||
{
|
||||
Ok(id) => id,
|
||||
Err(e) => return Err(Error::Database(e)),
|
||||
};
|
||||
.add(profile_identity_id, &filter_scope(request))?;
|
||||
|
||||
// Reindex
|
||||
self.index()?;
|
||||
@ -62,56 +56,31 @@ impl Auth {
|
||||
}
|
||||
|
||||
/// Remove all records match request (unauthorize)
|
||||
pub fn remove(&self, request: &str) -> Result<(), Error> {
|
||||
match self.database.records_scope(Some(&filter_scope(request))) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
if let Err(e) = self.database.delete(record.id) {
|
||||
return Err(Error::Database(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(Error::Database(e)),
|
||||
pub fn remove(&self, request: &str) -> Result<()> {
|
||||
for record in self.database.records_scope(Some(&filter_scope(request)))? {
|
||||
self.database.delete(record.id)?;
|
||||
}
|
||||
self.index()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove all records match `profile_identity_id` foreign reference key
|
||||
pub fn remove_ref(&self, profile_identity_id: i64) -> Result<(), Error> {
|
||||
match self.database.records_ref(profile_identity_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
if let Err(e) = self.database.delete(record.id) {
|
||||
return Err(Error::Database(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(Error::Database(e)),
|
||||
pub fn remove_ref(&self, profile_identity_id: i64) -> Result<()> {
|
||||
for record in self.database.records_ref(profile_identity_id)? {
|
||||
self.database.delete(record.id)?;
|
||||
}
|
||||
self.index()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create new `Memory` index from `Database` for `Self`
|
||||
pub fn index(&self) -> Result<(), Error> {
|
||||
pub fn index(&self) -> Result<()> {
|
||||
// Clear previous records
|
||||
if let Err(e) = self.memory.clear() {
|
||||
return Err(Error::Memory(e));
|
||||
}
|
||||
|
||||
self.memory.clear()?;
|
||||
// Build new index
|
||||
match self.database.records_scope(None) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
if let Err(e) = self.memory.add(record.scope, record.profile_identity_id) {
|
||||
return Err(Error::Memory(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(Error::Database(e)),
|
||||
for record in self.database.records_scope(None)? {
|
||||
self.memory.add(record.scope, record.profile_identity_id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -154,11 +123,9 @@ impl Auth {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
// nothing yet..
|
||||
|
@ -1,4 +1,5 @@
|
||||
use sqlite::{Connection, Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
pub struct Table {
|
||||
@ -25,51 +26,34 @@ impl Database {
|
||||
// Actions
|
||||
|
||||
/// Create new record in database
|
||||
pub fn add(&self, profile_identity_id: i64, scope: &str) -> Result<i64, Error> {
|
||||
// Begin new transaction
|
||||
pub fn add(&self, profile_identity_id: i64, scope: &str) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
// Create new record
|
||||
insert(&tx, profile_identity_id, scope)?;
|
||||
|
||||
// Hold insert ID for result
|
||||
let id = last_insert_id(&tx);
|
||||
|
||||
// Done
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(id),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
let id = insert(&tx, profile_identity_id, scope)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Delete record with given `id` from database
|
||||
pub fn delete(&self, id: i64) -> Result<(), Error> {
|
||||
// Begin new transaction
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
// Create new record
|
||||
delete(&tx, id)?;
|
||||
|
||||
// Done
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
/// Get records from database match current `profile_id` optionally filtered by `scope`
|
||||
pub fn records_scope(&self, scope: Option<&str>) -> Result<Vec<Table>, Error> {
|
||||
pub fn records_scope(&self, scope: Option<&str>) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select_scope(&tx, scope)
|
||||
}
|
||||
|
||||
/// Get records from database match current `profile_id` optionally filtered by `scope`
|
||||
pub fn records_ref(&self, profile_identity_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn records_ref(&self, profile_identity_id: i64) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select_ref(&tx, profile_identity_id)
|
||||
@ -78,8 +62,8 @@ impl Database {
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_identity_auth`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -90,24 +74,25 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
UNIQUE (`scope`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, profile_identity_id: i64, scope: &str) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, profile_identity_id: i64, scope: &str) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `profile_identity_auth` (
|
||||
`profile_identity_id`,
|
||||
`scope`
|
||||
) VALUES (?, ?)",
|
||||
(profile_identity_id, scope),
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `profile_identity_auth` WHERE `id` = ?", [id])
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `profile_identity_auth` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
||||
pub fn select_scope(tx: &Transaction, scope: Option<&str>) -> Result<Vec<Table>, Error> {
|
||||
pub fn select_scope(tx: &Transaction, scope: Option<&str>) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`profile_identity_id`,
|
||||
@ -135,7 +120,7 @@ pub fn select_scope(tx: &Transaction, scope: Option<&str>) -> Result<Vec<Table>,
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn select_ref(tx: &Transaction, profile_identity_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select_ref(tx: &Transaction, profile_identity_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`profile_identity_id`,
|
||||
@ -162,7 +147,3 @@ pub fn select_ref(tx: &Transaction, profile_identity_id: i64) -> Result<Vec<Tabl
|
||||
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Database(sqlite::Error),
|
||||
Memory(super::memory::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Database(e) => write!(f, "Database error: {e}"),
|
||||
Self::Memory(e) => write!(f, "Memory error: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
pub mod auth;
|
||||
pub mod error;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
pub use auth::Auth;
|
||||
pub use error::Error;
|
||||
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
|
||||
/// Reduce disk usage by cache Auth index in memory
|
||||
@ -31,30 +29,30 @@ impl Memory {
|
||||
|
||||
/// Add new record with `scope` as key and `profile_identity_id` as value
|
||||
/// * validate record with same key does not exist yet
|
||||
pub fn add(&self, scope: String, profile_identity_id: i64) -> Result<(), Error> {
|
||||
pub fn add(&self, scope: String, profile_identity_id: i64) -> Result<()> {
|
||||
// Borrow shared index access
|
||||
let mut index = self.index.borrow_mut();
|
||||
|
||||
// Prevent existing key overwrite
|
||||
if index.contains_key(&scope) {
|
||||
return Err(Error::Overwrite(scope));
|
||||
bail!("Overwrite attempt for existing record `{scope}`")
|
||||
}
|
||||
|
||||
// Slot should be free, let check it twice
|
||||
match index.insert(scope, profile_identity_id) {
|
||||
Some(_) => Err(Error::Unexpected),
|
||||
Some(_) => bail!("Unexpected error"),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cleanup index
|
||||
pub fn clear(&self) -> Result<(), Error> {
|
||||
pub fn clear(&self) -> Result<()> {
|
||||
let mut index = self.index.borrow_mut();
|
||||
index.clear();
|
||||
if index.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::Clear)
|
||||
bail!("Could not cleanup memory index")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Clear,
|
||||
Overwrite(String),
|
||||
Unexpected,
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Clear => write!(f, "Could not cleanup memory index"),
|
||||
Self::Overwrite(key) => {
|
||||
write!(f, "Overwrite attempt for existing record `{key}`")
|
||||
}
|
||||
Self::Unexpected => write!(f, "Unexpected error"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Auth(super::auth::Error),
|
||||
Certificate(Box<dyn std::error::Error>),
|
||||
Database(sqlite::Error),
|
||||
Memory(super::memory::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Auth(e) => write!(f, "Could not create auth: {e}"),
|
||||
Self::Certificate(e) => {
|
||||
write!(f, "Could not create certificate: {e}")
|
||||
}
|
||||
Self::Database(e) => {
|
||||
write!(f, "Database error: {e}")
|
||||
}
|
||||
Self::Memory(e) => write!(f, "Memory error: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
mod error;
|
||||
use error::Error;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use gtk::gio::TlsCertificate;
|
||||
|
||||
/// Gemini identity holder for cached record in application-wide struct format.
|
||||
@ -12,10 +10,10 @@ pub struct Item {
|
||||
|
||||
impl Item {
|
||||
/// Convert `Self` to [TlsCertificate](https://docs.gtk.org/gio/class.TlsCertificate.html)
|
||||
pub fn to_tls_certificate(&self) -> Result<TlsCertificate, Error> {
|
||||
pub fn to_tls_certificate(&self) -> Result<TlsCertificate> {
|
||||
match TlsCertificate::from_pem(&self.pem) {
|
||||
Ok(certificate) => Ok(certificate),
|
||||
Err(e) => Err(Error::TlsCertificate(e)),
|
||||
Err(e) => bail!("TLS certificate error: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
use gtk::glib;
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
TlsCertificate(glib::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::TlsCertificate(e) => write!(f, "TLS certificate error: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
pub mod error;
|
||||
pub use error::Error;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
|
||||
/// Reduce disk usage by cache index in memory
|
||||
@ -28,38 +26,38 @@ impl Memory {
|
||||
|
||||
/// Add new record with `id` as key and `pem` as value
|
||||
/// * validate record with same key does not exist yet
|
||||
pub fn add(&self, profile_identity_id: i64, pem: String) -> Result<(), Error> {
|
||||
pub fn add(&self, profile_identity_id: i64, pem: String) -> Result<()> {
|
||||
// Borrow shared index access
|
||||
let mut index = self.index.borrow_mut();
|
||||
|
||||
// Prevent existing key overwrite
|
||||
if index.contains_key(&profile_identity_id) {
|
||||
return Err(Error::Overwrite(profile_identity_id));
|
||||
bail!("Overwrite attempt for existing record `{profile_identity_id}`")
|
||||
}
|
||||
|
||||
// Slot should be free, let check it twice
|
||||
match index.insert(profile_identity_id, pem) {
|
||||
Some(_) => Err(Error::Unexpected),
|
||||
Some(_) => bail!("Unexpected error"),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get `pem` clone by `id` from memory index
|
||||
pub fn get(&self, id: i64) -> Result<String, Error> {
|
||||
pub fn get(&self, id: i64) -> Result<String> {
|
||||
match self.index.borrow().get(&id) {
|
||||
Some(pem) => Ok(pem.clone()),
|
||||
None => Err(Error::NotFound(id)),
|
||||
None => bail!("Record `{id}` not found in memory index"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cleanup index
|
||||
pub fn clear(&self) -> Result<(), Error> {
|
||||
pub fn clear(&self) -> Result<()> {
|
||||
let mut index = self.index.borrow_mut();
|
||||
index.clear();
|
||||
if index.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::Clear)
|
||||
bail!("Could not cleanup memory index")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Clear,
|
||||
NotFound(i64),
|
||||
Overwrite(i64),
|
||||
Unexpected,
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Clear => write!(f, "Could not cleanup memory index"),
|
||||
Self::NotFound(key) => {
|
||||
write!(f, "Record `{key}` not found in memory index")
|
||||
}
|
||||
Self::Overwrite(key) => write!(f, "Overwrite attempt for existing record `{key}`"),
|
||||
Self::Unexpected => write!(f, "Unexpected error"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
mod database;
|
||||
mod error;
|
||||
mod memory;
|
||||
|
||||
use anyhow::Result;
|
||||
use database::Database;
|
||||
use error::Error;
|
||||
use gtk::glib::Uri;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
@ -18,40 +17,30 @@ impl Search {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: &Rc<i64>) -> Result<Self, Error> {
|
||||
match Database::init(connection, profile_id) {
|
||||
Ok(database) => {
|
||||
// Init fast search index
|
||||
let memory = Memory::init();
|
||||
|
||||
// Build initial index
|
||||
index(&database, &memory)?;
|
||||
|
||||
// Return new `Self`
|
||||
Ok(Self { database, memory })
|
||||
}
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
}
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: &Rc<i64>) -> Result<Self> {
|
||||
let database = Database::init(connection, profile_id)?;
|
||||
// Init fast search index
|
||||
let memory = Memory::init();
|
||||
// Build initial index
|
||||
index(&database, &memory)?;
|
||||
// Return new `Self`
|
||||
Ok(Self { database, memory })
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Add new search provider record
|
||||
/// * requires valid [Uri](https://docs.gtk.org/glib/struct.Uri.html)
|
||||
pub fn add(&self, query: &Uri, is_default: bool) -> Result<(), Error> {
|
||||
match self.database.add(query.to_string(), is_default) {
|
||||
Ok(_) => index(&self.database, &self.memory),
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
}
|
||||
pub fn add(&self, query: &Uri, is_default: bool) -> Result<()> {
|
||||
self.database.add(query.to_string(), is_default)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add new search provider record
|
||||
/// * requires valid [Uri](https://docs.gtk.org/glib/struct.Uri.html)
|
||||
pub fn set_default(&self, profile_search_id: i64) -> Result<(), Error> {
|
||||
match self.database.set_default(profile_search_id) {
|
||||
Ok(_) => index(&self.database, &self.memory),
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
}
|
||||
pub fn set_default(&self, profile_search_id: i64) -> Result<()> {
|
||||
self.database.set_default(profile_search_id)?;
|
||||
index(&self.database, &self.memory)
|
||||
}
|
||||
|
||||
/// Get records from the memory index
|
||||
@ -60,11 +49,9 @@ impl Search {
|
||||
}
|
||||
|
||||
/// Delete record from `database` and `memory` index
|
||||
pub fn delete(&self, id: i64) -> Result<(), Error> {
|
||||
match self.database.delete(id) {
|
||||
Ok(_) => index(&self.database, &self.memory),
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
}
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
self.database.delete(id)?;
|
||||
index(&self.database, &self.memory)
|
||||
}
|
||||
|
||||
// Getters
|
||||
@ -77,11 +64,9 @@ impl Search {
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
pub fn migrate(tx: &Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
// nothing yet..
|
||||
@ -91,15 +76,10 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
}
|
||||
|
||||
/// Sync memory index with database
|
||||
fn index(database: &Database, memory: &Memory) -> Result<(), Error> {
|
||||
fn index(database: &Database, memory: &Memory) -> Result<()> {
|
||||
memory.clear();
|
||||
match database.records() {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
memory.push(record.id, record.query, record.is_default)
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(Error::Database(e)),
|
||||
for record in database.records()? {
|
||||
memory.push(record.id, record.query, record.is_default)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use sqlite::{Connection, Error, Transaction};
|
||||
use anyhow::Result;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -18,7 +19,7 @@ impl Database {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn init(connection: &Rc<RwLock<Connection>>, profile_id: &Rc<i64>) -> Result<Self, Error> {
|
||||
pub fn init(connection: &Rc<RwLock<Connection>>, profile_id: &Rc<i64>) -> Result<Self> {
|
||||
let mut writable = connection.write().unwrap(); // @TODO handle
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
@ -38,7 +39,7 @@ impl Database {
|
||||
// Getters
|
||||
|
||||
/// Get records from database
|
||||
pub fn records(&self) -> Result<Vec<Row>, Error> {
|
||||
pub fn records(&self) -> Result<Vec<Row>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO handle
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx, *self.profile_id)
|
||||
@ -48,30 +49,19 @@ impl Database {
|
||||
|
||||
/// Create new record in database
|
||||
/// * return last insert ID on success
|
||||
pub fn add(&self, query: String, is_default: bool) -> Result<i64, Error> {
|
||||
// Begin new transaction
|
||||
pub fn add(&self, query: String, is_default: bool) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO handle
|
||||
let tx = writable.transaction()?;
|
||||
|
||||
// Create new record
|
||||
if is_default {
|
||||
// make sure only one default provider in set
|
||||
reset(&tx, *self.profile_id, !is_default)?;
|
||||
}
|
||||
insert(&tx, *self.profile_id, query, is_default)?;
|
||||
|
||||
// Hold insert ID for result
|
||||
let id = last_insert_id(&tx);
|
||||
|
||||
// Done
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(id),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
let id = insert(&tx, *self.profile_id, query, is_default)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Delete record from database
|
||||
pub fn delete(&self, id: i64) -> Result<(), Error> {
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
// Begin new transaction
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
@ -100,11 +90,12 @@ impl Database {
|
||||
}
|
||||
|
||||
// Done
|
||||
tx.commit()
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Delete record from database
|
||||
pub fn set_default(&self, id: i64) -> Result<(), Error> {
|
||||
pub fn set_default(&self, id: i64) -> Result<()> {
|
||||
// Begin new transaction
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
@ -114,14 +105,15 @@ impl Database {
|
||||
|
||||
// Delete record by ID
|
||||
set_default(&tx, *self.profile_id, id, true)?;
|
||||
tx.commit()
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_search`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
@ -132,15 +124,10 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
FOREIGN KEY (`profile_id`) REFERENCES `profile` (`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
fn insert(
|
||||
tx: &Transaction,
|
||||
profile_id: i64,
|
||||
query: String,
|
||||
is_default: bool,
|
||||
) -> Result<usize, Error> {
|
||||
fn insert(tx: &Transaction, profile_id: i64, query: String, is_default: bool) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `profile_search` (
|
||||
`profile_id`,
|
||||
@ -148,10 +135,11 @@ fn insert(
|
||||
`query`
|
||||
) VALUES (?, ?, ?)",
|
||||
(profile_id, is_default, query),
|
||||
)
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Row>, Error> {
|
||||
fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Row>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`, `profile_id`, `is_default`, `query`
|
||||
FROM `profile_search`
|
||||
@ -177,35 +165,26 @@ fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Row>, Error> {
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `profile_search` WHERE `id` = ?", [id])
|
||||
fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `profile_search` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
||||
fn reset(tx: &Transaction, profile_id: i64, is_default: bool) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
fn reset(tx: &Transaction, profile_id: i64, is_default: bool) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"UPDATE `profile_search` SET `is_default` = ? WHERE `profile_id` = ?",
|
||||
(is_default, profile_id),
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
fn set_default(
|
||||
tx: &Transaction,
|
||||
profile_id: i64,
|
||||
id: i64,
|
||||
is_default: bool,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
fn set_default(tx: &Transaction, profile_id: i64, id: i64, is_default: bool) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"UPDATE `profile_search` SET `is_default` = ? WHERE `profile_id` = ? AND `id` = ?",
|
||||
(is_default, profile_id, id),
|
||||
)
|
||||
}
|
||||
|
||||
fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Init default search providers list for given profile
|
||||
fn add_defaults(tx: &Transaction, profile_id: i64) -> Result<(), Error> {
|
||||
fn add_defaults(tx: &Transaction, profile_id: i64) -> Result<()> {
|
||||
for (provider, is_default) in &[
|
||||
("gemini://tlgs.one/search/search", true),
|
||||
("gemini://kennedy.gemi.dev/search", false),
|
||||
|
@ -1,16 +0,0 @@
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Database(sqlite::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Database(e) => {
|
||||
write!(f, "Database error: {e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user