Skip to content

Commit 51e388c

Browse files
committed
added file_previewer
1 parent ba038cc commit 51e388c

7 files changed

Lines changed: 126 additions & 130 deletions

File tree

resources/icons/add_attachment.svg

Lines changed: 17 additions & 0 deletions
Loading

resources/icons/file.svg

Lines changed: 4 additions & 0 deletions
Loading

src/home/room_screen.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,7 @@ impl RoomScreen {
12691269
if is_append && !portal_list.is_at_end() {
12701270
// Immediately show the unread badge with no count while we fetch the actual count in the background.
12711271
jump_to_bottom.show_unread_message_badge(cx, UnreadMessageCount::Unknown);
1272-
submit_async_request(MatrixRequest::GetNumberUnreadMessages{ room_id: tl.room_id.clone() });
1272+
submit_async_request(MatrixRequest::GetNumberUnreadMessages{ room_id: tl.room_id.clone() });
12731273
}
12741274

12751275
if prior_items_changed {
@@ -1495,10 +1495,6 @@ impl RoomScreen {
14951495
}),
14961496
}
14971497
}
1498-
TimelineUpdate::ScrollToBottom => {
1499-
// Scroll the portal list to the bottom of the timeline
1500-
portal_list.set_first_id_and_scroll(tl.items.len().saturating_sub(1), 0.0);
1501-
}
15021498
}
15031499
}
15041500

@@ -2576,9 +2572,6 @@ pub enum TimelineUpdate {
25762572
user_id: OwnedUserId,
25772573
result: matrix_sdk::Result<()>,
25782574
},
2579-
/// A request to scroll the timeline to the bottom.
2580-
ScrollToBottom,
2581-
25822575
}
25832576

25842577
thread_local! {

src/room/room_input_bar.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ 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};
2222
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, html_or_plaintext::HtmlOrPlaintextWidgetRefExt, mentionable_text_input::MentionableTextInputWidgetExt, popup_list::{PopupItem, PopupKind, enqueue_popup_notification}, progress::MyProgressWidgetExt, styles::*}, sliding_sync::{MatrixRequest, UserPowerLevels, submit_async_request}, utils};
23+
use crate::shared::file_previewer::FilePreviewerAction;
2324

