feat: cache tab data

This commit is contained in:
Artemy Egorov 2024-07-30 19:09:59 +03:00
parent 4a702f0352
commit 8b231d1146
4 changed files with 63 additions and 57 deletions

View file

@ -31,4 +31,4 @@ Browser features:
- [x] tab closing - [x] tab closing
- [x] save and restore tabs - [x] save and restore tabs
- [ ] save and restore favorites - [ ] save and restore favorites
- [ ] cache tab data - [x] cache tab data

View file

@ -1,6 +1,6 @@
use dalet::{Argument, Body, Tag}; use dalet::{Argument, Body, Tag};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{fs, path::PathBuf}; use std::{collections::HashMap, fs, path::PathBuf};
use crate::utils::write_tabs; use crate::utils::write_tabs;
@ -32,6 +32,19 @@ pub struct VigiState {
// Temporary // Temporary
pub top_bar_input: String, pub top_bar_input: String,
pub current_data: Vec<Tag>, pub current_data: Vec<Tag>,
pub cached_inputs: HashMap<String, VigiOutput>,
}
#[derive(Serialize, Debug, Clone)]
pub struct VigiOutput {
pub title: String,
pub data: Vec<Tag>,
}
impl VigiOutput {
pub fn new(title: String, data: Vec<Tag>) -> Self {
Self { title, data }
}
} }
#[derive(Serialize, Debug, Clone)] #[derive(Serialize, Debug, Clone)]
@ -60,6 +73,7 @@ impl VigiState {
top_bar_input: "".to_string(), top_bar_input: "".to_string(),
current_data: Vec::new(), current_data: Vec::new(),
cached_inputs: HashMap::new(),
} }
} }
@ -88,69 +102,72 @@ impl VigiState {
.map_err(|_| VigiError::StateUpdate) .map_err(|_| VigiError::StateUpdate)
} }
async fn process_input(&mut self) -> Result<(), VigiError> { async fn process_input(&mut self, ignore_cache: bool) -> Result<(), VigiError> {
// TODO: Implement mime type, language, protocol or search detection // TODO: Implement mime type, language, protocol or search detection
// TODO: Implement text links parsing // TODO: Implement text links parsing
println!("process_input {{\n \"{}\"", self.top_bar_input); println!("process_input \"{}\"", self.top_bar_input);
let result = match self.top_bar_input.as_str() { let cached = !ignore_cache && self.cached_inputs.contains_key(&self.top_bar_input);
"" => {
self.update_tab(TabType::HomePage, "Home".to_owned(), "".to_owned())?;
self.current_data = vec![Tag::new( let output = {
0, if cached {
Body::Text("Type something in the address bar".to_owned()), self.cached_inputs.get(&self.top_bar_input).unwrap().clone()
Argument::Null, } else if self.top_bar_input.starts_with("https://")
)]; || self.top_bar_input.starts_with("http://")
{
let res = reqwest::get(&self.top_bar_input)
.await
.map_err(|_| VigiError::Network)?
.text()
.await
.map_err(|_| VigiError::Network)?;
Ok(()) let mut truncated = res.clone();
truncated.truncate(50);
VigiOutput::new(
truncated,
vec![Tag::new(0, Body::Text(res), Argument::Null)],
)
} else if self.top_bar_input.is_empty() {
VigiOutput::new(
"Homepage".to_owned(),
vec![Tag::new(
0,
Body::Text("Type something in the address bar".to_owned()),
Argument::Null,
)],
)
} else {
todo!();
} }
input => match reqwest::get(input).await {
Ok(res) => match res.text().await {
Ok(res) => {
let mut truncated = res.clone();
truncated.truncate(50);
self.update_tab(TabType::Text, truncated, input.to_owned())?;
self.current_data = vec![Tag::new(0, Body::Text(res), Argument::Null)];
Ok(())
}
Err(_) => Err(VigiError::Parse),
},
Err(_) => Err(VigiError::Network),
},
}; };
if result.is_ok() { self.update_tab(output.title.clone(), self.top_bar_input.clone())?;
println!(" Ok\n}}"); self.current_data = output.data.clone();
} else {
println!(" Err\n}}"); if !cached {
self.cached_inputs
.insert(self.top_bar_input.clone(), output);
} }
result Ok(())
} }
pub async fn update_input(&mut self, input: String) -> Result<(), VigiError> { pub async fn update_input(&mut self, input: String) -> Result<(), VigiError> {
self.top_bar_input = input; self.top_bar_input = input;
self.process_input().await self.process_input(true).await
} }
pub async fn load_tab(&mut self) -> Result<(), VigiError> { pub async fn load_tab(&mut self) -> Result<(), VigiError> {
self.process_input().await self.process_input(false).await
} }
fn update_tab( fn update_tab(&mut self, tab_title: String, tab_url: String) -> Result<(), VigiError> {
&mut self,
tab_type: TabType,
tab_title: String,
tab_url: String,
) -> Result<(), VigiError> {
match self.tabs.get_mut(self.current_tab_index) { match self.tabs.get_mut(self.current_tab_index) {
Some(tab) => { Some(tab) => {
*tab = Tab::new(tab_type, tab_title, tab_url, tab.id); *tab = Tab::new(tab_title, tab_url, tab.id);
write_tabs(&self.local_tabs_path, &self.tabs)?; write_tabs(&self.local_tabs_path, &self.tabs)?;
@ -163,7 +180,6 @@ impl VigiState {
pub fn add_tab(&mut self) -> Result<(), VigiError> { pub fn add_tab(&mut self) -> Result<(), VigiError> {
self.tabs_id_counter += 1; self.tabs_id_counter += 1;
self.tabs.push(Tab::new( self.tabs.push(Tab::new(
TabType::HomePage,
"Home".to_string(), "Home".to_string(),
"".to_string(), "".to_string(),
self.tabs_id_counter, self.tabs_id_counter,
@ -209,20 +225,13 @@ impl VigiState {
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Tab { pub struct Tab {
pub ty: TabType,
pub title: String, pub title: String,
pub url: String, pub url: String,
pub id: usize, pub id: usize,
} }
impl Tab { impl Tab {
pub fn new(ty: TabType, title: String, url: String, id: usize) -> Self { pub fn new(title: String, url: String, id: usize) -> Self {
Self { ty, title, url, id } Self { title, url, id }
} }
} }
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum TabType {
HomePage,
Text,
}

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { StateTab } from "$lib/types"; import type { StateTab } from "$lib/types";
import { removeTab, selectTab } from "$lib/utils"; import { removeTab, selectTab } from "$lib/utils";
import { fade, slide } from "svelte/transition"; import { slide } from "svelte/transition";
import Close from "$lib/icons/Close.svelte"; import Close from "$lib/icons/Close.svelte";
import { isLoading } from "$lib/stores"; import { isLoading } from "$lib/stores";
import GooLoad from "$lib/icons/GooLoad.svelte"; import GooLoad from "$lib/icons/GooLoad.svelte";

View file

@ -9,10 +9,7 @@ export interface VigiState {
current_data: Tag[]; current_data: Tag[];
} }
type TabType = "HomePage" | "Text";
export interface StateTab { export interface StateTab {
ty: TabType;
title: string; title: string;
url: string; url: string;
id: number; id: number;