mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-03-13 06:01:21 +00:00
move meta entities to the page level, remove extra references, add change some db tables structure, change app version
This commit is contained in:
parent
557ad69edf
commit
2ff6b9d963
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "Yoda"
|
||||
version = "0.9.7"
|
||||
version = "0.10.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
|
@ -51,8 +51,7 @@ impl App {
|
||||
Ok(records) => {
|
||||
// Restore child components
|
||||
for record in records {
|
||||
if let Err(e) =
|
||||
browser.restore(&transaction, &record.id)
|
||||
if let Err(e) = browser.restore(&transaction, record.id)
|
||||
{
|
||||
todo!("{e}")
|
||||
}
|
||||
@ -86,11 +85,11 @@ impl App {
|
||||
Ok(records) => {
|
||||
// Cleanup previous session records
|
||||
for record in records {
|
||||
match database::delete(&transaction, &record.id) {
|
||||
match database::delete(&transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
if let Err(e) =
|
||||
browser.clean(&transaction, &record.id)
|
||||
browser.clean(&transaction, record.id)
|
||||
{
|
||||
todo!("{e}")
|
||||
}
|
||||
@ -105,7 +104,7 @@ impl App {
|
||||
// Delegate save action to childs
|
||||
if let Err(e) = browser.save(
|
||||
&transaction,
|
||||
&database::last_insert_id(&transaction),
|
||||
database::last_insert_id(&transaction),
|
||||
) {
|
||||
todo!("{e}")
|
||||
}
|
||||
|
@ -106,15 +106,15 @@ impl Browser {
|
||||
|
||||
// Actions
|
||||
|
||||
pub fn clean(&self, transaction: &Transaction, app_id: &i64) -> Result<(), String> {
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
self.window.clean(transaction, &record.id)?;
|
||||
self.widget.clean(transaction, &record.id)?;
|
||||
self.window.clean(transaction, record.id)?;
|
||||
self.widget.clean(transaction, record.id)?;
|
||||
|
||||
/* @TODO
|
||||
self.header.clean(transaction, &record.id)?; */
|
||||
@ -129,13 +129,13 @@ impl Browser {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(&self, transaction: &Transaction, app_id: &i64) -> Result<(), String> {
|
||||
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)?;
|
||||
self.widget.restore(transaction, record.id)?;
|
||||
self.window.restore(transaction, record.id)?;
|
||||
|
||||
/* @TODO
|
||||
self.header.restore(transaction, &record.id)?; */
|
||||
@ -147,14 +147,14 @@ impl Browser {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_id: &i64) -> Result<(), String> {
|
||||
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)?;
|
||||
self.widget.save(transaction, id)?;
|
||||
self.window.save(transaction, id)?;
|
||||
|
||||
/* @TODO
|
||||
self.header.save(transaction, &id)?; */
|
||||
|
@ -18,11 +18,11 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_id: &i64) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, app_id: i64) -> Result<usize, Error> {
|
||||
tx.execute("INSERT INTO `app_browser` (`app_id`) VALUES (?)", [app_id])
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, app_id: &i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, app_id: i64) -> Result<Vec<Table>, Error> {
|
||||
let mut stmt = tx.prepare("SELECT `id`, `app_id` FROM `app_browser` WHERE `app_id` = ?")?;
|
||||
|
||||
let result = stmt.query_map([app_id], |row| {
|
||||
@ -42,7 +42,7 @@ pub fn select(tx: &Transaction, app_id: &i64) -> Result<Vec<Table>, Error> {
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
|
@ -41,11 +41,11 @@ impl Widget {
|
||||
}
|
||||
|
||||
// Actions
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_id: &i64) -> Result<(), String> {
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
// nothing yet..
|
||||
@ -60,7 +60,7 @@ impl Widget {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_id: &i64) -> Result<(), String> {
|
||||
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 {
|
||||
@ -79,13 +79,13 @@ impl Widget {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: &i64) -> Result<(), String> {
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> {
|
||||
match database::insert(
|
||||
transaction,
|
||||
app_browser_id,
|
||||
&self.application_window.default_width(),
|
||||
&self.application_window.default_height(),
|
||||
&self.application_window.is_maximized(),
|
||||
self.application_window.default_width(),
|
||||
self.application_window.default_height(),
|
||||
self.application_window.is_maximized(),
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Delegate save action to childs
|
||||
|
@ -26,10 +26,10 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
app_browser_id: &i64,
|
||||
default_width: &i32,
|
||||
default_height: &i32,
|
||||
is_maximized: &bool,
|
||||
app_browser_id: i64,
|
||||
default_width: i32,
|
||||
default_height: i32,
|
||||
is_maximized: bool,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_widget` (
|
||||
@ -40,14 +40,14 @@ pub fn insert(
|
||||
) VALUES (?, ?, ?, ?)",
|
||||
[
|
||||
app_browser_id,
|
||||
&(*default_width as i64),
|
||||
&(*default_height as i64),
|
||||
&(*is_maximized as i64),
|
||||
default_width as i64,
|
||||
default_height as i64,
|
||||
is_maximized as i64,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
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>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_id`,
|
||||
@ -76,7 +76,7 @@ pub fn select(tx: &Transaction, app_browser_id: &i64) -> Result<Vec<Table>, Erro
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser_widget` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
|
@ -138,14 +138,14 @@ impl Window {
|
||||
self.tab.update(tab_item_id);
|
||||
}
|
||||
|
||||
pub fn clean(&self, transaction: &Transaction, app_browser_id: &i64) -> Result<(), String> {
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
self.tab.clean(transaction, &record.id)?;
|
||||
self.tab.clean(transaction, record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
@ -157,12 +157,12 @@ impl Window {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(&self, transaction: &Transaction, app_browser_id: &i64) -> Result<(), String> {
|
||||
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)?;
|
||||
self.tab.restore(transaction, record.id)?;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
@ -171,13 +171,13 @@ impl Window {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self, transaction: &Transaction, app_browser_id: &i64) -> Result<(), String> {
|
||||
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))
|
||||
.save(transaction, database::last_insert_id(transaction))
|
||||
{
|
||||
return Err(e.to_string());
|
||||
}
|
||||
|
@ -18,14 +18,14 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_browser_id: &i64) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, app_browser_id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window` (`app_browser_id`) VALUES (?)",
|
||||
[app_browser_id],
|
||||
)
|
||||
}
|
||||
|
||||
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>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_id` FROM `app_browser_window`
|
||||
@ -49,7 +49,7 @@ pub fn select(tx: &Transaction, app_browser_id: &i64) -> Result<Vec<Table>, Erro
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser_window` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
|
@ -284,9 +284,7 @@ impl Tab {
|
||||
|
||||
// Update tab title on loading indicator inactive
|
||||
if !item.page.is_loading() {
|
||||
item.widget
|
||||
.tab_page
|
||||
.set_title(&item.page.meta.title.borrow())
|
||||
item.widget.tab_page.set_title(&item.page.title())
|
||||
}
|
||||
}
|
||||
// Update all tabs
|
||||
@ -297,9 +295,7 @@ impl Tab {
|
||||
|
||||
// Update tab title on loading indicator inactive
|
||||
if !item.page.is_loading() {
|
||||
item.widget
|
||||
.tab_page
|
||||
.set_title(&item.page.meta.title.borrow())
|
||||
item.widget.tab_page.set_title(&item.page.title())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -309,16 +305,16 @@ impl Tab {
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_id: &i64,
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to childs
|
||||
for (_, item) in self.index.borrow().iter() {
|
||||
item.clean(transaction, &record.id)?
|
||||
item.clean(transaction, record.id)?
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
@ -334,7 +330,7 @@ impl Tab {
|
||||
pub fn restore(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_id: &i64,
|
||||
app_browser_window_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_id) {
|
||||
Ok(records) => {
|
||||
@ -342,7 +338,7 @@ impl Tab {
|
||||
match Item::restore(
|
||||
&self.widget.tab_view,
|
||||
transaction,
|
||||
&record.id,
|
||||
record.id,
|
||||
&self.profile,
|
||||
(&self.browser_action, &self.window_action),
|
||||
) {
|
||||
@ -367,7 +363,7 @@ impl Tab {
|
||||
pub fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_id: &i64,
|
||||
app_browser_window_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::insert(transaction, app_browser_window_id) {
|
||||
Ok(_) => {
|
||||
@ -378,11 +374,11 @@ impl Tab {
|
||||
for (_, item) in self.index.borrow().iter() {
|
||||
item.save(
|
||||
transaction,
|
||||
&id,
|
||||
&self.widget.tab_view.page_position(&item.widget.tab_page),
|
||||
&item.widget.tab_page.is_pinned(),
|
||||
&item.widget.tab_page.is_selected(),
|
||||
&item.widget.tab_page.needs_attention(),
|
||||
id,
|
||||
self.widget.tab_view.page_position(&item.widget.tab_page),
|
||||
item.widget.tab_page.is_pinned(),
|
||||
item.widget.tab_page.is_selected(),
|
||||
item.widget.tab_page.needs_attention(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_browser_window_id: &i64) -> Result<usize, Error> {
|
||||
pub fn insert(tx: &Transaction, app_browser_window_id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab` (
|
||||
`app_browser_window_id`
|
||||
@ -27,7 +27,7 @@ pub fn insert(tx: &Transaction, app_browser_window_id: &i64) -> Result<usize, Er
|
||||
)
|
||||
}
|
||||
|
||||
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>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_id` FROM `app_browser_window_tab`
|
||||
@ -51,7 +51,7 @@ 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> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app_browser_window_tab` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
|
@ -129,16 +129,16 @@ impl Item {
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_id: &i64,
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
self.page.clean(transaction, &record.id)?;
|
||||
self.widget.clean(transaction, &record.id)?;
|
||||
self.page.clean(transaction, record.id)?;
|
||||
self.widget.clean(transaction, record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
@ -155,7 +155,7 @@ impl Item {
|
||||
pub fn restore(
|
||||
tab_view: &TabView,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_id: &i64,
|
||||
app_browser_window_tab_id: i64,
|
||||
profile: &Rc<Profile>,
|
||||
// Actions
|
||||
(browser_action, window_action): (&Rc<BrowserAction>, &Rc<WindowAction>),
|
||||
@ -183,8 +183,8 @@ impl Item {
|
||||
));
|
||||
|
||||
// Delegate restore action to the item childs
|
||||
item.page.restore(transaction, &record.id)?;
|
||||
item.widget.restore(transaction, &record.id)?;
|
||||
item.page.restore(transaction, record.id)?;
|
||||
item.widget.restore(transaction, record.id)?;
|
||||
|
||||
// Result
|
||||
items.push(item);
|
||||
@ -199,11 +199,11 @@ impl Item {
|
||||
pub fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_id: &i64,
|
||||
page_position: &i32,
|
||||
is_pinned: &bool,
|
||||
is_selected: &bool,
|
||||
is_attention: &bool,
|
||||
app_browser_window_tab_id: i64,
|
||||
page_position: i32,
|
||||
is_pinned: bool,
|
||||
is_selected: bool,
|
||||
is_attention: bool,
|
||||
) -> Result<(), String> {
|
||||
match database::insert(
|
||||
transaction,
|
||||
@ -217,8 +217,8 @@ impl Item {
|
||||
let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
self.page.save(transaction, &id)?;
|
||||
self.widget.save(transaction, &id)?;
|
||||
self.page.save(transaction, id)?;
|
||||
self.widget.save(transaction, id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
@ -27,11 +27,11 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_id: &i64,
|
||||
page_position: &i32,
|
||||
is_pinned: &bool,
|
||||
is_selected: &bool,
|
||||
is_attention: &bool,
|
||||
app_browser_window_tab_id: i64,
|
||||
page_position: i32,
|
||||
is_pinned: bool,
|
||||
is_selected: bool,
|
||||
is_attention: bool,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item` (
|
||||
@ -43,15 +43,15 @@ pub fn insert(
|
||||
) VALUES (?, ?, ?, ?, ?)",
|
||||
[
|
||||
app_browser_window_tab_id,
|
||||
&(*page_position as i64),
|
||||
&(*is_pinned as i64),
|
||||
&(*is_selected as i64),
|
||||
&(*is_attention as i64),
|
||||
page_position as i64,
|
||||
is_pinned as i64,
|
||||
is_selected as i64,
|
||||
is_attention as i64,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
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>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_id`,
|
||||
@ -83,7 +83,7 @@ pub fn select(tx: &Transaction, app_browser_window_tab_id: &i64) -> Result<Vec<T
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item` WHERE `id` = ?",
|
||||
[id],
|
||||
|
@ -3,20 +3,22 @@ mod content;
|
||||
mod database;
|
||||
mod error;
|
||||
mod input;
|
||||
mod meta;
|
||||
mod mode;
|
||||
mod navigation;
|
||||
mod redirect;
|
||||
mod search;
|
||||
mod status;
|
||||
mod widget;
|
||||
|
||||
use client::Client;
|
||||
use content::Content;
|
||||
use error::Error;
|
||||
use input::Input;
|
||||
use meta::{Meta, Status};
|
||||
use mode::Mode;
|
||||
use navigation::Navigation;
|
||||
use redirect::Redirect;
|
||||
use search::Search;
|
||||
use status::Status;
|
||||
use widget::Widget;
|
||||
|
||||
use crate::{
|
||||
@ -34,11 +36,14 @@ use gtk::{
|
||||
prelude::{EditableExt, FileExt, SocketClientExt},
|
||||
};
|
||||
use sqlite::Transaction;
|
||||
use std::{rc::Rc, time::Duration};
|
||||
use std::{cell::RefCell, rc::Rc, time::Duration};
|
||||
|
||||
pub struct Page {
|
||||
id: Rc<GString>,
|
||||
profile: Rc<Profile>,
|
||||
status: Rc<RefCell<Status>>,
|
||||
title: Rc<RefCell<GString>>,
|
||||
redirect: Rc<Redirect>,
|
||||
// Actions
|
||||
browser_action: Rc<BrowserAction>,
|
||||
tab_action: Rc<TabAction>,
|
||||
@ -48,7 +53,6 @@ pub struct Page {
|
||||
pub content: Rc<Content>,
|
||||
pub search: Rc<Search>,
|
||||
pub input: Rc<Input>,
|
||||
pub meta: Rc<Meta>,
|
||||
pub navigation: Rc<Navigation>,
|
||||
pub widget: Rc<Widget>,
|
||||
}
|
||||
@ -89,12 +93,15 @@ impl Page {
|
||||
&input.widget.clamp,
|
||||
));
|
||||
|
||||
let meta = Rc::new(Meta::new(Status::New, gformat!("New page")));
|
||||
//let meta = Rc::new(Meta::new(Status::New, gformat!("New page")));
|
||||
|
||||
// Done
|
||||
Self {
|
||||
id: id.clone(),
|
||||
profile: profile.clone(),
|
||||
redirect: Rc::new(Redirect::new()),
|
||||
status: Rc::new(RefCell::new(Status::New)),
|
||||
title: Rc::new(RefCell::new(gformat!("New page"))),
|
||||
// Actions
|
||||
browser_action: browser_action.clone(),
|
||||
tab_action: tab_action.clone(),
|
||||
@ -104,7 +111,6 @@ impl Page {
|
||||
content,
|
||||
search,
|
||||
input,
|
||||
meta,
|
||||
navigation,
|
||||
widget,
|
||||
}
|
||||
@ -190,12 +196,12 @@ impl Page {
|
||||
self.input.unset();
|
||||
|
||||
// Prevent infinitive redirection
|
||||
if self.meta.redirects() > DEFAULT_MAX_REDIRECT_COUNT {
|
||||
if self.redirect.count() > DEFAULT_MAX_REDIRECT_COUNT {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Try redirect request
|
||||
let request = if let Some(redirect) = self.meta.redirect() {
|
||||
let request = if let Some(redirect) = self.redirect.last() {
|
||||
// Gemini protocol may provide background (temporarily) redirects
|
||||
if redirect.is_foreground {
|
||||
self.navigation
|
||||
@ -209,14 +215,15 @@ impl Page {
|
||||
Mode::from(&redirect.request, redirect.referrer.as_ref())
|
||||
} else {
|
||||
// Reset redirect counter as request value taken from user input
|
||||
self.meta.redirect.borrow_mut().clear();
|
||||
self.redirect.clear();
|
||||
|
||||
// Return value from navigation entry
|
||||
Mode::from(&self.navigation.request.widget.entry.text(), None)
|
||||
};
|
||||
|
||||
// Update
|
||||
self.meta.set_status(Status::Reload).set_title("Loading..");
|
||||
self.status.replace(Status::Reload);
|
||||
self.title.replace(gformat!("Loading.."));
|
||||
self.browser_action.update.activate(Some(&self.id));
|
||||
|
||||
// Route by `Mode`
|
||||
@ -235,15 +242,12 @@ impl Page {
|
||||
self.load_gemini(uri, is_download, is_source, is_history)
|
||||
}
|
||||
"titan" => {
|
||||
// Format response
|
||||
let status = Status::Input;
|
||||
let title = "Titan input";
|
||||
|
||||
// Toggle input form
|
||||
// @TODO self.input.set_new_titan(|data|{});
|
||||
|
||||
// Update meta
|
||||
self.meta.set_status(status).set_title(title);
|
||||
self.status.replace(Status::Input);
|
||||
self.title.replace(gformat!("Titan input"));
|
||||
|
||||
// Update page
|
||||
self.browser_action.update.activate(Some(&self.id));
|
||||
@ -259,9 +263,8 @@ impl Page {
|
||||
status.set_description(Some(&format!("Scheme `{scheme}` not supported")));
|
||||
|
||||
// Update meta
|
||||
self.meta
|
||||
.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
self.status.replace(Status::Failure);
|
||||
self.title.replace(status.title());
|
||||
|
||||
// Update window
|
||||
self.browser_action.update.activate(Some(&self.id));
|
||||
@ -301,15 +304,14 @@ impl Page {
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
self.meta.clean(transaction, &record.id)?;
|
||||
self.navigation.clean(transaction, &record.id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
@ -318,24 +320,24 @@ impl Page {
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
// Update status
|
||||
self.meta.set_status(Status::SessionRestore);
|
||||
self.status.replace(Status::SessionRestore);
|
||||
|
||||
// Begin page restore
|
||||
match database::select(transaction, app_browser_window_tab_item_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Restore self by last record
|
||||
self.title.replace(record.title.into());
|
||||
// Delegate restore action to the item childs
|
||||
self.meta.restore(transaction, &record.id)?;
|
||||
self.navigation.restore(transaction, &record.id)?;
|
||||
// Make initial page history snap using `navigation` values restored
|
||||
// * just to have back/forward navigation ability
|
||||
@ -346,7 +348,7 @@ impl Page {
|
||||
}
|
||||
|
||||
// Update status
|
||||
self.meta.set_status(Status::SessionRestored);
|
||||
self.status.replace(Status::SessionRestored);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -354,14 +356,17 @@ impl Page {
|
||||
pub fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::insert(transaction, app_browser_window_tab_item_id) {
|
||||
match database::insert(
|
||||
transaction,
|
||||
app_browser_window_tab_item_id,
|
||||
self.title.borrow().as_str(),
|
||||
) {
|
||||
Ok(_) => {
|
||||
let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
self.meta.save(transaction, &id)?;
|
||||
self.navigation.save(transaction, &id)?;
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
@ -372,9 +377,14 @@ impl Page {
|
||||
|
||||
// Getters
|
||||
|
||||
/// Get `title` copy from `Self`
|
||||
pub fn title(&self) -> GString {
|
||||
self.title.borrow().clone()
|
||||
}
|
||||
|
||||
pub fn progress_fraction(&self) -> Option<f64> {
|
||||
// Interpret status to progress fraction
|
||||
match *self.meta.status.borrow() {
|
||||
match *self.status.borrow() {
|
||||
Status::Reload | Status::SessionRestore => Some(0.0),
|
||||
Status::Resolving => Some(0.1),
|
||||
Status::Resolved => Some(0.2),
|
||||
@ -410,20 +420,22 @@ impl Page {
|
||||
let content = self.content.clone();
|
||||
let id = self.id.clone();
|
||||
let input = self.input.clone();
|
||||
let meta = self.meta.clone();
|
||||
let title = self.title.clone();
|
||||
let status = self.status.clone();
|
||||
let navigation = self.navigation.clone();
|
||||
let profile = self.profile.clone();
|
||||
let search = self.search.clone();
|
||||
let tab_action = self.tab_action.clone();
|
||||
let window_action = self.window_action.clone();
|
||||
let redirect = self.redirect.clone();
|
||||
|
||||
// Listen for connection status updates
|
||||
self.client.gemini.socket.connect_event({
|
||||
let id = id.clone();
|
||||
let meta = meta.clone();
|
||||
let status = status.clone();
|
||||
let update = browser_action.update.clone();
|
||||
move |_, event, _, _| {
|
||||
meta.set_status(match event {
|
||||
status.replace(match event {
|
||||
SocketClientEvent::Resolving => Status::Resolving,
|
||||
SocketClientEvent::Resolved => Status::Resolved,
|
||||
SocketClientEvent::Connecting => Status::Connecting,
|
||||
@ -461,8 +473,7 @@ impl Page {
|
||||
response::meta::Status::Input |
|
||||
response::meta::Status::SensitiveInput => {
|
||||
// Format response
|
||||
let status = Status::Input;
|
||||
let title = match response.meta.data {
|
||||
let header = match response.meta.data {
|
||||
Some(data) => data.value,
|
||||
None => gformat!("Input expected"),
|
||||
};
|
||||
@ -473,21 +484,21 @@ impl Page {
|
||||
input.set_new_sensitive(
|
||||
tab_action.clone(),
|
||||
uri.clone(),
|
||||
Some(&title),
|
||||
Some(&header),
|
||||
Some(1024),
|
||||
),
|
||||
_ =>
|
||||
input.set_new_response(
|
||||
tab_action.clone(),
|
||||
uri.clone(),
|
||||
Some(&title),
|
||||
Some(&header),
|
||||
Some(1024),
|
||||
),
|
||||
}
|
||||
|
||||
// Update meta
|
||||
meta.set_status(status)
|
||||
.set_title(&title);
|
||||
status.replace(Status::Input);
|
||||
title.replace(header);
|
||||
|
||||
// Update page
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -499,7 +510,7 @@ impl Page {
|
||||
}
|
||||
if is_download {
|
||||
// Init download widget
|
||||
let status = content.to_status_download(
|
||||
let status_page = content.to_status_download(
|
||||
&uri_to_title(&uri), // grab default filename
|
||||
&cancellable,
|
||||
{
|
||||
@ -553,8 +564,8 @@ impl Page {
|
||||
);
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Success)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Success);
|
||||
title.replace(status_page.title());
|
||||
|
||||
// Update window
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -569,12 +580,13 @@ impl Page {
|
||||
{
|
||||
let browser_action = browser_action.clone();
|
||||
let content = content.clone();
|
||||
let search = search.clone();
|
||||
let id = id.clone();
|
||||
let meta = meta.clone();
|
||||
let search = search.clone();
|
||||
let status = status.clone();
|
||||
let title = title.clone();
|
||||
let uri = uri.clone();
|
||||
let window_action = window_action.clone();
|
||||
move |result|{
|
||||
move |result| {
|
||||
match result {
|
||||
Ok(buffer) => {
|
||||
// Set children component,
|
||||
@ -594,11 +606,11 @@ impl Page {
|
||||
search.set(Some(text_widget.text_view));
|
||||
|
||||
// Update page meta
|
||||
meta.set_status(Status::Success)
|
||||
.set_title(&match text_widget.meta.title {
|
||||
Some(meta_title) => meta_title,
|
||||
None => uri_to_title(&uri)
|
||||
});
|
||||
status.replace(Status::Success);
|
||||
title.replace(match text_widget.meta.title {
|
||||
Some(meta_title) => meta_title.into(), // @TODO
|
||||
None => uri_to_title(&uri)
|
||||
});
|
||||
|
||||
// Update window components
|
||||
window_action.find.simple_action.set_enabled(true);
|
||||
@ -607,12 +619,12 @@ impl Page {
|
||||
}
|
||||
Err(e) => {
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some(&e.to_string()));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some(&e.to_string()));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
|
||||
// Update window
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -624,7 +636,7 @@ impl Page {
|
||||
},
|
||||
"image/png" | "image/gif" | "image/jpeg" | "image/webp" => {
|
||||
// Final image size unknown, show loading widget
|
||||
let status = content.to_status_loading(
|
||||
let status_page = content.to_status_loading(
|
||||
Some(Duration::from_secs(1)) // show if download time > 1 second
|
||||
);
|
||||
|
||||
@ -638,7 +650,7 @@ impl Page {
|
||||
0xA00000, // 10M bytes max to prevent memory overflow if server play with promises
|
||||
move |_, total| {
|
||||
// Update loading progress
|
||||
status.set_description(
|
||||
status_page.set_description(
|
||||
Some(&gformat!("Download: {total} bytes"))
|
||||
);
|
||||
},
|
||||
@ -647,7 +659,8 @@ impl Page {
|
||||
let cancellable = cancellable.clone();
|
||||
let content = content.clone();
|
||||
let id = id.clone();
|
||||
let meta = meta.clone();
|
||||
let status = status.clone();
|
||||
let title = title.clone();
|
||||
let uri = uri.clone();
|
||||
move |result| match result {
|
||||
Ok((memory_input_stream, _)) => {
|
||||
@ -659,8 +672,8 @@ impl Page {
|
||||
match result {
|
||||
Ok(buffer) => {
|
||||
// Update page meta
|
||||
meta.set_status(Status::Success)
|
||||
.set_title(uri_to_title(&uri).as_str());
|
||||
status.replace(Status::Success);
|
||||
title.replace(uri_to_title(&uri));
|
||||
|
||||
// Update page content
|
||||
content.to_image(&Texture::for_pixbuf(&buffer));
|
||||
@ -670,12 +683,12 @@ impl Page {
|
||||
}
|
||||
Err(e) => {
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some(e.message()));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some(e.message()));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -683,12 +696,12 @@ impl Page {
|
||||
},
|
||||
Err(e) => {
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some(&e.to_string()));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some(&e.to_string()));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -696,14 +709,14 @@ impl Page {
|
||||
},
|
||||
mime => {
|
||||
// Init children widget
|
||||
let status = content.to_status_mime(
|
||||
let status_page = content.to_status_mime(
|
||||
mime,
|
||||
Some((tab_action.clone(), navigation.request.download()))
|
||||
);
|
||||
|
||||
// Update page meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
|
||||
// Update window
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -734,8 +747,8 @@ impl Page {
|
||||
// Client MUST prevent external redirects (by protocol specification)
|
||||
if is_external_uri(&resolved_uri, &uri) {
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title("Oops");
|
||||
status.replace(Status::Failure);
|
||||
title.replace(gformat!("Oops"));
|
||||
|
||||
// Show placeholder with manual confirmation to continue @TODO status page?
|
||||
content.to_text_gemini(
|
||||
@ -746,10 +759,10 @@ impl Page {
|
||||
)
|
||||
);
|
||||
// Client MUST limit the number of redirects they follow to 5 (by protocol specification)
|
||||
} else if meta.redirects() > 5 {
|
||||
} else if redirect.count() > 5 {
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title("Oops");
|
||||
status.replace(Status::Failure);
|
||||
title.replace(gformat!("Oops"));
|
||||
|
||||
// Show placeholder with manual confirmation to continue @TODO status page?
|
||||
content.to_text_gemini(
|
||||
@ -762,7 +775,7 @@ impl Page {
|
||||
// Redirection value looks valid, create new redirect (stored in meta `Redirect` holder)
|
||||
// then call page reload action to apply it by the parental controller
|
||||
} else {
|
||||
meta.add_redirect(
|
||||
redirect.add(
|
||||
// skip query and fragment by protocol requirements
|
||||
// @TODO review fragment specification
|
||||
resolved_uri.to_string_partial(
|
||||
@ -772,9 +785,10 @@ impl Page {
|
||||
Some(navigation.request.widget.entry.text()),
|
||||
// set follow policy based on status code
|
||||
matches!(response.meta.status, response::meta::Status::PermanentRedirect),
|
||||
)
|
||||
.set_status(Status::Redirect) // @TODO is this status really wanted?
|
||||
.set_title("Redirect");
|
||||
);
|
||||
|
||||
status.replace(Status::Redirect); // @TODO is this status really wanted here?
|
||||
title.replace(gformat!("Redirect"));
|
||||
|
||||
// Reload page to apply redirection (without history record request)
|
||||
tab_action.load.activate(None, false);
|
||||
@ -782,34 +796,34 @@ impl Page {
|
||||
},
|
||||
Err(e) => {
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some(&e.to_string()));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some(&e.to_string()));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some(&e.to_string()));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some(&e.to_string()));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
},
|
||||
}
|
||||
},
|
||||
None => {
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some("Redirection target not defined"));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some("Redirection target not defined"));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
},
|
||||
}
|
||||
|
||||
@ -827,9 +841,9 @@ impl Page {
|
||||
}
|
||||
|
||||
// Update widget
|
||||
let status = content.to_status_identity();
|
||||
let status_page = content.to_status_identity();
|
||||
|
||||
status.set_description(Some(&match response.meta.data {
|
||||
status_page.set_description(Some(&match response.meta.data {
|
||||
Some(data) => data.value,
|
||||
None => match response.meta.status {
|
||||
response::meta::Status::CertificateUnauthorized => gformat!("Certificate not authorized"),
|
||||
@ -839,8 +853,8 @@ impl Page {
|
||||
}));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Success)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Success);
|
||||
title.replace(status_page.title());
|
||||
|
||||
// Update window
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -852,16 +866,16 @@ impl Page {
|
||||
}
|
||||
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
let status_page = content.to_status_failure();
|
||||
|
||||
status.set_description(Some(&match response.meta.data {
|
||||
status_page.set_description(Some(&match response.meta.data {
|
||||
Some(data) => data.value,
|
||||
None => gformat!("Status code not supported"),
|
||||
}));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
|
||||
// Update window
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -875,12 +889,12 @@ impl Page {
|
||||
}
|
||||
|
||||
// Update widget
|
||||
let status = content.to_status_failure();
|
||||
status.set_description(Some(&e.to_string()));
|
||||
let status_page = content.to_status_failure();
|
||||
status_page.set_description(Some(&e.to_string()));
|
||||
|
||||
// Update meta
|
||||
meta.set_status(Status::Failure)
|
||||
.set_title(&status.title());
|
||||
status.replace(Status::Failure);
|
||||
title.replace(status_page.title());
|
||||
|
||||
// Update window
|
||||
browser_action.update.activate(Some(&id));
|
||||
@ -899,7 +913,6 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
}
|
||||
|
||||
// Delegate migration to childs
|
||||
meta::migrate(tx)?;
|
||||
navigation::migrate(tx)?;
|
||||
|
||||
// Success
|
||||
@ -911,12 +924,12 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
/// Useful as common placeholder when page title could not be detected
|
||||
///
|
||||
/// * this feature may be improved and moved outside @TODO
|
||||
fn uri_to_title(uri: &Uri) -> String {
|
||||
let title = uri.path().split('/').last().unwrap_or_default().to_string();
|
||||
if title.is_empty() {
|
||||
fn uri_to_title(uri: &Uri) -> GString {
|
||||
let title = uri.path();
|
||||
if title.split('/').last().unwrap_or_default().is_empty() {
|
||||
match uri.host() {
|
||||
Some(host) => host.to_string(),
|
||||
None => "Untitled".to_string(),
|
||||
Some(host) => host,
|
||||
None => gformat!("Untitled"),
|
||||
}
|
||||
} else {
|
||||
title
|
||||
|
@ -2,7 +2,8 @@ use sqlite::{Error, Transaction};
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
// pub app_browser_window_tab_item_id: i64, not in use
|
||||
// pub app_browser_window_tab_item_id: i64, not in use,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
@ -11,6 +12,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`app_browser_window_tab_item_id` INTEGER NOT NULL,
|
||||
`title` VARCHAR(1024),
|
||||
|
||||
FOREIGN KEY (`app_browser_window_tab_item_id`) REFERENCES `app_browser_window_tab_item`(`id`)
|
||||
)",
|
||||
@ -18,19 +20,25 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, app_browser_window_tab_item_id: &i64) -> Result<usize, Error> {
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
title: &str,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item_page` (
|
||||
`app_browser_window_tab_item_id`
|
||||
) VALUES (?)",
|
||||
[app_browser_window_tab_item_id],
|
||||
`app_browser_window_tab_item_id`,
|
||||
`title`
|
||||
) VALUES (?, ?)",
|
||||
(app_browser_window_tab_item_id, title),
|
||||
)
|
||||
}
|
||||
|
||||
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>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_item_id`
|
||||
`app_browser_window_tab_item_id`,
|
||||
`title`
|
||||
FROM `app_browser_window_tab_item_page`
|
||||
WHERE `app_browser_window_tab_item_id` = ?",
|
||||
)?;
|
||||
@ -39,6 +47,7 @@ pub fn select(tx: &Transaction, app_browser_window_tab_item_id: &i64) -> Result<
|
||||
Ok(Table {
|
||||
id: row.get(0)?,
|
||||
// app_browser_window_tab_item_id: row.get(1)?, not in use
|
||||
title: row.get(2)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
@ -52,7 +61,7 @@ pub fn select(tx: &Transaction, app_browser_window_tab_item_id: &i64) -> Result<
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item_page` WHERE `id` = ?",
|
||||
[id],
|
||||
|
@ -1,179 +0,0 @@
|
||||
mod database;
|
||||
mod redirect;
|
||||
|
||||
use redirect::Redirect;
|
||||
|
||||
use gtk::glib::GString;
|
||||
use sqlite::Transaction;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Status {
|
||||
Complete,
|
||||
Connected,
|
||||
Connecting,
|
||||
Failure,
|
||||
Input,
|
||||
New,
|
||||
ProxyNegotiated,
|
||||
ProxyNegotiating,
|
||||
Redirect,
|
||||
Reload,
|
||||
Resolved,
|
||||
Resolving,
|
||||
SessionRestore,
|
||||
SessionRestored,
|
||||
Success,
|
||||
TlsHandshaked,
|
||||
TlsHandshaking,
|
||||
}
|
||||
|
||||
pub struct Meta {
|
||||
pub status: RefCell<Status>,
|
||||
pub title: RefCell<GString>,
|
||||
pub redirect: RefCell<Vec<Redirect>>,
|
||||
}
|
||||
|
||||
impl Meta {
|
||||
// Constructors
|
||||
|
||||
pub fn new(status: Status, title: GString) -> Self {
|
||||
Self {
|
||||
status: RefCell::new(status),
|
||||
title: RefCell::new(title),
|
||||
redirect: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
pub fn set_status(&self, status: Status) -> &Self {
|
||||
self.status.replace(status);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) -> &Self {
|
||||
self.title.replace(GString::from(title));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_redirect(
|
||||
&self,
|
||||
request: GString,
|
||||
referrer: Option<GString>,
|
||||
is_foreground: bool,
|
||||
) -> &Self {
|
||||
self.redirect.borrow_mut().push(Redirect {
|
||||
request,
|
||||
referrer,
|
||||
is_foreground,
|
||||
is_processed: Cell::new(false),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn redirects(&self) -> usize {
|
||||
self.redirect.borrow().len() + 1
|
||||
}
|
||||
|
||||
pub fn redirect(&self) -> Option<Redirect> {
|
||||
if let Some(redirect) = self.redirect.borrow().last() {
|
||||
if !redirect.is_processed.replace(true) {
|
||||
return Some(redirect.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_page_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_page_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()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_page_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_page_id) {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
// Record value can be stored as NULL
|
||||
if let Some(title) = record.title {
|
||||
self.set_title(title.as_str());
|
||||
}
|
||||
|
||||
// Delegate restore action to the item childs
|
||||
// nothing yet..
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_page_id: &i64,
|
||||
) -> Result<(), String> {
|
||||
// Keep value in memory until operation complete
|
||||
let title = self.title.borrow();
|
||||
|
||||
match database::insert(
|
||||
transaction,
|
||||
app_browser_window_tab_page_id,
|
||||
match title.is_empty() {
|
||||
true => None,
|
||||
false => Some(title.as_str()),
|
||||
},
|
||||
) {
|
||||
Ok(_) => {
|
||||
// let id = database::last_insert_id(transaction);
|
||||
|
||||
// Delegate save action to childs
|
||||
// nothing yet..
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Tools
|
||||
pub fn migrate(tx: &Transaction) -> Result<(), String> {
|
||||
// Migrate self components
|
||||
if let Err(e) = database::init(tx) {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
|
||||
// Delegate migration to childs
|
||||
// nothing yet..
|
||||
|
||||
// Success
|
||||
Ok(())
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
use sqlite::{Error, Transaction};
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
// pub app_browser_window_tab_item_page_id: i64, not in use
|
||||
pub title: Option<String>, // can be stored as NULL
|
||||
}
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page_meta`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`app_browser_window_tab_item_page_id` INTEGER NOT NULL,
|
||||
`title` VARCHAR(1024),
|
||||
|
||||
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,
|
||||
title: Option<&str>,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"INSERT INTO `app_browser_window_tab_item_page_meta` (
|
||||
`app_browser_window_tab_item_page_id`,
|
||||
`title`
|
||||
) VALUES (?, ?)",
|
||||
(app_browser_window_tab_item_page_id, title),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn select(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_item_page_id: &i64,
|
||||
) -> Result<Vec<Table>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_item_page_id`,
|
||||
`title`
|
||||
FROM `app_browser_window_tab_item_page_meta`
|
||||
WHERE `app_browser_window_tab_item_page_id` = ?",
|
||||
)?;
|
||||
|
||||
let result = stmt.query_map([app_browser_window_tab_item_page_id], |row| {
|
||||
Ok(Table {
|
||||
id: row.get(0)?,
|
||||
// app_browser_window_tab_item_page_id: row.get(1)?, not in use
|
||||
title: row.get(2)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut records = Vec::new();
|
||||
|
||||
for record in result {
|
||||
let table = record?;
|
||||
records.push(table);
|
||||
}
|
||||
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item_page_meta` WHERE `id` = ?",
|
||||
[id],
|
||||
)
|
||||
}
|
||||
|
||||
/* not in use
|
||||
pub fn last_insert_id(tx: &Transaction) -> i64 {
|
||||
tx.last_insert_rowid()
|
||||
} */
|
57
src/app/browser/window/tab/item/page/redirect.rs
Normal file
57
src/app/browser/window/tab/item/page/redirect.rs
Normal file
@ -0,0 +1,57 @@
|
||||
mod item;
|
||||
use item::Item;
|
||||
|
||||
use gtk::glib::GString;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
pub struct Redirect {
|
||||
index: RefCell<Vec<Item>>,
|
||||
}
|
||||
|
||||
impl Default for Redirect {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Redirect {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
index: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
pub fn add(&self, request: GString, referrer: Option<GString>, is_foreground: bool) -> &Self {
|
||||
self.index.borrow_mut().push(Item {
|
||||
request,
|
||||
referrer,
|
||||
is_foreground,
|
||||
is_processed: Cell::new(false),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.index.borrow_mut().clear()
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
self.index.borrow().len() + 1
|
||||
}
|
||||
|
||||
pub fn last(&self) -> Option<Item> {
|
||||
if let Some(redirect) = self.index.borrow().last() {
|
||||
if !redirect.is_processed.replace(true) {
|
||||
return Some(redirect.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
use gtk::glib::GString;
|
||||
use std::cell::Cell;
|
||||
|
||||
/// Single redirect `Item`
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Redirect {
|
||||
pub struct Item {
|
||||
pub is_foreground: bool,
|
||||
pub is_processed: Cell<bool>,
|
||||
pub referrer: Option<GString>,
|
22
src/app/browser/window/tab/item/page/status.rs
Normal file
22
src/app/browser/window/tab/item/page/status.rs
Normal file
@ -0,0 +1,22 @@
|
||||
/// `Page` status
|
||||
/// * not same as the Gemini status!
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Status {
|
||||
Complete,
|
||||
Connected,
|
||||
Connecting,
|
||||
Failure,
|
||||
Input,
|
||||
New,
|
||||
ProxyNegotiated,
|
||||
ProxyNegotiating,
|
||||
Redirect,
|
||||
Reload,
|
||||
Resolved,
|
||||
Resolving,
|
||||
SessionRestore,
|
||||
SessionRestored,
|
||||
Success,
|
||||
TlsHandshaked,
|
||||
TlsHandshaking,
|
||||
}
|
@ -58,12 +58,12 @@ impl Widget {
|
||||
pub fn clean(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
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) {
|
||||
match database::delete(transaction, record.id) {
|
||||
Ok(_) => {
|
||||
// Delegate clean action to the item childs
|
||||
// nothing yet..
|
||||
@ -81,7 +81,7 @@ impl Widget {
|
||||
pub fn restore(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
match database::select(transaction, app_browser_window_tab_item_id) {
|
||||
Ok(records) => {
|
||||
@ -104,7 +104,7 @@ impl Widget {
|
||||
pub fn save(
|
||||
&self,
|
||||
transaction: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
) -> Result<(), String> {
|
||||
// Keep value in memory until operation complete
|
||||
let title = self.tab_page.title();
|
||||
|
@ -22,7 +22,7 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
|
||||
pub fn insert(
|
||||
tx: &Transaction,
|
||||
app_browser_window_tab_item_id: &i64,
|
||||
app_browser_window_tab_item_id: i64,
|
||||
title: Option<&str>,
|
||||
) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
@ -34,7 +34,7 @@ pub fn insert(
|
||||
)
|
||||
}
|
||||
|
||||
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>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`app_browser_window_tab_item_id`,
|
||||
@ -61,7 +61,7 @@ pub fn select(tx: &Transaction, app_browser_window_tab_item_id: &i64) -> Result<
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"DELETE FROM `app_browser_window_tab_item_widget` WHERE `id` = ?",
|
||||
[id],
|
||||
|
@ -32,7 +32,7 @@ pub fn select(tx: &Transaction) -> Result<Vec<Table>, Error> {
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: &i64) -> Result<usize, Error> {
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `app` WHERE `id` = ?", [id])
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user