mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-04-02 09:35:28 +00:00
page controller contains lot of code, begin components reorganization before implement new features
This commit is contained in:
parent
2cab9e4287
commit
a35d86a630
6 changed files with 153 additions and 80 deletions
|
|
@ -1,5 +1,14 @@
|
|||
mod redirect;
|
||||
mod status;
|
||||
|
||||
use redirect::Redirect;
|
||||
use status::Status;
|
||||
|
||||
use gtk::{gio::Cancellable, prelude::CancellableExt};
|
||||
use std::cell::Cell;
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
/// Multi-client holder for single `Page` object
|
||||
///
|
||||
|
|
@ -10,7 +19,11 @@ use std::cell::Cell;
|
|||
pub struct Client {
|
||||
// Shared reference to cancel async operations
|
||||
cancellable: Cell<Cancellable>,
|
||||
// Clients
|
||||
// Redirects resolver for different protocols
|
||||
pub redirect: Rc<Redirect>,
|
||||
// Track update status
|
||||
status: Rc<RefCell<Status>>,
|
||||
// Drivers
|
||||
pub gemini: gemini::Client,
|
||||
// other clients..
|
||||
}
|
||||
|
|
@ -28,6 +41,8 @@ impl Client {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
cancellable: Cell::new(Cancellable::new()),
|
||||
redirect: Rc::new(Redirect::new()),
|
||||
status: Rc::new(RefCell::new(Status::Cancellable)),
|
||||
gemini: gemini::Client::new(),
|
||||
}
|
||||
}
|
||||
|
|
@ -41,9 +56,23 @@ impl Client {
|
|||
let previous = self.cancellable.replace(cancellable.clone());
|
||||
if !previous.is_cancelled() {
|
||||
previous.cancel();
|
||||
self.status.replace(Status::Cancelled);
|
||||
} else {
|
||||
self.status.replace(Status::Cancellable);
|
||||
}
|
||||
|
||||
// Done
|
||||
cancellable
|
||||
}
|
||||
|
||||
pub fn request(&self, query: &str) {
|
||||
self.status.replace(Status::Request(query.to_string()));
|
||||
|
||||
// Forcefully prevent infinitive redirection
|
||||
// * this condition just to make sure that client will never stuck by driver implementation issue
|
||||
if self.redirect.count() > redirect::LIMIT {
|
||||
self.status.replace(Status::RedirectLimit(redirect::LIMIT));
|
||||
// @TODO return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
67
src/app/browser/window/tab/item/page/client/redirect.rs
Normal file
67
src/app/browser/window/tab/item/page/client/redirect.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
mod item;
|
||||
use item::Item;
|
||||
|
||||
use gtk::glib::Uri;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
/// Global limit to prevent infinitive redirection issues
|
||||
/// * defined value is globally applicable to ALL drivers
|
||||
/// * every driver implement its own value, according to protocol specification
|
||||
/// * the `Client` will forcefully break redirection loop when iteration reach this value
|
||||
pub const LIMIT: usize = 10; // @TODO make optional
|
||||
|
||||
pub struct Redirect {
|
||||
chain: RefCell<Vec<Item>>,
|
||||
}
|
||||
|
||||
impl Default for Redirect {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Redirect {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
chain: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Register new redirect in chain
|
||||
pub fn add(&self, request: Uri, referrer: Option<Uri>, is_foreground: bool) -> &Self {
|
||||
self.chain.borrow_mut().push(Item {
|
||||
request,
|
||||
referrer,
|
||||
is_foreground,
|
||||
is_processed: Cell::new(false),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Clear redirect chain
|
||||
pub fn clear(&self) {
|
||||
self.chain.borrow_mut().clear()
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
/// Get total redirects count in chain
|
||||
pub fn count(&self) -> usize {
|
||||
self.chain.borrow().len() + 1
|
||||
}
|
||||
|
||||
/// Get last redirection `Item` copy
|
||||
pub fn last(&self) -> Option<Item> {
|
||||
if let Some(redirect) = self.chain.borrow().last() {
|
||||
if !redirect.is_processed.replace(true) {
|
||||
return Some(redirect.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
11
src/app/browser/window/tab/item/page/client/redirect/item.rs
Normal file
11
src/app/browser/window/tab/item/page/client/redirect/item.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
use gtk::glib::Uri;
|
||||
use std::cell::Cell;
|
||||
|
||||
/// Single redirect `Item`
|
||||
#[derive(Clone)]
|
||||
pub struct Item {
|
||||
pub is_foreground: bool,
|
||||
pub is_processed: Cell<bool>,
|
||||
pub referrer: Option<Uri>,
|
||||
pub request: Uri,
|
||||
}
|
||||
36
src/app/browser/window/tab/item/page/client/status.rs
Normal file
36
src/app/browser/window/tab/item/page/client/status.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
/// Local `Client` status
|
||||
/// * not same as the Gemini status!
|
||||
pub enum Status {
|
||||
/// Ready to use (or cancel from outside)
|
||||
Cancellable,
|
||||
/// Operation cancelled, new `Cancellable` required to continue
|
||||
Cancelled,
|
||||
/// Redirection count limit reached by protocol driver or global settings
|
||||
RedirectLimit(usize),
|
||||
/// New `request` begin
|
||||
Request(String),
|
||||
}
|
||||
|
||||
impl Display for Status {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Cancellable => {
|
||||
write!(f, "Ready to use (or cancel from outside)")
|
||||
}
|
||||
Self::Cancelled => {
|
||||
write!(
|
||||
f,
|
||||
"Operation cancelled, new `Cancellable` required to continue"
|
||||
)
|
||||
}
|
||||
Self::RedirectLimit(count) => {
|
||||
write!(f, "Redirection count limit ({count}) reached by protocol driver or global settings")
|
||||
}
|
||||
Self::Request(value) => {
|
||||
write!(f, "Request `{value}`...")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue