Skip to content

Attachment upload with file dialog#674

Open
alanpoon wants to merge 32 commits intoproject-robius:mainfrom
alanpoon:image_upload
Open

Attachment upload with file dialog#674
alanpoon wants to merge 32 commits intoproject-robius:mainfrom
alanpoon:image_upload

Conversation

@alanpoon
Copy link
Contributor

Screen.Recording.2026-01-26.at.4.09.11.PM.mov
  • macOS
  • Android
  • Linux
  • Windows

@alanpoon alanpoon self-assigned this Jan 26, 2026
@kevinaboos
Copy link
Member

awesome!

I know this isn't yet complete, but I wanted to quickly drop in and suggest using rfd instead of makepad's internal file API. rfd is the de facto crate for this kind of thing, and I plan to shortly create a robius crate that wraps rfd, so we'll end up with a similar API.

Plus, with rfd you'd get immediate support for all 3 desktop platforms.

@alanpoon
Copy link
Contributor Author

awesome!

I know this isn't yet complete, but I wanted to quickly drop in and suggest using rfd instead of makepad's internal file API. rfd is the de facto crate for this kind of thing, and I plan to shortly create a robius crate that wraps rfd, so we'll end up with a similar API.

Plus, with rfd you'd get immediate support for all 3 desktop platforms.

Kindly refer to this implementation of the rfd. https://github.com/Vjze/YY_DPS/blob/edb15ffc85b646c27547081b30a0e6f0d8ba688b/src/export/export_view.rs#L158 This requires the tokio runtime in a field in export screen

@kevinaboos
Copy link
Member

awesome!
I know this isn't yet complete, but I wanted to quickly drop in and suggest using rfd instead of makepad's internal file API. rfd is the de facto crate for this kind of thing, and I plan to shortly create a robius crate that wraps rfd, so we'll end up with a similar API.
Plus, with rfd you'd get immediate support for all 3 desktop platforms.

Kindly refer to this implementation of the rfd. https://github.com/Vjze/YY_DPS/blob/edb15ffc85b646c27547081b30a0e6f0d8ba688b/src/export/export_view.rs#L158 This requires the tokio runtime in a field in export screen

Ok, what's the issue with that? Is that problematic? Apologies, but I'm not quite sure what point you're trying to make.

Moly has used rfd in their app, works fine AFAIK.

@alanpoon alanpoon added the waiting-on-review This issue is waiting to be reviewed label Jan 30, 2026
@alanpoon alanpoon marked this pull request as ready for review January 30, 2026 16:18
@alanpoon
Copy link
Contributor Author

awesome!
I know this isn't yet complete, but I wanted to quickly drop in and suggest using rfd instead of makepad's internal file API. rfd is the de facto crate for this kind of thing, and I plan to shortly create a robius crate that wraps rfd, so we'll end up with a similar API.
Plus, with rfd you'd get immediate support for all 3 desktop platforms.

Kindly refer to this implementation of the rfd. https://github.com/Vjze/YY_DPS/blob/edb15ffc85b646c27547081b30a0e6f0d8ba688b/src/export/export_view.rs#L158 This requires the tokio runtime in a field in export screen

Ok, what's the issue with that? Is that problematic? Apologies, but I'm not quite sure what point you're trying to make.

Moly has used rfd in their app, works fine AFAIK.

Thanks for referring me to Moly. File Dialog does not work well in asynchronously in macOS as file dialog is only allowing in main thread.

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, looks very good — impressive work here!

I left comments about a few major structural decisions, but it's mostly just about refactoring things into more modular widgets. I also left some questions about using higher-level Timeline APIs vs Room APIs for sending attachments.

@kevinaboos kevinaboos removed the waiting-on-review This issue is waiting to be reviewed label Feb 5, 2026
@kevinaboos kevinaboos assigned kevinaboos and alanpoon and unassigned alanpoon Feb 5, 2026
@kevinaboos kevinaboos added the waiting-on-author This issue is waiting on the original author for a response label Feb 5, 2026
@kevinaboos
Copy link
Member

  • macOS
  • Android
  • Linux
  • Windows

Also, now that you're using rfd, can you confirm whether this also works for Linux and Windows? Theoretically they are also included as supported platforms in rfd.

@kevinaboos kevinaboos added the waiting-on-author This issue is waiting on the original author for a response label Feb 19, 2026
alanpoon and others added 4 commits February 24, 2026 16:35
Co-authored-by: Kevin Boos <1139460+kevinaboos@users.noreply.github.com>
Co-authored-by: Kevin Boos <1139460+kevinaboos@users.noreply.github.com>
@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 Feb 24, 2026
@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 Feb 25, 2026
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.

Looks pretty good, just a few minor comments.

Comment on lines 202 to 206
/// Counter for generating unique IDs for file load tasks.
#[rust] file_load_task_id_counter: u32,
/// The pending file load operation, if any. Contains the task ID and receiver
/// channel for receiving the loaded file data from a background thread.
#[rust] pending_file_load: Option<(u32, FileLoadReceiver)>,
Copy link
Member

