-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update(FilePreview): Open image preview in high quality #1698
Changes from all commits
a5948b0
d3b5fe4
20d35a8
883c1da
6bc2362
b18b0e3
a2978d3
24808b4
6e16101
fbbdd75
4247933
252dcbf
372e703
ae41ffb
a92565a
ea3c0b4
a092616
a4a82b1
409db76
07ebf60
12399d2
05c107c
54ad231
20f81aa
7bace92
ae88525
c0ee8ec
730d988
b689aba
53a6efe
14e41b6
482a31c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
pub fn download_file_for_better_preview(file_name: String) { | ||
let file_name_with_extension = format!("{}", cx.props.filename); | ||
let temp_dir = STATIC_ARGS.temp_files.join(file_name_with_extension); | ||
if !temp_dir.exists() { | ||
cx.props.on_press.call(Some(temp_dir.clone())); | ||
} | ||
let temp_path_as_string = temp_dir.clone().to_string_lossy().to_string(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub const IMAGE_MAX_WIDTH: &str = "80vw"; | ||
|
||
pub const IMAGE_MAX_HEIGHT: &str = "80vh"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
use dioxus::prelude::*; | ||
|
||
pub struct LifeCycle<D: FnOnce()> { | ||
ondestroy: Option<D>, | ||
} | ||
|
||
/// It works like a useEffect hook, but it will be called only once | ||
/// when the component is mounted | ||
/// and when the component is unmounted | ||
pub fn use_component_lifecycle<C: FnOnce() + 'static, D: FnOnce() + 'static>( | ||
cx: &ScopeState, | ||
create: C, | ||
destroy: D, | ||
) -> &LifeCycle<D> { | ||
cx.use_hook(|| { | ||
cx.spawn(async move { | ||
// This will be run once the component is mounted | ||
std::future::ready::<()>(()).await; | ||
create(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something ive overlooked here is that youre calling this in a async task. While im not sure what the context behind it might be for every use case, if blocking functions are called, it might be best to spawn a blocking task here so it does not block the executor by using |
||
}); | ||
LifeCycle { | ||
ondestroy: Some(destroy), | ||
} | ||
}) | ||
} | ||
|
||
impl<D: FnOnce()> Drop for LifeCycle<D> { | ||
fn drop(&mut self) { | ||
let f = self.ondestroy.take().unwrap(); | ||
f(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
use std::path::PathBuf; | ||
|
||
/// It will work to load local files in img or video tags, but will ignore drive | ||
const PREFIX_TO_WORK_ON_ALL_OS: &str = "http://dioxus."; | ||
|
||
/// This function is used to treat local file path if it needs | ||
/// to be loaded in img or video tags for example | ||
pub fn get_fixed_path_to_load_local_file(path: PathBuf) -> String { | ||
format!( | ||
"{}{}", | ||
PREFIX_TO_WORK_ON_ALL_OS, | ||
path.to_string_lossy().to_string().replace('\\', "/") | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub mod img_dimensions_preview; | ||
pub mod lifecycle; | ||
pub mod local_file_path; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,17 @@ | ||
use std::ffi::OsStr; | ||
use std::fs; | ||
use std::path::PathBuf; | ||
|
||
use crate::elements::button::Button; | ||
use crate::elements::Appearance; | ||
use crate::layout::modal::Modal; | ||
use common::icons::outline::Shape as Icon; | ||
use common::icons::Icon as IconElement; | ||
use common::utils::img_dimensions_preview::IMAGE_MAX_HEIGHT; | ||
use common::utils::img_dimensions_preview::IMAGE_MAX_WIDTH; | ||
use common::utils::lifecycle::use_component_lifecycle; | ||
use common::utils::local_file_path::get_fixed_path_to_load_local_file; | ||
use common::STATIC_ARGS; | ||
use dioxus_html::input_data::keyboard_types::Modifiers; | ||
|
||
use dioxus::prelude::*; | ||
|
@@ -54,7 +60,7 @@ pub struct Props<'a> { | |
download_pending: Option<bool>, | ||
|
||
// called shen the icon is clicked | ||
on_press: EventHandler<'a, ()>, | ||
on_press: EventHandler<'a, Option<PathBuf>>, | ||
|
||
progress: Option<&'a Progression>, | ||
} | ||
|
@@ -156,6 +162,17 @@ pub fn FileEmbed<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> { | |
let thumbnail = cx.props.thumbnail.clone().unwrap_or_default(); | ||
let large_thumbnail = thumbnail.clone(); // TODO: This should be the source of the image | ||
let has_thumbnail = !thumbnail.is_empty(); | ||
let file_name_with_extension = cx.props.filename.to_string(); | ||
let temp_dir = STATIC_ARGS.temp_files.join(file_name_with_extension); | ||
let temp_dir2 = temp_dir.clone(); | ||
|
||
use_component_lifecycle( | ||
cx, | ||
|| {}, | ||
move || { | ||
let _ = fs::remove_file(temp_dir2.clone()); | ||
}, | ||
); | ||
|
||
cx.render(rsx! ( | ||
div { | ||
|
@@ -184,23 +201,30 @@ pub fn FileEmbed<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> { | |
aria_label: "file-icon", | ||
if has_thumbnail { | ||
rsx!( | ||
fullscreen_preview.then(|| rsx!( | ||
Modal { | ||
open: *fullscreen_preview.clone(), | ||
onclose: move |_| fullscreen_preview.set(false), | ||
transparent: false, | ||
close_on_click_inside_modal: true, | ||
dont_pad: true, | ||
img { | ||
id: "image-preview-modal-file-embed", | ||
aria_label: "image-preview-modal-file-embed", | ||
src: "{large_thumbnail}", | ||
max_height: "80vh", | ||
max_width: "80vw", | ||
onclick: move |e| e.stop_propagation(), | ||
}, | ||
fullscreen_preview.then(|| { | ||
if !temp_dir.exists() { | ||
cx.props.on_press.call(Some(temp_dir.clone())); | ||
} | ||
)), | ||
let temp_file_path_as_string = get_fixed_path_to_load_local_file(temp_dir.clone()); | ||
rsx!( | ||
Modal { | ||
open: *fullscreen_preview.clone(), | ||
onclose: move |_| fullscreen_preview.set(false), | ||
transparent: false, | ||
close_on_click_inside_modal: true, | ||
dont_pad: true, | ||
img { | ||
id: "image-preview-modal-file-embed", | ||
aria_label: "image-preview-modal-file-embed", | ||
src: format_args!("{}", if temp_dir.exists() | ||
{ temp_file_path_as_string} | ||
else {large_thumbnail} ), | ||
Comment on lines
+219
to
+221
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You may be able to avoid using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, I will fix it. |
||
max_height: IMAGE_MAX_HEIGHT, | ||
max_width: IMAGE_MAX_WIDTH, | ||
onclick: move |e| e.stop_propagation(), | ||
}, | ||
} | ||
)}), | ||
div { | ||
class: "image-container", | ||
aria_label: "message-image-container", | ||
|
@@ -347,7 +371,7 @@ fn show_download_button_if_enabled<'a>( | |
icon: btn_icon, | ||
appearance: Appearance::Primary, | ||
aria_label: "attachment-button".into(), | ||
onpress: move |_| cx.props.on_press.call(()), | ||
onpress: move |_| cx.props.on_press.call(None), | ||
} | ||
} | ||
)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, does the task need to yield first before calling
create
?