Skip to content

Commit 6cda2f7

Browse files
committed
add header text for file previewer
1 parent a647eca commit 6cda2f7

3 files changed

Lines changed: 143 additions & 39 deletions

File tree

src/room/room_input_bar.rs

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ use makepad_widgets::*;
1919
use matrix_sdk::room::reply::{EnforceThread, Reply};
2020
use matrix_sdk_ui::timeline::{EmbeddedEvent, EventTimelineItem, TimelineEventItemId};
2121
use ruma::{events::room::message::{LocationMessageEventContent, MessageType, RoomMessageEventContent}, OwnedRoomId};
22-
use crate::{home::{editing_pane::{EditingPaneState, EditingPaneWidgetExt}, location_preview::LocationPreviewWidgetExt, room_screen::{MessageAction, RoomScreenProps, populate_preview_of_timeline_item}, tombstone_footer::{SuccessorRoomDetails, TombstoneFooterWidgetExt}}, location::init_location_subscriber, shared::{avatar::AvatarWidgetRefExt, file_previewer::{FileLoadReceiver, FilePreviewerMetaData}, html_or_plaintext::HtmlOrPlaintextWidgetRefExt, mentionable_text_input::MentionableTextInputWidgetExt, popup_list::{PopupItem, PopupKind, enqueue_popup_notification}, progress::ProgressWidgetExt, styles::*}, sliding_sync::{MatrixRequest, UserPowerLevels, submit_async_request}, utils};
22+
use crate::{home::{editing_pane::{EditingPaneState, EditingPaneWidgetExt}, location_preview::LocationPreviewWidgetExt, room_screen::{MessageAction, RoomScreenProps, populate_preview_of_timeline_item}, tombstone_footer::{SuccessorRoomDetails, TombstoneFooterWidgetExt}}, location::init_location_subscriber, shared::{avatar::AvatarWidgetRefExt, file_previewer::{FileLoadReceiver, FilePreviewerMetaData, format_file_size}, html_or_plaintext::HtmlOrPlaintextWidgetRefExt, mentionable_text_input::MentionableTextInputWidgetExt, popup_list::{PopupItem, PopupKind, enqueue_popup_notification}, progress::ProgressWidgetExt, styles::*}, sliding_sync::{MatrixRequest, UserPowerLevels, submit_async_request}, utils};
2323
use crate::shared::file_previewer::FilePreviewerAction;
2424

