-
Notifications
You must be signed in to change notification settings - Fork 40
Add image viewer widget #565
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
base: main
Are you sure you want to change the base?
Changes from 52 commits
e51b874
f323303
e1d2aaf
e4fe2c8
440bde3
d029bbc
ddd04b9
d641657
9fe9ddc
27ebbd7
92d78b3
de263cc
43137a1
03e4120
c9f2484
81cf00a
ec774a0
d85a312
09b9772
8269f0a
6ea6026
4e4f34d
ee6b8e7
0e10331
4febe14
4efdf4b
85cfb9b
5188571
c3cfc21
932c318
9bd6dbb
048c3d3
816fae5
f0cecc1
2ca47a3
082de67
bdf8cfc
68179c5
e55568c
30ca041
1a35f45
964b798
1136030
897952c
571c888
b43a96e
b4f81ab
dd6555b
9226992
784a08b
89d01b6
348b6c5
8ae8291
75a7ce1
932036c
b24a3d1
1c66b16
baf936a
69a2a7f
e4f53c0
5648d1e
378760a
0c1fb66
555e883
7e4f899
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,92 @@ | ||
| use makepad_widgets::*; | ||
| use matrix_sdk_ui::timeline::EventTimelineItem; | ||
| use matrix_sdk::{ | ||
| media::MediaFormat, ruma::{ | ||
| events::room::message::MessageType, | ||
| OwnedMxcUri | ||
| } | ||
| }; | ||
| use reqwest::StatusCode; | ||
|
|
||
| use crate::{media_cache::{MediaCache, MediaCacheEntry}, shared::{avatar::{AvatarRef, AvatarWidgetRefExt}, image_viewer::{ImageViewerAction, ImageViewerError, LoadState}}}; | ||
|
|
||
| /// Populates the image viewer modal with the given media content. | ||
| /// | ||
| /// If the media is already cached, it will be immediately displayed. | ||
| /// If the media is not cached, it will be fetched from the server. | ||
| /// If the media fetch fails, an error message will be displayed. | ||
| /// | ||
| /// This function requires passing in a reference to `Cx`, which isn't used, but acts as a guarantee that this function must only be called by the main UI thread. | ||
| pub fn populate_matrix_image_modal( | ||
| cx: &mut Cx, | ||
| mxc_uri: OwnedMxcUri, | ||
| media_cache: &mut MediaCache, | ||
| ) { | ||
| // Try to get media from cache or trigger fetch | ||
| let media_entry = media_cache.try_get_media_or_fetch(mxc_uri.clone(), MediaFormat::File); | ||
|
|
||
| // Handle the different media states | ||
| match media_entry { | ||
| (MediaCacheEntry::Loaded(data), MediaFormat::File) => { | ||
| cx.action(ImageViewerAction::Show(LoadState::Loaded(data))); | ||
| } | ||
| (MediaCacheEntry::Failed(status_code), MediaFormat::File) => { | ||
| let error = match status_code { | ||
| StatusCode::NOT_FOUND => ImageViewerError::NotFound, | ||
| StatusCode::INTERNAL_SERVER_ERROR => ImageViewerError::ConnectionFailed, | ||
| StatusCode::PARTIAL_CONTENT => ImageViewerError::BadData, | ||
| StatusCode::UNAUTHORIZED => ImageViewerError::Unauthorized, | ||
| StatusCode::REQUEST_TIMEOUT => ImageViewerError::Timeout, | ||
| _ => ImageViewerError::Unknown, | ||
| }; | ||
| cx.action(ImageViewerAction::Show(LoadState::Error(error))); | ||
| // Remove failed media entry from cache for MediaFormat::File so as to start all over again from loading Thumbnail. | ||
| media_cache.remove_cache_entry(&mxc_uri, Some(MediaFormat::File)); | ||
| } | ||
| _ => {} | ||
| } | ||
| } | ||
|
|
||
| /// Extracts image name and size from an event timeline item. | ||
| pub fn extract_image_info(event_tl_item: &EventTimelineItem) -> (String, i32) { | ||
|
||
| if let Some(message) = event_tl_item.content().as_message() { | ||
| if let MessageType::Image(image_content) = message.msgtype() { | ||
| let name = message.body().to_string(); | ||
| let size = image_content | ||
| .info | ||
| .as_ref() | ||
| .and_then(|info| info.size) | ||
| .map(|s| i32::try_from(s).unwrap_or_default()) | ||
| .unwrap_or(0); | ||
| (name, size) | ||
| } else { | ||
| ("Unknown Image".to_string(), 0) | ||
| } | ||
| } else { | ||
| ("Unknown Image".to_string(), 0) | ||
| } | ||
|
||
| } | ||
|
|
||
| /// Condensed message does not have a profile, so we need to find the previous portal list item. | ||
| /// Searches backwards for a non-empty display name and avatar in previous portal list items. | ||
| /// Mutates display_name and avatar_ref. | ||
| /// Returns when first non-empty display name is found. | ||
| pub fn find_previous_profile_in_condensed_message( | ||
|
||
| portal_list: &PortalListRef, | ||
| mut current_index: usize, | ||
| display_name: &mut String, | ||
| avatar_ref: &mut AvatarRef, | ||
| ) { | ||
| // Start from the current index and work backwards | ||
| while current_index > 0 { | ||
| current_index -= 1; | ||
| if let Some((_id, item_ref)) = portal_list.get_item(current_index) { | ||
| let username = item_ref.label(ids!(content.username_view.username)).text(); | ||
| if !username.is_empty() { | ||
| *display_name = username; | ||
| *avatar_ref = item_ref.avatar(ids!(profile.avatar)); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.