2425
live_design! {
2526
use link::theme::*;
@@ -39,7 +40,7 @@ live_design! {
3940
use link::tsp_link::TspSignAnycastCheckbox;
4041

4142
ICO_LOCATION_PERSON = dep("crate://self/resources/icons/location-person.svg")
42-
ICO_ADD_IMAGE = dep("crate://self/resources/icons/add_image.svg")
43+
ICON_ADD_ATTACHMENT = dep("crate://self/resources/icons/add_attachment.svg")
4344

4445

4546
pub RoomInputBar = {{RoomInputBar}}<RoundedView> {
@@ -128,11 +129,11 @@ live_design! {
128129
text: "",
129130
}
130131

131-
image_upload_button = <RobrixIconButton> {
132+
attachment_upload_button = <RobrixIconButton> {
132133
margin: {left: 4}
133134
spacing: 0,
134135
draw_icon: {
135-
svg_file: (ICO_ADD_IMAGE)
136+
svg_file: (ICON_ADD_ATTACHMENT)
136137
color: (COLOR_ACTIVE_PRIMARY_DARKER)
137138
},
138139
draw_bg: {
@@ -248,28 +249,22 @@ impl Widget for RoomInputBar {
248249
}
249250
_ => {}
250251
}
251-
if let Event::FileDialogResult { live_id: _, path } = event {
252-
if let Some(path) = path {
253-
log!("File selected for upload: {}", path.display());
254-
255-
// Prepare the reply context if replying to a message
256-
let replied_to_event_id = self.replying_to.as_ref()
257-
.and_then(|(event_tl_item, _emb)| event_tl_item.event_id().map(ToOwned::to_owned));
258-
259-
// Post action to show the file previewer modal
260-
cx.action(crate::shared::file_previewer::FilePreviewerAction::Show {
261-
file_path: path.clone(),
262-
room_id: room_screen_props.room_name_id.room_id().clone(),
263-
replied_to_event_id,
264-
});
252+
if let Event::FileDialogResult { live_id, path } = event {
253+
if *live_id == live_id!(attachment_upload) {
254+
if let Some(path) = path {
255+
log!("File selected for upload: {}", path.display());
256+
// Post action to show the file previewer modal
257+
cx.action(FilePreviewerAction::Show {
258+
file_path: path.clone(),
259+
});
260+
}
265261
}
266262
}
267263

268264
// Handle upload progress updates
269265
if let Some(subscriber) = &self.upload_progress_subscriber {
270266
// Get the current progress value
271267
let progress = subscriber.get();
272-
println!("Upload progress: {}/{}", progress.current, progress.total);
273268
if progress.current >= progress.total {
274269
// Upload complete, hide progress bar
275270
self.view.view(ids!(upload_progress_view)).set_visible(cx, false);
@@ -336,9 +331,8 @@ impl RoomInputBar {
336331
}
337332

338333
// Handle the image upload button being clicked.
339-
if self.button(ids!(image_upload_button)).clicked(actions) {
340-
log!("Image upload button clicked; opening file dialog...");
341-
cx.open_system_openfile_dialog(live_id!(upload), FileDialog::new());
334+
if self.button(ids!(attachment_upload_button)).clicked(actions) {
335+
cx.open_system_openfile_dialog(live_id!(attachment_upload), FileDialog::new());
342336
}
343337

344338
// Handle the send location button being clicked.
@@ -438,12 +432,16 @@ impl RoomInputBar {
438432
// Handle file upload action
439433
for action in actions {
440434
match action.downcast_ref() {
441-
Some(crate::shared::file_previewer::FilePreviewerAction::Upload { room_id, file_path, replied_to_event_id }) => {
435+
Some(FilePreviewerAction::Upload { file_path }) => {
442436
// Reconstruct the Reply from the event_id
443-
let replied_to = replied_to_event_id.as_ref().map(|event_id| Reply {
444-
event_id: event_id.clone(),
445-
enforce_thread: EnforceThread::MaybeThreaded,
446-
});
437+
let replied_to = self.replying_to.take().and_then(|(event_tl_item, _emb)|
438+
event_tl_item.event_id().map(|event_id|
439+
Reply {
440+
event_id: event_id.to_owned(),
441+
enforce_thread: EnforceThread::MaybeThreaded,
442+
}
443+
)
444+
);
447445

448446
// Create a SharedObservable for tracking upload progress
449447
use matrix_sdk::TransmissionProgress;
@@ -453,15 +451,15 @@ impl RoomInputBar {
453451
// Store the subscriber so we can track progress updates
454452
self.upload_progress_subscriber = Some(progress_subscriber);
455453
progress_observable.set(TransmissionProgress { current: 0, total: 100 });
456-
println!("FilePreviewerAction::Upload");
457454
submit_async_request(MatrixRequest::Upload {
458-
room_id: room_id.clone(),
455+
room_id: room_screen_props.room_name_id.room_id().clone(),
459456
file_path: file_path.clone(),
460457
replied_to,
461458
#[cfg(feature = "tsp")]
462459
sign_with_tsp: false,
463460
progress_sender: Some(progress_observable),
464461
});
462+
self.clear_replying_to(cx);
465463
}
466464
_ => {}
467465
}

src/shared/file_previewer.rs

Lines changed: 41 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ live_design! {
7070
}
7171

7272
pub FilePreviewer = {{FilePreviewer}} {
73+
width: Fit, height: Fit
7374
wrapper = <RoundedView> {
75+
width: Fit, height: Fit
7476
align: {x: 0.5}
7577
flow: Down
7678
padding: {top: 30, right: 40, bottom: 20, left: 40}
@@ -82,7 +84,7 @@ live_design! {
8284
}
8385

8486
header_view = <View> {
85-
width: Fill
87+
width: 400
8688
height: Fit
8789
flow: Right
8890
align: {x: 1.0, y: 0.0}
@@ -92,42 +94,49 @@ live_design! {
9294
draw_icon: { svg_file: (ICON_CLOSE) }
9395
icon_walk: {width: 21, height: 21 }
9496
}
95-
9697
}
97-
98-
// File metadata section (always visible)
99-
metadata_view = <View> {
100-
width: Fill
101-
height: Fit
102-
flow: Down
103-
spacing: 5
104-
padding: {bottom: 15}
105-
106-
filename_label = <Label> {
107-
width: Fill
108-
height: Fit
109-
draw_text: {
110-
text_style: <REGULAR_TEXT>{font_size: 14},
111-
color: #000,
112-
wrap: Word
98+
<View> {
99+
width: Fit, height: Fit
100+
flow: Right
101+
// Document view (visible only for non-image files)
102+
document_view = <View> {
103+
visible: false,
104+
width: Fit
105+
height: 40
106+
flow: Down
107+
align: {x: 0.5, y: 0.5}
108+
file_icon = <Icon> {
109+
draw_icon: {
110+
svg_file: (ICON_FILE),
111+
color: #999,
112+
}
113+
icon_walk: { width: 20, height: 20 }
113114
}
114115
}
115-
116-
filesize_label = <Label> {
117-
width: Fill
116+
// File metadata section (always visible)
117+
metadata_view = <View> {
118+
width: 400
118119
height: Fit
119-
draw_text: {
120-
text_style: <REGULAR_TEXT>{font_size: 12},
121-
color: #666,
120+
flow: Down
121+
spacing: 5
122+
123+
filename_text = <Label> {
124+
width: Fill
125+
height: Fit
126+
draw_text: {
127+
text_style: <REGULAR_TEXT>{font_size: 14},
128+
color: #000,
129+
wrap: Word
130+
}
122131
}
123132
}
124133
}
125134

126135
// Image preview (visible only for image files)
127136
image_view = <View> {
128137
visible: true,
129-
width: 400
130-
height: 400
138+
width: 300
139+
height: 300
131140
flow: Down
132141
align: {x: 0.5, y: 0.5}
133142

@@ -137,28 +146,9 @@ live_design! {
137146
}
138147
}
139148

140-
// Document view (visible only for non-image files)
141-
document_view = <View> {
142-
visible: false,
143-
width: Fill
144-
height: Fit
145-
flow: Down
146-
align: {x: 0.5, y: 0.5}
147-
padding: 20,
148-
149-
file_icon = <Icon> {
150-
draw_icon: {
151-
svg_file: (ICON_HTML_FILE),
152-
color: #999,
153-
}
154-
icon_walk: { width: 48, height: 48 }
155-
}
156-
}
157-
158149
buttons_view = <View> {
159-
width: Fill, height: Fit
150+
width: 300, height: Fit
160151
flow: Right,
161-
padding: {top: 20, bottom: 20}
162152
margin: {right: -15}
163153
align: {x: 1.0, y: 0.5}
164154
spacing: 20
@@ -209,14 +199,10 @@ pub enum FilePreviewerAction {
209199
/// Display the FilePreviewer widget with the given file path and room context.
210200
Show {
211201
file_path: PathBuf,
212-
room_id: ruma::OwnedRoomId,
213-
replied_to_event_id: Option<ruma::OwnedEventId>,
214202
},
215203
/// Upload the file with the given path.
216204
Upload {
217-
room_id: ruma::OwnedRoomId,
218205
file_path: PathBuf,
219-
replied_to_event_id: Option<ruma::OwnedEventId>,
220206
},
221207
/// Hide the FilePreviewer widget.
222208
Hide,
@@ -230,8 +216,6 @@ pub struct FilePreviewer {
230216
#[rust] background_task_id: u32,
231217
#[rust] receiver: Option<(u32, std::sync::mpsc::Receiver<(FilePreviewerMetaData, Vec<u8>)>)>,
232218
#[rust] file_path: Option<PathBuf>,
233-
#[rust] room_id: Option<ruma::OwnedRoomId>,
234-
#[rust] replied_to_event_id: Option<ruma::OwnedEventId>,
235219
}
236220

237221
impl Widget for FilePreviewer {
@@ -260,7 +244,6 @@ impl Widget for FilePreviewer {
260244
self.view(ids!(wrapper.document_view)).set_visible(cx, false);
261245
self.file_type = FileType::Image;
262246

263-
264247
} else {
265248
println!("Failed to load image from bytes");
266249
// Failed to load image, show as document
@@ -278,7 +261,6 @@ impl Widget for FilePreviewer {
278261
Err(std::sync::mpsc::TryRecvError::Disconnected) => {
279262
remove_receiver = true;
280263
}
281-
282264
}
283265
if remove_receiver {
284266
self.receiver = None;
@@ -291,6 +273,7 @@ impl Widget for FilePreviewer {
291273
self.view.draw_walk(cx, scope, walk)
292274
}
293275
}
276+
294277
impl MatchEvent for FilePreviewer {
295278
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
296279
// Handle close button click
@@ -311,11 +294,9 @@ impl MatchEvent for FilePreviewer {
311294
}
312295
// Handle upload button click
313296
if self.view.button(ids!(wrapper.buttons_view.upload_button)).clicked(actions) {
314-
if let (Some(file_path), Some(room_id)) = (&self.file_path, &self.room_id) {
297+
if let Some(file_path) = &self.file_path {
315298
cx.action(FilePreviewerAction::Upload {
316-
room_id: room_id.clone(),
317299
file_path: file_path.clone(),
318-
replied_to_event_id: self.replied_to_event_id.clone(),
319300
});
320301
cx.action(FilePreviewerAction::Hide);
321302
self.view.button(ids!(wrapper.buttons_view.upload_button)).set_enabled(cx, false);
@@ -324,7 +305,7 @@ impl MatchEvent for FilePreviewer {
324305
}
325306
for action in actions {
326307
match action.downcast_ref() {
327-
Some(FilePreviewerAction::Show { file_path, room_id, replied_to_event_id }) => {
308+
Some(FilePreviewerAction::Show { file_path }) => {
328309
self.view.button(ids!(close_button)).reset_hover(cx);
329310
self.view.button(ids!(close_button)).set_enabled(cx, true);
330311
// Reset button states
@@ -334,8 +315,6 @@ impl MatchEvent for FilePreviewer {
334315
self.view.button(ids!(wrapper.buttons_view.upload_button)).set_enabled(cx, true);
335316
// Store the context for later use when upload button is clicked
336317
self.file_path = Some(file_path.clone());
337-
self.room_id = Some(room_id.clone());
338-
self.replied_to_event_id = replied_to_event_id.clone();
339318
let (sender, receiver) = std::sync::mpsc::channel();
340319
if let Some(new_value) = self.background_task_id.checked_add(1) {
341320
self.background_task_id = new_value;
@@ -371,16 +350,16 @@ impl MatchEvent for FilePreviewer {
371350
}
372351
}
373352
}
353+
374354
impl FilePreviewer {
375355
/// Sets the file metadata (filename and size).
376356
///
377357
/// ## Arguments
378358
/// * `filename`: the name of the file
379359
/// * `filesize`: the size of the file in bytes
380360
pub fn set_metadata(&mut self, cx: &mut Cx, filename: &str, filesize: u64) {
381-
self.view.label(ids!(wrapper.metadata_view.filename_label)).set_text(cx, filename);
382361
let size_str = format_file_size(filesize);
383-
self.view.label(ids!(wrapper.metadata_view.filesize_label)).set_text(cx, &size_str);
362+
self.view.label(ids!(filename_text)).set_text(cx, &format!("{} - ({})", filename, size_str));
384363
}
385364

386365
/// Displays an image preview.

0 commit comments

Comments
 (0)