25+
/// Maximum file size allowed for upload (100 MB).
26+
/// Files larger than this will be rejected to prevent memory issues.
27+
const MAX_FILE_SIZE_BYTES: u64 = 100 * 1024 * 1024;
28+
2529
live_design! {
2630
use link::theme::*;
2731
use link::shaders::*;
@@ -80,14 +84,36 @@ live_design! {
8084
flow: Down,
8185
spacing: 5,
8286

83-
progress_label = <Label> {
87+
header_row = <View> {
8488
width: Fill,
8589
height: Fit,
86-
draw_text: {
87-
text_style: <REGULAR_TEXT>{font_size: 10},
88-
color: #666
90+
flow: Right,
91+
align: {y: 0.5}
92+
spacing: 10,
93+
94+
progress_label = <Label> {
95+
width: Fill,
96+
height: Fit,
97+
draw_text: {
98+
text_style: <REGULAR_TEXT>{font_size: 10},
99+
color: #666
100+
}
101+
text: "Uploading..."
102+
}
103+
104+
cancel_upload_button = <Button> {
105+
width: Fit,
106+
height: Fit,
107+
padding: {top: 4, bottom: 4, left: 8, right: 8}
108+
draw_text: {
109+
text_style: <REGULAR_TEXT>{font_size: 9},
110+
color: #fff
111+
}
112+
draw_bg: {
113+
color: #c44
114+
}
115+
text: "Cancel"
89116
}
90-
text: "Uploading..."
91117
}
92118

93119
progress = <Progress> {
@@ -269,8 +295,8 @@ impl Widget for RoomInputBar {
269295
0.0
270296
};
271297

272-
self.view.progress(ids!(progress)).set_value(cx, progress_percentage);
273-
let progress_label = self.view.label(ids!(upload_progress_view.progress_label));
298+
self.view.progress(ids!(upload_progress_view.progress)).set_value(cx, progress_percentage);
299+
let progress_label = self.view.label(ids!(upload_progress_view.header_row.progress_label));
274300
progress_label.set_text(cx, &format!("Uploading... {:.0}%", progress_percentage));
275301
}
276302
self.redraw(cx);
@@ -339,6 +365,44 @@ impl RoomInputBar {
339365
// Handle the file attachment upload button being clicked.
340366
if self.button(ids!(attachment_upload_button)).clicked(actions) {
341367
if let Some(selected_file_path) = rfd::FileDialog::new().pick_file() {
368+
// Check file size before reading to prevent memory issues
369+
let file_size = match std::fs::metadata(&selected_file_path) {
370+
Ok(metadata) => metadata.len(),
371+
Err(e) => {
372+
error!("Failed to read file metadata for {:?}: {}", selected_file_path, e);
373+
enqueue_popup_notification(PopupItem {
374+
message: format!("Unable to access file: {}", e),
375+
auto_dismissal_duration: None,
376+
kind: PopupKind::Error
377+
});
378+
return;
379+
}
380+
};
381+
382+
// Check for empty files
383+
if file_size == 0 {
384+
enqueue_popup_notification(PopupItem {
385+
message: String::from("Cannot upload empty file"),
386+
auto_dismissal_duration: None,
387+
kind: PopupKind::Error
388+
});
389+
return;
390+
}
391+
392+
// Check if file exceeds maximum size
393+
if file_size > MAX_FILE_SIZE_BYTES {
394+
enqueue_popup_notification(PopupItem {
395+
message: format!(
396+
"File too large ({}). Maximum allowed size is {}",
397+
format_file_size(file_size),
398+
format_file_size(MAX_FILE_SIZE_BYTES)
399+
),
400+
auto_dismissal_duration: None,
401+
kind: PopupKind::Error
402+
});
403+
return;
404+
}
405+
342406
let filename = selected_file_path
343407
.file_name()
344408
.and_then(|n| n.to_str())
@@ -355,7 +419,6 @@ impl RoomInputBar {
355419
let (sender, receiver) = std::sync::mpsc::channel();
356420
self.background_task_id = self.background_task_id.wrapping_add(1);
357421
self.receiver = Some((self.background_task_id, receiver));
358-
359422
// Read file in background thread to avoid blocking the UI
360423
cx.spawn_thread(move || {
361424
match std::fs::read(&selected_file_path) {
@@ -383,6 +446,21 @@ impl RoomInputBar {
383446
}
384447
}
385448

449+
// Handle cancel upload button being clicked.
450+
if self.button(ids!(upload_progress_view.header_row.cancel_upload_button)).clicked(actions) {
451+
log!("Upload cancelled by user");
452+
// Hide the progress bar immediately
453+
self.view.view(ids!(upload_progress_view)).set_visible(cx, false);
454+
self.upload_progress_subscriber = None;
455+
// Note: The actual upload will continue in the background but user won't see progress
456+
enqueue_popup_notification(PopupItem {
457+
message: String::from("Upload cancelled"),
458+
kind: PopupKind::Info,
459+
auto_dismissal_duration: Some(3.0)
460+
});
461+
self.redraw(cx);
462+
}
463+
386464
// Handle the send location button being clicked.
387465
if self.button(ids!(location_preview.send_location_button)).clicked(actions) {
388466
let location_preview = self.location_preview(ids!(location_preview));

src/shared/file_previewer.rs

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ live_design! {
4040
align: {x: 0.5}
4141
flow: Down
4242
padding: {top: 20, right: 20, bottom: 10, left: 20}
43-
4443
show_bg: true
4544
draw_bg: {
4645
color: (COLOR_PRIMARY)
@@ -49,36 +48,59 @@ live_design! {
4948

5049
<View> {
5150
width: Fit, height: Fit
52-
flow: Right
53-
// Document view (visible only for non-image files)
54-
document_view = <View> {
55-
visible: false,
56-
width: Fit
57-
height: 40
58-
flow: Down
59-
align: {x: 0.5, y: 0.5}
60-
file_icon = <Icon> {
61-
draw_icon: {
62-
svg_file: (ICON_FILE),
63-
color: #999,
51+
flow: Down
52+
53+
<View> {
54+
width: Fit, height: Fit
55+
56+
header_label = <Label> {
57+
width: 200
58+
height: 50
59+
padding: 0
60+
//margin: {bottom: 15}
61+
draw_text: {
62+
text_style: <REGULAR_TEXT>{font_size: 15},
63+
color: (COLOR_TEXT),
64+
wrap: Word
6465
}
65-
icon_walk: { width: 20, height: 20 }
66+
text: "Upload Files"
6667
}
6768
}
68-
// File metadata section (always visible)
69-
metadata_view = <View> {
70-
width: 250
71-
height: Fit
72-
flow: Down
73-
spacing: 5
74-
75-
filename_text = <Label> {
76-
width: Fill
69+
<View> {
70+
width: Fit, height: Fit
71+
flow: Right
72+
73+
// Document view (visible only for non-image files)
74+
document_view = <View> {
75+
visible: false,
76+
width: Fit
77+
height: 40
78+
flow: Down
79+
align: {x: 0.5, y: 0.5}
80+
file_icon = <Icon> {
81+
draw_icon: {
82+
svg_file: (ICON_FILE),
83+
color: #999,
84+
}
85+
icon_walk: { width: 20, height: 20 }
86+
}
87+
}
88+
89+
// File metadata section (always visible)
90+
metadata_view = <View> {
91+
width: 250
7792
height: Fit
78-
draw_text: {
79-
text_style: <REGULAR_TEXT>{font_size: 14},
80-
color: #000,
81-
wrap: Word
93+
flow: Down
94+
spacing: 5
95+
96+
filename_text = <Label> {
97+
width: Fill
98+
height: Fit
99+
draw_text: {
100+
text_style: <REGULAR_TEXT>{font_size: 14},
101+
color: #000,
102+
wrap: Word
103+
}
82104
}
83105
}
84106
}
@@ -347,7 +369,7 @@ pub enum FileType {
347369
///
348370
/// Uses binary units (1024 bytes = 1 KB) for conversion.
349371
/// For sizes less than 1 KB, displays the exact byte count without decimal places.
350-
fn format_file_size(bytes: u64) -> String {
372+
pub fn format_file_size(bytes: u64) -> String {
351373
const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
352374

353375
if bytes == 0 {

src/sliding_sync.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,21 +1418,22 @@ async fn matrix_worker_task(
14181418
let mime_type = file_meta.mime.clone();
14191419

14201420
// Upload the file to the media repository and send the message
1421+
let file_size_uint = UInt::try_from(file_meta.file_size as u64).ok();
14211422
let attachment_config = matrix_sdk::attachment::AttachmentConfig::new()
14221423
.info(if mime_type.type_() == mime::IMAGE {
14231424
matrix_sdk::attachment::AttachmentInfo::Image(
14241425
matrix_sdk::attachment::BaseImageInfo {
14251426
height: None,
14261427
width: None,
1427-
size: Some(UInt::new(file_meta.file_size as u64).unwrap()),
1428+
size: file_size_uint,
14281429
blurhash: None,
14291430
is_animated: None,
14301431
}
14311432
)
14321433
} else {
14331434
matrix_sdk::attachment::AttachmentInfo::File(
14341435
matrix_sdk::attachment::BaseFileInfo {
1435-
size: Some(UInt::new(file_meta.file_size as u64).unwrap()),
1436+
size: file_size_uint,
14361437
}
14371438
)
14381439
});
@@ -1483,12 +1484,15 @@ async fn matrix_worker_task(
14831484
}
14841485
Err(e) => {
14851486
error!("Failed to upload file to room {room_id}: {e:?}");
1487+
// Set progress to completion state (0/0) to hide the progress bar
14861488
progress_sender.set(TransmissionProgress { total: 0, current: 0 });
14871489
enqueue_popup_notification(PopupItem {
14881490
message: format!("Failed to upload file: {e}"),
14891491
kind: PopupKind::Error,
14901492
auto_dismissal_duration: None
14911493
});
1494+
// Signal UI to update and hide the progress bar
1495+
SignalToUI::set_ui_signal();
14921496
}
14931497
}
14941498
});

0 commit comments

Comments
 (0)