From e22cac904ce141d33a3619a5f0313136d47ecc28 Mon Sep 17 00:00:00 2001 From: Nocturnalx Date: Sun, 9 Jun 2024 10:42:33 +0100 Subject: [PATCH 1/5] very hot fix for issue #187, doesn't close it. -IP not recognised as url --- napture/src/main.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/napture/src/main.rs b/napture/src/main.rs index 4911466d..48e066f7 100644 --- a/napture/src/main.rs +++ b/napture/src/main.rs @@ -611,7 +611,16 @@ fn fetch_dns(url: String) -> String { if let Ok(json) = response.json::() { let path = url.split_once('/') .unwrap_or(("", "")).1; - json.ip + &format!("/{}", path) + + //check if json.ip is a standalone IP address, + //if so, prepend "http://" to make it parsable + //as a url. + let ip = match json.ip.parse::() { + Ok(_ip) => format!("http://{}", json.ip), + Err(_) => json.ip.clone(), + }; + + ip + &format!("/{}", path) } else { lualog!( "debug", From b6f728de9cea6ea15e5817e9706ede81c5d3e537 Mon Sep 17 00:00:00 2001 From: Nocturnalx Date: Mon, 10 Jun 2024 05:20:28 +0100 Subject: [PATCH 2/5] Added mouse button listeners for forwards and back navigation. --- napture/src/main.rs | 78 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/napture/src/main.rs b/napture/src/main.rs index 48e066f7..1540a0bc 100644 --- a/napture/src/main.rs +++ b/napture/src/main.rs @@ -420,6 +420,8 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>>, config: Rc>>, config: Rc>, css_provider: Rc>){ + +// } + // commented code here was an attempt at implementing multiple tabs. // it will be kept here in case I decide to implement multiple tabs again fn make_tab( From 8c8a2819e7ef0f69668b071a6964ae489e74344c Mon Sep 17 00:00:00 2001 From: Nocturnalx Date: Tue, 11 Jun 2024 17:00:21 +0100 Subject: [PATCH 3/5] created page source viewer --- napture/src/b9/html.rs | 34 +++- napture/src/main.rs | 300 +++++++++++++++++++++++++---- napture/src/page_source_mod/mod.rs | 25 +++ 3 files changed, 319 insertions(+), 40 deletions(-) create mode 100644 napture/src/page_source_mod/mod.rs diff --git a/napture/src/b9/html.rs b/napture/src/b9/html.rs index e40b2300..54cc47b9 100644 --- a/napture/src/b9/html.rs +++ b/napture/src/b9/html.rs @@ -1,6 +1,6 @@ extern crate html_parser; -use crate::{lualog, Tab, globals::LUA_TIMEOUTS}; +use crate::{globals::LUA_TIMEOUTS, lualog, Tab}; use super::{ css::{self, Styleable}, @@ -26,7 +26,7 @@ fn decode_html_entities>(s: T) -> String { decode_html_entities(s.as_ref()).to_string() } -async fn parse_html(mut url: String) -> Result<(Node, Node)> { +async fn parse_html(mut url: String) -> Result<(Node, Node, String)> { let mut is_html = true; let mut file_name = String::new(); @@ -79,7 +79,7 @@ async fn parse_html(mut url: String) -> Result<(Node, Node)> { } }; - Ok((head, body)) + Ok((head, body, html)) } fn find_element_by_name(elements: &Vec, name: &str) -> Option { @@ -128,7 +128,7 @@ pub async fn build_ui( let mut css: String = css::reset_css(); - let (head, body) = match parse_html(furl.to_string()).await { + let (head, body, source_html) = match parse_html(furl.to_string()).await { Ok(ok) => ok, Err(e) => { eprintln!("Couldn't parse HTML: {}", e); @@ -136,6 +136,12 @@ pub async fn build_ui( } }; + // add html to source here after parse_html() + { + let mut page_source = tab.page_source.borrow_mut(); + page_source.add_file("index.html".to_string(), source_html.to_string()); + } + let head_elements = match head.element() { Some(ok) => ok, None => { @@ -166,6 +172,7 @@ pub async fn build_ui( } } + //css is pushed to css variable inside render_head() css.push_str(&html_view.style()); for element in body_elements.children.iter() { @@ -210,12 +217,22 @@ pub async fn build_ui( let tagss = Rc::clone(&tags); if !src.is_empty() { - let luacode = if src.starts_with("https://") { - fetch_file(src).await + + let src_clone = src.clone(); + + let luacode = if src_clone.starts_with("https://") { + fetch_file(src_clone).await } else { - fetch_file(format!("{}/{}", furl, src)).await + fetch_file(format!("{}/{}", furl, src_clone)).await }; + //add lua code to page source + { + let src_clone = src.clone(); + let mut page_source = tab.page_source.borrow_mut(); + page_source.add_file(src_clone.to_string(), luacode.to_string()); + } + if let Err(e) = super::lua::run(luacode, tags, tab.url.clone()).await { println!("ERROR: Failed to run lua: {}", e); } @@ -274,6 +291,9 @@ async fn render_head(element: &Element, contents: Option<&Node>, tab: Rc>, // id: String, } @@ -149,6 +152,11 @@ fn handle_search_update( tab_in_closure.url = dns_url; } + //clear page_source info for tab before fetching new page files + //enclosed to let borrowed mut go out of scope + let mut page_source_in_closure = tab_in_closure.page_source.borrow_mut(); + page_source_in_closure.clear(); + searchbar_mut.set_text(&url.replace("buss://", "")); searchbar_mut.set_position(-1); @@ -186,6 +194,7 @@ fn get_time() -> String { fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>) { let history = Rc::new(RefCell::new(History::new())); + let page_source = Rc::new(RefCell::new(PageSource::new())); let default_url = if let Some(dev_build) = args.borrow().get(1) { // cli dev_build.to_string() @@ -221,7 +230,8 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); let event_controller = gtk::EventControllerKey::new(); let history_ = Rc::clone(&history); + let page_source_ = Rc::clone(&page_source); + + // let lua_logs_showing = Rc::new(RefCell::new(false)); + // let settings_showing = Rc::new(RefCell::new(false)); + // let history_showing = Rc::new(RefCell::new(false)); + + let source_viewer_showing = Rc::new(RefCell::new(false)); + let source_viewer_window: Rc>> = Rc::new(RefCell::new(None)); + + let source_viewer_showing_ = source_viewer_showing.clone(); + let source_viewer_window_ = source_viewer_window.clone(); event_controller.connect_key_pressed(move |_, key, _a, b| { let app_clone = Rc::clone(&app_); let history_clone = Rc::clone(&history_); + let page_source_clone = Rc::clone(&page_source_); + + let source_viewer_showing_clone = source_viewer_showing_.clone(); + let mut source_viewer_window_ref = source_viewer_window_.borrow_mut(); if b == (gdk::ModifierType::SHIFT_MASK | gdk::ModifierType::CONTROL_MASK) && key == gdk::Key::P @@ -284,6 +309,17 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); search.connect_activate({ + let rc_scroll_search = rc_scroll.clone(); + let rc_css_provider_search = rc_css_provider.clone(); + let rc_tab_search = rc_tab.clone(); let history = history.clone(); let go_forward = go_forward.clone(); let go_back = go_back.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); + move |query| { update_buttons(&go_back, &go_forward, &history); handle_search_update( @@ -348,18 +392,33 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); refresh_button.connect_clicked({ + let rc_scroll_refresh = rc_scroll.clone(); + let rc_css_provider_refresh = rc_css_provider.clone(); + let rc_tab_refresh = rc_tab.clone(); + let rc_search_refresh = rc_search.clone(); let history = history.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); history .borrow_mut() .add_to_history(rc_search_refresh.borrow().text().to_string(), get_time(), true); @@ -370,17 +429,32 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); home_button.connect_clicked({ - let history = history.clone(); + let rc_scroll_home = rc_scroll.clone(); + let rc_css_provider_home = rc_css_provider.clone(); + let rc_tab_home = rc_tab.clone(); + let rc_search_home = rc_search.clone(); + let history = history.clone(); let go_forward = go_forward.clone(); let go_back = go_back.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); move |_button| { rc_search_home.borrow_mut().set_text(DEFAULT_URL); history @@ -393,17 +467,32 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); go_back.connect_clicked({ + let rc_scroll_back = rc_scroll.clone(); + let rc_css_provider_back = rc_css_provider.clone(); + let rc_tab_back = rc_tab.clone(); + let rc_search_back = rc_search.clone(); let history = history.clone(); let go_forward = go_forward.clone(); let go_back = go_back.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); move |_| { history.borrow_mut().go_back(); update_buttons(&go_back, &go_forward, &history); @@ -415,17 +504,32 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); go_forward.connect_clicked({ + let rc_scroll_forward = rc_scroll.clone(); + let rc_css_provider_forward = rc_css_provider.clone(); + let rc_tab_forward = rc_tab.clone(); + let rc_search_forward = rc_search.clone(); let history = history.clone(); let go_forward = go_forward.clone(); let go_back = go_back.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); move |_| { history.borrow_mut().go_forward(); update_buttons(&go_back, &go_forward, &history); @@ -437,6 +541,17 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); gesture_back.connect_pressed({ + let rc_scroll_back = rc_scroll.clone(); + let rc_css_provider_back = rc_css_provider.clone(); + let rc_tab_back = rc_tab.clone(); + let rc_search_back = rc_search.clone(); let history = history.clone(); let go_forward = go_forward.clone(); let go_back = go_back.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); move |gesture_back, n, _x, _y| { gesture_back.set_state(gtk::EventSequenceState::Claimed); @@ -468,6 +586,17 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>>, config: Rc> = Rc::new(RefCell::new(app.clone())); gesture_forward.connect_pressed({ + let rc_scroll_forward = rc_scroll.clone(); + let rc_css_provider_forward = rc_css_provider.clone(); + let rc_tab_forward = rc_tab.clone(); + let rc_search_forward = rc_search.clone(); let history = history.clone(); let go_forward = go_forward.clone(); let go_back = go_back.clone(); + let source_viewer_window_ = source_viewer_window.clone(); + let source_viewer_showing_= source_viewer_showing.clone(); + let page_source_ = page_source.clone(); move |gesture_forward, n, _x, _y|{ gesture_forward.set_state(gtk::EventSequenceState::Claimed); @@ -501,12 +633,24 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc, mut tabs: Vec, default_url: String, + page_source: Rc>, ) -> Tab { // let tabid = gen_tab_id(); @@ -589,6 +734,7 @@ fn make_tab( // id: tabid, label_widget: tabname, icon_widget: tabicon, + page_source: page_source }; tabs.push(res.clone()); @@ -709,6 +855,94 @@ fn fetch_dns(url: String) -> String { } } +fn display_source_viewer(app: &Rc>, page_source: Rc>, showing: Rc>) -> Window{ + + let window: Window = Object::builder() + .property("application", glib::Value::from(&*app.borrow_mut())) + .build(); + + window.set_default_size(700, 1000); + + // Create the main container box with horizontal orientation + let main_box = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .spacing(6) + .margin_top(6) + .margin_bottom(6) + .margin_start(6) + .margin_end(6) + .build(); + + // Create the menu box for the left side + let menu_box = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .spacing(6) + .width_request(140) + .build(); + + // scroller for text area + let content_scroll = gtk::ScrolledWindow::builder().build(); + + let content_text_view = gtk::TextView::builder() + .wrap_mode(gtk::WrapMode::Word) + .editable(false) + .hexpand(true) + .build(); + + content_scroll.set_child(Some(&content_text_view)); + + // let files = page_source.get_files(); + + // create buffers and listeners to update the text area buffer + let content_buffer = content_text_view.buffer(); + + for file in page_source.borrow().get_files() { + + let button = gtk::Button::with_label(file.get(0).expect("")); + + let file_clone = file.clone(); + + button.connect_clicked({ + let content_buffer = content_buffer.clone(); + + move |_| { + content_buffer.set_text(file_clone.get(1).expect("")); + } + }); + + menu_box.append(&button); + } + + // Add menu box and content area to the main box + main_box.append(&menu_box); + main_box.append(&content_scroll); + + window.set_child(Some(&main_box)); + + let label = gtk::Label::new(Some("Source")); + let empty_label = gtk::Label::new(Some("")); + let headerbar = gtk::HeaderBar::builder().build(); + + headerbar.pack_start(&label); + headerbar.set_title_widget(Some(&empty_label)); + + window.set_titlebar(Some(&headerbar)); + + let showing_clone = showing.clone(); + window.connect_close_request(move |_|{ + + *showing_clone.borrow_mut() = false; + + gtk::glib::Propagation::Proceed + }); + + window.present(); + + *showing.borrow_mut() = true; + + window +} + fn display_lua_logs(app: &Rc>) { let window: Window = Object::builder() .property("application", glib::Value::from(&*app.borrow_mut())) diff --git a/napture/src/page_source_mod/mod.rs b/napture/src/page_source_mod/mod.rs new file mode 100644 index 00000000..e7d37124 --- /dev/null +++ b/napture/src/page_source_mod/mod.rs @@ -0,0 +1,25 @@ +#[derive(Debug)] +pub struct PageSource { + files: Vec>, +} + +impl PageSource { + pub fn new() -> Self { + PageSource { + files: Vec::new(), + } + } + + pub fn add_file(&mut self, name: String, contents: String){ + let file = vec![name, contents]; + self.files.push(file); + } + + pub fn get_files(&self) -> &Vec>{ + &self.files + } + + pub fn clear(&mut self){ + self.files.clear(); + } +} \ No newline at end of file From 6ff7392a55eb04db4124e6588866d116d7bda7ef Mon Sep 17 00:00:00 2001 From: Nocturnalx Date: Tue, 11 Jun 2024 17:23:19 +0100 Subject: [PATCH 4/5] didnt check my final tweaks before last comit, this fixes mut borrow issue --- napture/src/b9/html.rs | 6 ++++-- napture/src/main.rs | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/napture/src/b9/html.rs b/napture/src/b9/html.rs index 54cc47b9..a085c0c4 100644 --- a/napture/src/b9/html.rs +++ b/napture/src/b9/html.rs @@ -291,8 +291,10 @@ async fn render_head(element: &Element, contents: Option<&Node>, tab: Rc Date: Wed, 12 Jun 2024 11:05:27 +0100 Subject: [PATCH 5/5] changes to default window sizing --- napture/src/main.rs | 98 +++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/napture/src/main.rs b/napture/src/main.rs index da50f994..0b7f2537 100644 --- a/napture/src/main.rs +++ b/napture/src/main.rs @@ -342,7 +342,7 @@ fn build_ui(app: &adw::Application, args: Rc>>, config: Rc>>, config: Rc>>, config: Rc>, page_source: Rc