Commit bcfb1622 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui
Browse files

track web resources and re-download if needed

parent 4fa8029e
Pipeline #150320 failed with stage
in 8 minutes and 3 seconds
use crate::banners;
use crate::config;
use crate::utils;
use crate::widgets::{View, Window};
use gio::prelude::*;
use gtk::prelude::*;
......@@ -14,9 +13,8 @@ pub enum Action {
OpenFile,
LoadFile(PathBuf),
SetView(View),
AddError(String, String), // (id, error)
RemoveError(String), // id
DownloadResource(String, String), // (url, cache_filepath)
AddError(String, String), // (id, error)
RemoveError(String), // id
}
pub struct Application {
......@@ -152,22 +150,7 @@ impl Application {
self.errors.borrow_mut().remove(&id);
self.window.set_errors(self.errors.borrow());
}
Action::DownloadResource(resource_url, cache_file) => self.download_into(resource_url, cache_file),
};
glib::Continue(true)
}
fn download_into(&self, resource_url: String, cache_file: String) {
let sender = self.sender.clone();
let ctx = glib::MainContext::default();
ctx.spawn_local(async move {
match utils::download(&resource_url, &cache_file).await {
Ok(_) => send!(sender, Action::RemoveError(resource_url)),
Err(err) => {
warn!("Failed to download the file {}", err);
send!(sender, Action::AddError(resource_url, "Failed to download".to_string()));
}
};
});
}
}
use crate::application::Action;
use crate::utils;
use gio::prelude::*;
use glib::Sender;
use libxml::parser::Parser;
......@@ -71,26 +72,43 @@ impl Banner {
}
fn init(&self) {
self.prepare_css();
}
pub fn set_css(&mut self, css: &str) {
self.css = css.to_string();
self.prepare_css();
}
fn prepare_css(&self) {
lazy_static! {
static ref RE: Regex = Regex::new(r"(?:https|http)+://(?:\w\.?)+\.(?:[\w]/?\~?\-?\.?)+").expect("Invalid Regex expression");
}
let css = self.css.clone();
if let Some(urls_caps) = RE.captures(&css) {
for url_cap in urls_caps.iter() {
let resource_url = url_cap.unwrap().as_str().to_string();
let url_segments: Vec<&str> = resource_url.rsplit('/').collect();
let resource_filename: String = (*url_segments.get(0).unwrap()).to_string();
let mut cache_file: PathBuf = glib::get_user_cache_dir().unwrap();
cache_file.push(resource_filename);
let cache_filepath = cache_file.to_str().unwrap().to_string();
if !cache_file.exists() {
send!(self.sender, Action::DownloadResource(resource_url.clone(), cache_filepath.clone()));
if let Ok(mut web_resources) = self.web_resources.try_borrow_mut() {
web_resources.clear();
let css = self.css.clone();
if let Some(urls_caps) = RE.captures(&css) {
for url_cap in urls_caps.iter() {
let resource_url = url_cap.unwrap().as_str().to_string();
let url_segments: Vec<&str> = resource_url.rsplit('/').collect();
let resource_filename: String = (*url_segments.get(0).unwrap()).to_string();
let mut cache_file: PathBuf = glib::get_user_cache_dir().unwrap();
cache_file.push(resource_filename);
let cache_filepath = cache_file.to_str().unwrap().to_string();
web_resources.insert(resource_url, cache_filepath);
}
self.web_resources.borrow_mut().insert(resource_url, cache_filepath);
}
}
}
pub async fn prepare_resources(&self) -> Result<(), failure::Error> {
for (resource_url, cache_path) in self.web_resources.try_borrow()?.iter() {
utils::download(resource_url, cache_path).await?;
}
Ok(())
}
}
pub struct Banners {
......
......@@ -3,14 +3,14 @@ use crate::banners;
use glib::Sender;
use gtk::prelude::*;
use sourceview::prelude::*;
use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};
#[derive(Debug)]
pub struct Banner {
pub widget: gtk::Box,
builder: gtk::Builder,
sender: Sender<Action>,
banner: banners::Banner,
banner: RefCell<banners::Banner>,
}
// Contains an EventBox & Revealer(SourceView)
......@@ -26,7 +26,7 @@ impl Banner {
widget: banner_widget,
builder,
sender,
banner,
banner: RefCell::new(banner),
});
b.init(b.clone());
......@@ -45,7 +45,6 @@ impl Banner {
get_widget!(self.builder, sourceview::Buffer, source_buffer);
self.inject_css(&self.banner.css);
source_revealer.show();
banner_eventbox.show();
......@@ -53,7 +52,7 @@ impl Banner {
let css_lang = sourceview::LanguageManager::get_default().and_then(|lm| lm.get_language("css")).unwrap();
source_buffer.set_language(Some(&css_lang));
source_buffer.set_highlight_syntax(true);
source_buffer.set_text(&self.banner.css.trim());
source_buffer.set_text(&self.banner.borrow().css.trim());
if let Some(undo_manager) = source_buffer.get_undo_manager() {
undo_manager.begin_not_undoable_action();
......@@ -83,21 +82,40 @@ impl Banner {
let css = buffer.get_text(&start, &end, true).unwrap();
banner_widget.inject_css(&css);
});
let css = self.banner.borrow().css.clone();
self.inject_css(&css);
}
fn inject_css(&self, css: &str) {
self.banner.borrow_mut().set_css(css);
let sender = self.sender.clone();
let banner = self.banner.borrow().clone();
let ctx = glib::MainContext::default();
ctx.spawn_local(async move {
let error_id = format!("io_{}", banner.id);
match banner.prepare_resources().await {
Ok(_) => {
send!(sender, Action::RemoveError(error_id));
}
Err(err) => {
warn!("Failed to download the file {}", err);
send!(sender, Action::AddError(error_id, "Failed to download a web resource".to_string()));
}
};
});
get_widget!(self.builder, gtk::Box, banner);
let ctx = banner.get_style_context();
// Inject the banner CSS
let mut css = css.replace("@datadir@/gnome-software", &self.banner.resources_dir);
for (url, cache_path) in self.banner.web_resources.borrow().iter() {
let mut css = css.replace("@datadir@/gnome-software", &self.banner.borrow().resources_dir);
let web_resources = self.banner.borrow().web_resources.borrow().clone();
for (url, cache_path) in web_resources.iter() {
css = css.replace(url, cache_path);
}
let css = format!(".banner{{ {} }}", css);
let banner_id = &self.banner.id;
let banner_id = &self.banner.borrow().id;
let provider = gtk::CssProvider::new();
match provider.load_from_data(css.as_bytes()) {
Ok(_) => send!(self.sender, Action::RemoveError(banner_id.to_string())),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment