Fullscreen MediaViewer refactor

- Moved media related logic into notedeck instead of the ui crate,
  since they pertain to Images/ImageCache based systems

- Made RenderableMedia owned to make it less of a nightmware
  to work with and the perf should be negligible

- Added a ImageMetadata cache to Images. This is referenced
  whenever we encounter an image so we don't have to
  redo the work all of the time

- Relpaced our ad-hoc, hand(vibe?)-coded panning and zoom logic
  with the Scene widget, which is explicitly designed for
  this use case

- Extracted and detangle fullscreen media rendering from inside of note
  rendering.  We instead let the application decide what action they
  want to perform when note media is clicked on.

- We add an on_view_media action to MediaAction for the application to
  handle. The Columns app uses this toggle a FullscreenMedia app
  option bits whenever we get a MediaAction::ViewMedis(urls).

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2025-07-25 13:45:54 -07:00
parent 96ab4ee681
commit 3d18db8fd2
45 changed files with 1284 additions and 1222 deletions

View File

@@ -20,9 +20,12 @@ use enostr::{ClientMessage, PoolRelay, Pubkey, RelayEvent, RelayMessage, RelayPo
use nostrdb::Transaction;
use notedeck::{
tr, ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState,
Localization, UnknownIds,
Images, JobsCache, Localization, UnknownIds,
};
use notedeck_ui::{
media::{MediaViewer, MediaViewerState},
NoteOptions,
};
use notedeck_ui::{jobs::JobsCache, NoteOptions};
use std::collections::{BTreeSet, HashMap};
use std::path::Path;
use std::time::Duration;
@@ -365,12 +368,43 @@ fn render_damus(
render_damus_desktop(damus, app_ctx, ui)
};
fullscreen_media_viewer_ui(
ui,
&mut damus.options,
&mut damus.view_state.media_viewer,
app_ctx.img_cache,
);
// We use this for keeping timestamps and things up to date
ui.ctx().request_repaint_after(Duration::from_secs(5));
app_action
}
/// Present a fullscreen media viewer if the FullscreenMedia AppOptions flag is set. This is
/// typically set by image carousels using a MediaAction's on_view_media callback when
/// an image is clicked
fn fullscreen_media_viewer_ui(
ui: &mut egui::Ui,
options: &mut AppOptions,
viewer_state: &mut MediaViewerState,
img_cache: &mut Images,
) {
if !options.contains(AppOptions::FullscreenMedia) || viewer_state.urls.is_empty() {
return;
}
// Close it?
if ui.input(|i| i.key_pressed(egui::Key::Escape)) {
options.set(AppOptions::FullscreenMedia, false);
return;
}
MediaViewer::new(viewer_state)
.fullscreen(true)
.ui(img_cache, ui);
}
/*
fn determine_key_storage_type() -> KeyStorageType {
#[cfg(target_os = "macos")]