Skip to content

Conversation

@alanpoon
Copy link
Contributor

@alanpoon alanpoon commented Aug 6, 2025

Fixes #327
Screenshot 2025-08-06 at 5 46 55 PM

in replacement of #443

Waiting for this PR to be merged: makepad/makepad#788.

@alanpoon alanpoon self-assigned this Aug 6, 2025
@alanpoon alanpoon added the blocked-on-makepad Blocked on a Makepad bug or missing Makepad feature label Aug 11, 2025
@alanpoon
Copy link
Contributor Author

Intention of adding an image magnifier and the ability to pan image.

The image's image_scale, image_pan will always be set to default in draw_walk. Hence unable to dynamically scale and pan image.
makepad/makepad#785

@kevinaboos
Copy link
Member

Intention of adding an image magnifier and the ability to pan image.

The image's image_scale, image_pan will always be set to default in draw_walk. Hence unable to dynamically scale and pan image. makepad/makepad#785

@alanpoon I just checked with Rik, and this line should not be present in the Image widget. It's some errant code left over from dealing with animations in a strange way.

You can submit a PR to makepad that removes that line, and then continue with this issue here.

@kevinaboos kevinaboos added waiting-on-author This issue is waiting on the original author for a response and removed blocked-on-makepad Blocked on a Makepad bug or missing Makepad feature labels Oct 17, 2025
@alanpoon
Copy link
Contributor Author

Sure, the makepad PR is here: makepad/makepad#788

@alanpoon
Copy link
Contributor Author

Screenshot 2025-10-19 at 10 58 51 AM Screenshot 2025-10-19 at 10 58 57 AM Screenshot 2025-10-19 at 10 59 17 AM

@alanpoon alanpoon added waiting-on-review This issue is waiting to be reviewed and removed waiting-on-author This issue is waiting on the original author for a response labels Oct 19, 2025
Copy link
Member

@kevinaboos kevinaboos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Alan, nice work here.

My main comment is that we should decouple the ImageViewer widget from the RoomScreen. It doesn't need to know anything about the RoomScreen except for being able to access the RoomScreen's MediaCache instance (technically even that is not required, see Aarav's PR for an example of just passing the image data directly from the media fetch background task to the ImageViewer via an action).

Also, Aarav and I had a lot of discussions about using actions to communicate with the ImageViewer widget in PR#443. I think you can combine your approach (of storing images in the RoomScreen's MediaCache) with the action-based design from #443 (in which you emit an action including the image data/status instead of directly accessing the widget and calling a function on it). Actions are more idiomatic and also allow easy communication from any context, both in a background task and in a RoomScreen TimelineUpdate handler.

@alanpoon alanpoon added the waiting-on-review This issue is waiting to be reviewed label Nov 13, 2025
Copy link
Member

@kevinaboos kevinaboos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks pretty good, I left mostly nitpick comments but a few are more significant in nature.

Comment on lines 50 to 51
/// Extracts image name and size from an event timeline item.
pub fn extract_image_info(event_tl_item: &EventTimelineItem) -> (String, i32) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. "Extract" makes it sound like you're unarchiving/decompressing a file. I would just call it something like get_image_name_and_filesize or something similar.
  2. The image "size" sounds like a dimension, i'd recommend saying "size in bytes" or something just to be very clear.
  3. How can an image size value be a signed integer? Answer: it cannot, and in the SDK it's a UInt, so you can either use that directly or convert it to a u64.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines 62 to 67
} else {
("Unknown Image".to_string(), 0)
}
} else {
("Unknown Image".to_string(), 0)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dedup these, e.g., by returning early from within the if conditional and then having this as a default return value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines 70 to 74
/// 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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Reading widget values from the UI is an odd way to try to obtain content for a timeline event. I'm not sure what context you have when calling this, but why not just get this info from the event timeline item itself?
  2. Using this style of output parameters is strange and not very rusty. I'd recommend you just return the display_name and the AvatarRef directly instead of mutating them, because that would clearly convey when you were unable to obtain them. Currently, with this function signature, there's no way to know if you successfully obtained those two bits of data, which is a form of silencing errors.
  3. Nit: doc comments are rendered using markdown, so the line separation here gets lost. Generally, you should start the doc comment with a short one-line summary, then a blank line, and then the details in any format you wish.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1-2: Removed this function, and use avatar.set_avatar_and_get_username after retrieving timeline event.
3: Doc fixed.

Comment on lines 1570 to 1571
index: usize,
widget_ref: WidgetRef,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you give these more specific names? I assume index is the index into the portallist of ... something? and what is widget_ref? That could be anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed index to item_id. Removed widget_ref.

/// The error type is matched against a string which describes the error in a way that is visible to the user.
///
/// The strings returned by this function will be appropriate for display in a label or similar widget.
pub fn image_viewer_error_to_string(error: &ImageViewerError) -> &str {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check out the thiserror crate, that's exactly what it's for. You're re-creating a less featureful version of proper error conversion/display.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix by using thiserror crate.

}
}
}
pub Rotation_Button = <RobrixIconButton> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this doesn't follow typical code style, you're combining camel case and snake case. It should be something like RotateButton.

