From: Olaf Wintermann Date: Sat, 1 Aug 2026 07:34:46 +0000 (+0200) Subject: add webview preview to file notes X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=59dd09a3212730a2cba8406316899c428fb8fe31;p=note.git add webview preview to file notes --- diff --git a/Cargo.lock b/Cargo.lock index 9c387f4..8fe7708 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1581,6 +1581,7 @@ dependencies = [ "sea-orm", "tokio", "ui-rs", + "url", ] [[package]] diff --git a/application/note/Cargo.toml b/application/note/Cargo.toml index 4a7e28f..5bd627c 100644 --- a/application/note/Cargo.toml +++ b/application/note/Cargo.toml @@ -10,3 +10,4 @@ ui-rs = { path = "../../ui-rs" } tokio = { version = "1.52.1", features = ["rt-multi-thread"] } sea-orm = { version = "2.0.0-rc", features = [ "sqlx-sqlite", "sqlx-postgres", "runtime-tokio-native-tls", "macros" ] } notify = "9.0.0-rc.4" +url = "2" diff --git a/application/note/src/file.rs b/application/note/src/file.rs index a84be06..bf357bb 100644 --- a/application/note/src/file.rs +++ b/application/note/src/file.rs @@ -29,6 +29,7 @@ use std::ffi::{OsStr}; use std::mem; use std::path::{Path, PathBuf}; use std::rc::Rc; +use url::Url; use backend::backend::{BackendHandle, BroadcastMessage, NoteId, NoteTitleUpdate, OpenExternResult}; use ui_rs::{action, doc_cast, ui_actions, UiModel}; use ui_rs::ui::*; @@ -61,6 +62,9 @@ pub struct FileNote { #[bind("filenote_image")] pub image: UiImage, + + #[bind("filenote_webview")] + pub webview: UiWeb, } #[ui_actions] @@ -82,6 +86,7 @@ impl FileNote { preview_tab: Default::default(), note_nodename: Default::default(), image: Default::default(), + webview: Default::default() } } @@ -117,13 +122,21 @@ impl FileNote { // TODO: implement better file type detection // idealy save content type in the note match path.extension().and_then(OsStr::to_str) { - Some("png") => { + Some("png" | "jpeg" | "jpg" | "webp") => { let result = note.image.load_image_file(path.as_path()); if result.is_ok() { // TODO: replace 1 with enum value note.preview_tab.set(1); } }, + Some("html" | "htm" | "pdf") => { + let url = Url::from_file_path(&path); + if let Ok(url) = url { + note.webview.load_url(url.as_str()); + // TODO: replace 1 with enum value + note.preview_tab.set(2); + } + } _ => {} } diff --git a/application/note/src/window.rs b/application/note/src/window.rs index 3e20493..2ca11a5 100644 --- a/application/note/src/window.rs +++ b/application/note/src/window.rs @@ -28,7 +28,7 @@ use std::any::Any; use backend::backend::{BackendHandle, BroadcastMessage, NoteId}; -use ui_rs::{action, button, grid, hbox, imageviewer, label, sourcelist, tableview, tabview, textarea, textfield, ui_actions, UiModel}; +use ui_rs::{action, button, grid, hbox, imageviewer, label, sourcelist, tableview, tabview, textarea, textfield, ui_actions, webview, UiModel}; use ui_rs::ui::*; use crate::{App, AppStates}; use entity::collection::{CollectionType, Model as Collection, Node}; @@ -284,6 +284,11 @@ pub fn create_window(app: &App, ctx: &AppContext) -> UiObject Default for UiList { diff --git a/ui-rs/src/ui/webview.rs b/ui-rs/src/ui/webview.rs index 1ddaa9d..8d572f7 100644 --- a/ui-rs/src/ui/webview.rs +++ b/ui-rs/src/ui/webview.rs @@ -28,6 +28,45 @@ #![allow(dead_code)] +#[macro_export] +macro_rules! webview { + ($parent:expr, $($tt:tt)*) => { + $crate::widget!($parent, webview, $($tt)*) + }; +} + +impl UiWeb { + pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { + let c_string = name.map(|n| CString::new(n).unwrap()); + let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + unsafe { + self.ptr = toolkit::ui_generic_new(ctx.ptr, c_str); + } + } + + pub fn load_url(&self, url: &str) { + let cstr = CString::new(url).unwrap(); + unsafe { + ui_webview_load_url(self.ptr, cstr.as_ptr()); + } + } + + pub fn load_content(&self, uri: Option<&str>, content: &[u8], mimetype: Option<&str>, encoding: Option<&str>) { + let cstr_uri = uri.map(|n| CString::new(n).unwrap()); + let uri_ptr = cstr_uri.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + + let cstr_mime = mimetype.map(|n| CString::new(n).unwrap()); + let mime_ptr = cstr_mime.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + + let cstr_enc = encoding.map(|n| CString::new(n).unwrap()); + let enc_ptr = cstr_enc.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + + unsafe { + ui_webview_load_content(self.ptr, uri_ptr, content.as_ptr().cast(), content.len() as libc::size_t, mime_ptr, enc_ptr); + } + } +} + pub struct WebView { ptr: *mut c_void } @@ -163,7 +202,7 @@ impl<'a, T> WebViewBuilder<'a, T> { self } - pub fn value(&mut self, value: &toolkit::UiImage) -> &mut Self{ + pub fn value(&mut self, value: &toolkit::UiWeb) -> &mut Self{ unsafe { ui_webview_args_set_value(self.args, value.ptr); } @@ -204,7 +243,7 @@ impl toolkit::UiObject { /* -------------------------------- C functions -------------------------------- */ use std::ffi::{c_char, c_double, c_int, c_void, CString}; -use crate::ui::{ffi, toolkit}; +use crate::ui::{ffi, toolkit, UiContext, UiWeb}; use crate::ui::ffi::UiWebviewArgs; use crate::ui::widget::Widget; @@ -243,4 +282,13 @@ unsafe extern "C" { fn ui_webview_args_set_states(args: *mut UiWebviewArgs, states: *const c_int, numstates: c_int); fn ui_webview_args_set_visibility_states(args: *mut UiWebviewArgs, states: *const c_int, numstates: c_int); fn ui_webview_args_free(args: *mut UiWebviewArgs); + + fn ui_webview_load_url(obj: *mut ffi::UiGeneric, url: *const c_char); + fn ui_webview_load_content( + obj: *mut ffi::UiGeneric, + uri: *const c_char, + content: *const c_char, + contentlen: libc::size_t, + mimetype: *const c_char, + encoding: *const c_char); }