Choose a reason for hiding this comment

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

it looks like neither of these u32 values are used any more, correct? If so, please remove them.

Seems like they wouldn't be needed anyway now that you're using proper TimelineUpdate channels for this stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove file_load_task_id_counter

Comment on lines 118 to 124
draw_icon: {
svg_file: (ICON_ADD_ATTACHMENT)
color: (COLOR_ACTIVE_PRIMARY_DARKER)
},
draw_bg: {
color: (COLOR_PRIMARY),
}
Copy link
Member

Choose a reason for hiding this comment

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

I think you've flipped these. The background color should be COLOR_ACTIVE_PRIMARY (blue), and the foreground color (both text and icon) should be COLOR_PRIMARY (white)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change to follow "location_button"

}
if remove_receiver {
self.pending_file_load = None;
cx.set_cursor(MouseCursor::Default);
Copy link
Member

Choose a reason for hiding this comment

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

nit: why is this needed? I suppose it doesn't hurt, but I don't see how it's beneficial. The cursor should be based on what the mouse is hovering over, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove "cx.set_cursor(MouseCursor::Default);"

}
}

/// Actions emitted by the `FileUploadModal` widget.
Copy link
Member

Choose a reason for hiding this comment

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

nit: are these actions actually emitted by the FileUploadModal widget? seems like they aren't necessarily; please update the doc comments to be clear for each variant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the doc comments.

let mime_type = file_meta.mime.clone();
let attachment_config = matrix_sdk_ui::timeline::AttachmentConfig {
txn_id: None,
info: None,
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't you fill in this info here, especially since most of it is already available as part of the file_data?

note that we do rely on this basic image info when showing images in the RoomScreen timeline, so it's only fair to expect that we should provide it to Robrix and other clients as well when uploading an image/file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Set Info.

Comment on lines 1719 to 1750
let mut subscriber = send_attachment.subscribe_to_send_progress();
let timeline_update_sender = sender.clone();
Handle::current().spawn(async move {
while let Some(progress) = subscriber.next().await {
sender.send(TimelineUpdate::FileUploadUpdate { current: progress.current as u64, total: file_meta.file_size }).unwrap_or_else(|e| {
error!("Failed to send progress update to UI: {e:?}");
});
SignalToUI::set_ui_signal();
}
});
timeline_update_sender.send(TimelineUpdate::FileUploadUpdate { current: 0, total: file_meta.file_size }).unwrap_or_else(|e| {
error!("Failed to send initial progress update to UI: {e:?}");
});
match send_attachment.await {
Ok(_) => {
log!("Successfully uploaded and sent file to {timeline_kind}");
timeline_update_sender.send(TimelineUpdate::FileUploadUpdate { current: file_meta.file_size, total: file_meta.file_size }).unwrap_or_else(|e| {
error!("Failed to send progress update to UI: {e:?}");
});
SignalToUI::set_ui_signal();
}
Err(e) => {
error!("Failed to upload file to {timeline_kind}: {e:?}");
// Set progress to completion state (0/0) to hide the progress bar
timeline_update_sender.send(TimelineUpdate::FileUploadUpdate { current: 0, total: 0 }).unwrap_or_else(|e| {
error!("Failed to send progress update to UI: {e:?}");
});
SignalToUI::set_ui_signal();
enqueue_popup_notification(format!("Failed to upload file: {e}"), PopupKind::Error, None);
}
}
});
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 improve the formatting of this? it's hard to read. Needs more whitespace newlines for separation, and better wrapping to avoid very long lines (ideally not much longer than 100 chars)

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 formatting.

Comment on lines 1743 to 1747
timeline_update_sender.send(TimelineUpdate::FileUploadUpdate { current: 0, total: 0 }).unwrap_or_else(|e| {
error!("Failed to send progress update to UI: {e:?}");
});
SignalToUI::set_ui_signal();
enqueue_popup_notification(format!("Failed to upload file: {e}"), PopupKind::Error, None);
Copy link
Member

Choose a reason for hiding this comment

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

While this technically works, it's not a great user experience.

Don't just hide the progress bar and show a popup notification error from the background task here. That doesn't allow the user to retry if anything went wrong (e.g., a temporary network disconnection).

Instead, send a variant of the FileUploadUpdate action with the explicit error to the UI, such that we can then show a retry button in the UI to allow the user to (1) see the error, and (2) attempt to re-send it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added Retry button.

@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 Feb 25, 2026
alanpoon and others added 8 commits February 26, 2026 08:25
Co-authored-by: Kevin Boos <1139460+kevinaboos@users.noreply.github.com>
Co-authored-by: Kevin Boos <1139460+kevinaboos@users.noreply.github.com>
Co-authored-by: Kevin Boos <1139460+kevinaboos@users.noreply.github.com>
@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 Feb 26, 2026
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.

2 participants