fix(media): use ScaledTexture
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
use std::{collections::HashMap, path::Path};
|
use std::{collections::HashMap, path::Path};
|
||||||
|
|
||||||
use egui::{
|
use egui::{
|
||||||
Button, Color32, Context, CornerRadius, FontId, Image, Response, RichText, Sense,
|
vec2, Button, Color32, Context, CornerRadius, FontId, Image, Response, RichText, Sense,
|
||||||
TextureHandle, UiBuilder, Window,
|
TextureHandle, UiBuilder, Vec2, Window,
|
||||||
};
|
};
|
||||||
use notedeck::{
|
use notedeck::{
|
||||||
fonts::get_font_size, note::MediaAction, show_one_error_message, supported_mime_hosted_at_url,
|
fonts::get_font_size, note::MediaAction, show_one_error_message, supported_mime_hosted_at_url,
|
||||||
@@ -33,14 +33,17 @@ pub(crate) fn image_carousel(
|
|||||||
) -> Option<MediaAction> {
|
) -> Option<MediaAction> {
|
||||||
// let's make sure everything is within our area
|
// let's make sure everything is within our area
|
||||||
|
|
||||||
let height = 360.0;
|
let size = {
|
||||||
let width = ui.available_width();
|
let height = 360.0;
|
||||||
|
let width = ui.available_width();
|
||||||
|
egui::vec2(width, height)
|
||||||
|
};
|
||||||
|
|
||||||
let show_popup = get_show_popup(ui, popup_id(carousel_id));
|
let show_popup = get_show_popup(ui, popup_id(carousel_id));
|
||||||
let mut action = None;
|
let mut action = None;
|
||||||
|
|
||||||
//let has_touch_screen = ui.ctx().input(|i| i.has_touch_screen());
|
//let has_touch_screen = ui.ctx().input(|i| i.has_touch_screen());
|
||||||
ui.add_sized([width, height], |ui: &mut egui::Ui| {
|
ui.add_sized(size, |ui: &mut egui::Ui| {
|
||||||
egui::ScrollArea::horizontal()
|
egui::ScrollArea::horizontal()
|
||||||
.drag_to_scroll(false)
|
.drag_to_scroll(false)
|
||||||
.id_salt(carousel_id)
|
.id_salt(carousel_id)
|
||||||
@@ -63,7 +66,7 @@ pub(crate) fn image_carousel(
|
|||||||
job_pool,
|
job_pool,
|
||||||
jobs,
|
jobs,
|
||||||
trusted_media,
|
trusted_media,
|
||||||
height,
|
size,
|
||||||
&mut cache.textures_cache,
|
&mut cache.textures_cache,
|
||||||
url,
|
url,
|
||||||
*media_type,
|
*media_type,
|
||||||
@@ -76,7 +79,7 @@ pub(crate) fn image_carousel(
|
|||||||
&mut img_cache.gif_states,
|
&mut img_cache.gif_states,
|
||||||
media_state,
|
media_state,
|
||||||
url,
|
url,
|
||||||
height,
|
size,
|
||||||
i18n,
|
i18n,
|
||||||
) {
|
) {
|
||||||
// clicked the media, lets set the active index
|
// clicked the media, lets set the active index
|
||||||
@@ -90,7 +93,7 @@ pub(crate) fn image_carousel(
|
|||||||
url,
|
url,
|
||||||
*media_type,
|
*media_type,
|
||||||
cache,
|
cache,
|
||||||
ImageType::Content(Some((width as u32, height as u32))),
|
ImageType::Content(Some((size.x as u32, size.y as u32))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +279,7 @@ pub fn get_content_media_render_state<'a>(
|
|||||||
job_pool: &'a mut JobPool,
|
job_pool: &'a mut JobPool,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
media_trusted: bool,
|
media_trusted: bool,
|
||||||
height: f32,
|
size: Vec2,
|
||||||
cache: &'a mut TexturesCache,
|
cache: &'a mut TexturesCache,
|
||||||
url: &'a str,
|
url: &'a str,
|
||||||
cache_type: MediaCacheType,
|
cache_type: MediaCacheType,
|
||||||
@@ -302,7 +305,7 @@ pub fn get_content_media_render_state<'a>(
|
|||||||
obfuscation_type,
|
obfuscation_type,
|
||||||
job_pool,
|
job_pool,
|
||||||
jobs,
|
jobs,
|
||||||
height,
|
size,
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -313,11 +316,11 @@ pub fn get_content_media_render_state<'a>(
|
|||||||
obfuscation_type,
|
obfuscation_type,
|
||||||
job_pool,
|
job_pool,
|
||||||
jobs,
|
jobs,
|
||||||
height,
|
size,
|
||||||
)),
|
)),
|
||||||
notedeck::LoadableTextureState::Error(e) => MediaRenderState::Error(e),
|
notedeck::LoadableTextureState::Error(e) => MediaRenderState::Error(e),
|
||||||
notedeck::LoadableTextureState::Loading { actual_image_tex } => {
|
notedeck::LoadableTextureState::Loading { actual_image_tex } => {
|
||||||
let obfuscation = get_obfuscated(ui, url, obfuscation_type, job_pool, jobs, height);
|
let obfuscation = get_obfuscated(ui, url, obfuscation_type, job_pool, jobs, size);
|
||||||
MediaRenderState::Transitioning {
|
MediaRenderState::Transitioning {
|
||||||
image: actual_image_tex,
|
image: actual_image_tex,
|
||||||
obfuscation,
|
obfuscation,
|
||||||
@@ -335,7 +338,7 @@ fn get_obfuscated<'a>(
|
|||||||
obfuscation_type: ObfuscationType<'a>,
|
obfuscation_type: ObfuscationType<'a>,
|
||||||
job_pool: &'a mut JobPool,
|
job_pool: &'a mut JobPool,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
height: f32,
|
size: Vec2,
|
||||||
) -> ObfuscatedTexture<'a> {
|
) -> ObfuscatedTexture<'a> {
|
||||||
let ObfuscationType::Blurhash(renderable_blur) = obfuscation_type else {
|
let ObfuscationType::Blurhash(renderable_blur) = obfuscation_type else {
|
||||||
return ObfuscatedTexture::Default;
|
return ObfuscatedTexture::Default;
|
||||||
@@ -348,8 +351,8 @@ fn get_obfuscated<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let available_points = PointDimensions {
|
let available_points = PointDimensions {
|
||||||
x: ui.available_width(),
|
x: size.x,
|
||||||
y: height,
|
y: size.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
let pixel_sizes = renderable_blur.scaled_pixel_dimensions(ui, available_points);
|
let pixel_sizes = renderable_blur.scaled_pixel_dimensions(ui, available_points);
|
||||||
@@ -731,12 +734,12 @@ fn render_media(
|
|||||||
gifs: &mut GifStateMap,
|
gifs: &mut GifStateMap,
|
||||||
render_state: MediaRenderState,
|
render_state: MediaRenderState,
|
||||||
url: &str,
|
url: &str,
|
||||||
height: f32,
|
size: egui::Vec2,
|
||||||
i18n: &mut Localization,
|
i18n: &mut Localization,
|
||||||
) -> Option<MediaUIAction> {
|
) -> Option<MediaUIAction> {
|
||||||
match render_state {
|
match render_state {
|
||||||
MediaRenderState::ActualImage(image) => {
|
MediaRenderState::ActualImage(image) => {
|
||||||
if render_success_media(ui, url, image, gifs, height, i18n).clicked() {
|
if render_success_media(ui, url, image, gifs, size, i18n).clicked() {
|
||||||
Some(MediaUIAction::Clicked)
|
Some(MediaUIAction::Clicked)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -744,29 +747,31 @@ fn render_media(
|
|||||||
}
|
}
|
||||||
MediaRenderState::Transitioning { image, obfuscation } => match obfuscation {
|
MediaRenderState::Transitioning { image, obfuscation } => match obfuscation {
|
||||||
ObfuscatedTexture::Blur(texture) => {
|
ObfuscatedTexture::Blur(texture) => {
|
||||||
if render_blur_transition(ui, url, height, texture, image.get_first_texture()) {
|
if render_blur_transition(ui, url, size, texture, image.get_first_texture()) {
|
||||||
Some(MediaUIAction::DoneLoading)
|
Some(MediaUIAction::DoneLoading)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObfuscatedTexture::Default => {
|
ObfuscatedTexture::Default => {
|
||||||
ui.add(texture_to_image(ui, image.get_first_texture(), height));
|
let scaled =
|
||||||
|
ScaledTexture::new(image.get_first_texture(), size, is_narrow(ui.ctx()));
|
||||||
|
ui.add(scaled.get_image());
|
||||||
Some(MediaUIAction::DoneLoading)
|
Some(MediaUIAction::DoneLoading)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MediaRenderState::Error(e) => {
|
MediaRenderState::Error(e) => {
|
||||||
ui.allocate_space(egui::vec2(height, height));
|
ui.allocate_space(size);
|
||||||
show_one_error_message(ui, &format!("Could not render media {url}: {e}"));
|
show_one_error_message(ui, &format!("Could not render media {url}: {e}"));
|
||||||
Some(MediaUIAction::Error)
|
Some(MediaUIAction::Error)
|
||||||
}
|
}
|
||||||
MediaRenderState::Shimmering(obfuscated_texture) => {
|
MediaRenderState::Shimmering(obfuscated_texture) => {
|
||||||
match obfuscated_texture {
|
match obfuscated_texture {
|
||||||
ObfuscatedTexture::Blur(texture_handle) => {
|
ObfuscatedTexture::Blur(texture_handle) => {
|
||||||
shimmer_blurhash(texture_handle, ui, url, height);
|
shimmer_blurhash(texture_handle, ui, url, size);
|
||||||
}
|
}
|
||||||
ObfuscatedTexture::Default => {
|
ObfuscatedTexture::Default => {
|
||||||
render_default_blur_bg(ui, height, url, true);
|
render_default_blur_bg(ui, size, url, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@@ -774,12 +779,12 @@ fn render_media(
|
|||||||
MediaRenderState::Obfuscated(obfuscated_texture) => {
|
MediaRenderState::Obfuscated(obfuscated_texture) => {
|
||||||
let resp = match obfuscated_texture {
|
let resp = match obfuscated_texture {
|
||||||
ObfuscatedTexture::Blur(texture_handle) => {
|
ObfuscatedTexture::Blur(texture_handle) => {
|
||||||
let img = texture_to_image(ui, texture_handle, height);
|
let scaled = ScaledTexture::new(texture_handle, size, is_narrow(ui.ctx()));
|
||||||
|
|
||||||
let resp = ui.add(img);
|
let resp = ui.add(scaled.get_image());
|
||||||
render_blur_text(ui, i18n, url, resp.rect)
|
render_blur_text(ui, i18n, url, resp.rect)
|
||||||
}
|
}
|
||||||
ObfuscatedTexture::Default => render_default_blur(ui, i18n, height, url),
|
ObfuscatedTexture::Default => render_default_blur(ui, i18n, size, url),
|
||||||
};
|
};
|
||||||
|
|
||||||
if resp
|
if resp
|
||||||
@@ -883,20 +888,26 @@ fn render_blur_text(
|
|||||||
fn render_default_blur(
|
fn render_default_blur(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
i18n: &mut Localization,
|
i18n: &mut Localization,
|
||||||
height: f32,
|
size: egui::Vec2,
|
||||||
url: &str,
|
url: &str,
|
||||||
) -> egui::Response {
|
) -> egui::Response {
|
||||||
let rect = render_default_blur_bg(ui, height, url, false);
|
let rect = render_default_blur_bg(ui, size, url, false);
|
||||||
render_blur_text(ui, i18n, url, rect)
|
render_blur_text(ui, i18n, url, rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_default_blur_bg(ui: &mut egui::Ui, height: f32, url: &str, shimmer: bool) -> egui::Rect {
|
fn render_default_blur_bg(
|
||||||
let width = if is_narrow(ui.ctx()) {
|
ui: &mut egui::Ui,
|
||||||
ui.available_width()
|
size: egui::Vec2,
|
||||||
|
url: &str,
|
||||||
|
shimmer: bool,
|
||||||
|
) -> egui::Rect {
|
||||||
|
let size = if is_narrow(ui.ctx()) {
|
||||||
|
size
|
||||||
} else {
|
} else {
|
||||||
height
|
vec2(size.y, size.y)
|
||||||
};
|
};
|
||||||
let (rect, _) = ui.allocate_exact_size(egui::vec2(width, height), egui::Sense::click());
|
|
||||||
|
let (rect, _) = ui.allocate_exact_size(size, egui::Sense::click());
|
||||||
|
|
||||||
let painter = ui.painter_at(rect);
|
let painter = ui.painter_at(rect);
|
||||||
|
|
||||||
@@ -980,30 +991,25 @@ fn render_success_media(
|
|||||||
url: &str,
|
url: &str,
|
||||||
tex: &mut TexturedImage,
|
tex: &mut TexturedImage,
|
||||||
gifs: &mut GifStateMap,
|
gifs: &mut GifStateMap,
|
||||||
height: f32,
|
size: Vec2,
|
||||||
i18n: &mut Localization,
|
i18n: &mut Localization,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let texture = handle_repaint(ui, retrieve_latest_texture(url, gifs, tex));
|
let texture = handle_repaint(ui, retrieve_latest_texture(url, gifs, tex));
|
||||||
let img = texture_to_image(ui, texture, height);
|
|
||||||
|
|
||||||
let img_resp = ui.add(Button::image(img).frame(false));
|
let scaled = ScaledTexture::new(texture, size, is_narrow(ui.ctx()));
|
||||||
|
|
||||||
|
let img_resp = ui.add(Button::image(scaled.get_image()).frame(false));
|
||||||
|
|
||||||
copy_link(i18n, url, &img_resp);
|
copy_link(i18n, url, &img_resp);
|
||||||
|
|
||||||
img_resp
|
img_resp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn texture_to_image<'a>(ui: &egui::Ui, tex: &TextureHandle, max_height: f32) -> egui::Image<'a> {
|
fn texture_to_image<'a>(tex: &TextureHandle, size: Vec2) -> egui::Image<'a> {
|
||||||
let mut img = Image::new(tex)
|
Image::new(tex)
|
||||||
.max_height(max_height)
|
|
||||||
.corner_radius(5.0)
|
.corner_radius(5.0)
|
||||||
.maintain_aspect_ratio(true);
|
.fit_to_exact_size(size)
|
||||||
|
.maintain_aspect_ratio(true)
|
||||||
if is_narrow(ui.ctx()) {
|
|
||||||
img = img.max_width(ui.available_width());
|
|
||||||
}
|
|
||||||
|
|
||||||
img
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BLUR_SHIMMER_ID: fn(&str) -> egui::Id = |url| egui::Id::new(("blur_shimmer", url));
|
static BLUR_SHIMMER_ID: fn(&str) -> egui::Id = |url| egui::Id::new(("blur_shimmer", url));
|
||||||
@@ -1022,11 +1028,11 @@ fn get_blur_current_alpha(ui: &mut egui::Ui, url: &str) -> u8 {
|
|||||||
.animate()
|
.animate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shimmer_blurhash(tex: &TextureHandle, ui: &mut egui::Ui, url: &str, max_height: f32) {
|
fn shimmer_blurhash(tex: &TextureHandle, ui: &mut egui::Ui, url: &str, size: Vec2) {
|
||||||
let cur_alpha = get_blur_current_alpha(ui, url);
|
let cur_alpha = get_blur_current_alpha(ui, url);
|
||||||
|
|
||||||
let scaled = ScaledTexture::new(tex, max_height);
|
let scaled = ScaledTexture::new(tex, size, is_narrow(ui.ctx()));
|
||||||
let img = scaled.get_image(ui);
|
let img = scaled.get_image();
|
||||||
show_blurhash_with_alpha(ui, img, cur_alpha);
|
show_blurhash_with_alpha(ui, img, cur_alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,54 +1054,60 @@ type FinishedTransition = bool;
|
|||||||
fn render_blur_transition(
|
fn render_blur_transition(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
url: &str,
|
url: &str,
|
||||||
max_height: f32,
|
size: Vec2,
|
||||||
blur_texture: &TextureHandle,
|
blur_texture: &TextureHandle,
|
||||||
image_texture: &TextureHandle,
|
image_texture: &TextureHandle,
|
||||||
) -> FinishedTransition {
|
) -> FinishedTransition {
|
||||||
let scaled_texture = ScaledTexture::new(image_texture, max_height);
|
let scaled_texture = ScaledTexture::new(image_texture, size, is_narrow(ui.ctx()));
|
||||||
|
|
||||||
let blur_img = texture_to_image(ui, blur_texture, max_height);
|
let scaled_blur_img = ScaledTexture::new(blur_texture, size, is_narrow(ui.ctx()));
|
||||||
|
|
||||||
match get_blur_transition_state(ui.ctx(), url) {
|
match get_blur_transition_state(ui.ctx(), url) {
|
||||||
BlurTransitionState::StoppingShimmer { cur_alpha } => {
|
BlurTransitionState::StoppingShimmer { cur_alpha } => {
|
||||||
show_blurhash_with_alpha(ui, blur_img, cur_alpha);
|
show_blurhash_with_alpha(ui, scaled_blur_img.get_image(), cur_alpha);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
BlurTransitionState::FadingBlur => render_blur_fade(ui, url, blur_img, &scaled_texture),
|
BlurTransitionState::FadingBlur => {
|
||||||
|
render_blur_fade(ui, url, scaled_blur_img.get_image(), &scaled_texture)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScaledTexture<'a> {
|
struct ScaledTexture<'a> {
|
||||||
tex: &'a TextureHandle,
|
tex: &'a TextureHandle,
|
||||||
max_height: f32,
|
size: Vec2,
|
||||||
pub scaled_size: egui::Vec2,
|
pub scaled_size: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ScaledTexture<'a> {
|
impl<'a> ScaledTexture<'a> {
|
||||||
pub fn new(tex: &'a TextureHandle, max_height: f32) -> Self {
|
pub fn new(tex: &'a TextureHandle, max_size: Vec2, is_narrow: bool) -> Self {
|
||||||
let scaled_size = {
|
let tex_size = tex.size_vec2();
|
||||||
let mut size = tex.size_vec2();
|
|
||||||
|
|
||||||
if size.y > max_height {
|
let scaled_size = if !is_narrow {
|
||||||
let old_y = size.y;
|
if tex_size.y > max_size.y {
|
||||||
size.y = max_height;
|
let scale = max_size.y / tex_size.y;
|
||||||
size.x *= max_height / old_y;
|
tex_size * scale
|
||||||
|
} else {
|
||||||
|
tex_size
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if tex_size.x < max_size.x || tex_size.x > max_size.x {
|
||||||
|
let scale = max_size.x / tex_size.x;
|
||||||
|
tex_size * scale
|
||||||
|
} else {
|
||||||
|
tex_size
|
||||||
}
|
}
|
||||||
|
|
||||||
size
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
tex,
|
tex,
|
||||||
max_height,
|
size: max_size,
|
||||||
scaled_size,
|
scaled_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_image(&self, ui: &egui::Ui) -> Image {
|
pub fn get_image(&self) -> Image {
|
||||||
texture_to_image(ui, self.tex, self.max_height)
|
texture_to_image(self.tex, self.size).fit_to_exact_size(self.scaled_size)
|
||||||
.max_size(self.scaled_size)
|
|
||||||
.shrink_to_fit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1114,7 +1126,7 @@ fn render_blur_fade(
|
|||||||
.animate()
|
.animate()
|
||||||
};
|
};
|
||||||
|
|
||||||
let img = image_texture.get_image(ui);
|
let img = image_texture.get_image();
|
||||||
|
|
||||||
let blur_img = blur_img.tint(fade_color(cur_alpha));
|
let blur_img = blur_img.tint(fade_color(cur_alpha));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user