flow: Right

top_left_container = <View> {
width: 150, height: Fit,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this size choice look with longer usernames? 150 pixels seems way too small to fit an avatar, a username, and a timestamp

and what about mobile devices with skinnier screens? Don't forget to test things on a wide variety of view sizes.

Honestly it seems like you might need to rethink this layout. Perhaps something like image name on the top, and then the avatar+username+timestamp on the line beneath that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed top_left_container's width to be 200. Added the logic to empty_right_container's width to 0 when display_context is mobile.

Comment on lines 483 to 491
/// A lock to prevent multiple rotation animations from running at the same time
#[rust]
is_animating_rotation: bool,
#[animator]
animator: Animator,
/// Timer for rotation animation, prevents clicking the rotation buttons too often
/// to start the animation
#[rust]
timer: Timer,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using a "lock" (which is just a bool, not really a lock) plus a timer to prevent multiple simultaneous animations is a very fragile way to achieve this.

Luckily, you don't need any of this. All you have to do is check the state of the animator, and if it is playing an animator, simply ignore additional button presses on the rotate buttons.

Alternatively, if the user clicks the rotate button while the image is already being rotated, you could just cut the animation short and then jump to the next rotation state immediately, and then start another rotation animation again. That is probably a way better UX than some kind of hidden timeout thing.

In general, timers in makepad aren't great and we definitely should not use them for anything related to animations, ever.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use is_animating.

Comment on lines 727 to 737
// Clear the rotated image texture with a white background
if let Ok(image_buffer) = ImageBuffer::new(&[255], 1, 1) {
let texture = image_buffer.into_new_texture(cx);
self.view
.rotated_image(ids!(rotated_image))
.set_texture(cx, Some(texture.clone()));
self.view.rotated_image(ids!(rotated_image)).redraw(cx);
self.view
.image(ids!(metadata_view.top_left_container.avatar.img_view.img))
.set_texture(cx, Some(texture));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it actually necessary to clear the image texture? seems like wasted effort because the image texture will be set/replaced later anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you need to free the texture's memory, just do that. No need to create a new one and actually draw it.

@kevinaboos kevinaboos added waiting-on-author This issue is waiting on the original author for a response and removed waiting-on-review This issue is waiting to be reviewed labels Nov 13, 2025
@alanpoon alanpoon added waiting-on-review This issue is waiting to be reviewed waiting-on-author This issue is waiting on the original author for a response and removed waiting-on-author This issue is waiting on the original author for a response waiting-on-review This issue is waiting to be reviewed labels Nov 17, 2025
@alanpoon alanpoon added waiting-on-review This issue is waiting to be reviewed waiting-on-author This issue is waiting on the original author for a response and removed waiting-on-author This issue is waiting on the original author for a response waiting-on-review This issue is waiting to be reviewed labels Nov 24, 2025
@alanpoon alanpoon added waiting-on-review This issue is waiting to be reviewed and removed waiting-on-author This issue is waiting on the original author for a response labels Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on-review This issue is waiting to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When the user clicks a thumbnail image, show the full-size image in an image viewer widget

2 participants