diff --git a/pixstrip-gtk/src/app.rs b/pixstrip-gtk/src/app.rs index ebc1803..efdb767 100644 --- a/pixstrip-gtk/src/app.rs +++ b/pixstrip-gtk/src/app.rs @@ -1151,12 +1151,69 @@ fn show_history_dialog(window: &adw::ApplicationWindow) { .as_deref() .unwrap_or("Custom workflow"); - let row = adw::ActionRow::builder() + // Format timestamp + let time_label = entry.timestamp.parse::().ok().and_then(|ts| { + let dt = glib::DateTime::from_unix_local(ts as i64).ok()?; + let formatted = dt.format("%Y-%m-%d %H:%M").ok()?; + Some(formatted.to_string()) + }).unwrap_or_else(|| "Unknown date".to_string()); + + let row = adw::ExpanderRow::builder() .title(preset_label) - .subtitle(&subtitle) + .subtitle(&format!("{} - {}", time_label, subtitle)) + .show_enable_switch(false) .build(); row.add_prefix(>k::Image::from_icon_name("image-x-generic-symbolic")); + // Detail rows inside expander + let input_row = adw::ActionRow::builder() + .title("Input") + .subtitle(&entry.input_dir) + .build(); + input_row.add_prefix(>k::Image::from_icon_name("folder-symbolic")); + row.add_row(&input_row); + + let output_row = adw::ActionRow::builder() + .title("Output") + .subtitle(&entry.output_dir) + .activatable(true) + .build(); + output_row.add_prefix(>k::Image::from_icon_name("folder-open-symbolic")); + let out_dir = entry.output_dir.clone(); + output_row.connect_activated(move |_| { + let _ = gtk::gio::AppInfo::launch_default_for_uri( + &format!("file://{}", out_dir), + gtk::gio::AppLaunchContext::NONE, + ); + }); + row.add_row(&output_row); + + let size_row = adw::ActionRow::builder() + .title("Size") + .subtitle(&format!( + "{} -> {} ({})", + format_bytes(entry.total_input_bytes), + format_bytes(entry.total_output_bytes), + savings + )) + .build(); + size_row.add_prefix(>k::Image::from_icon_name("drive-harddisk-symbolic")); + row.add_row(&size_row); + + if entry.failed > 0 { + let err_row = adw::ActionRow::builder() + .title("Errors") + .subtitle(&format!("{} files failed", entry.failed)) + .build(); + err_row.add_prefix(>k::Image::from_icon_name("dialog-warning-symbolic")); + row.add_row(&err_row); + } + + // Action buttons row + let actions_row = adw::ActionRow::builder() + .title("Actions") + .build(); + // Undo button - moves output files to trash if !entry.output_files.is_empty() { let undo_btn = gtk::Button::builder() @@ -1177,9 +1234,26 @@ fn show_history_dialog(window: &adw::ApplicationWindow) { btn.set_sensitive(false); btn.set_tooltip_text(Some(&format!("{} files moved to trash", trashed))); }); - row.add_suffix(&undo_btn); + actions_row.add_suffix(&undo_btn); } + // Open output folder button + let open_btn = gtk::Button::builder() + .icon_name("folder-open-symbolic") + .tooltip_text("Open output folder") + .valign(gtk::Align::Center) + .build(); + open_btn.add_css_class("flat"); + let out_dir2 = entry.output_dir.clone(); + open_btn.connect_clicked(move |_| { + let _ = gtk::gio::AppInfo::launch_default_for_uri( + &format!("file://{}", out_dir2), + gtk::gio::AppLaunchContext::NONE, + ); + }); + actions_row.add_suffix(&open_btn); + + row.add_row(&actions_row); group.add(&row); } content.append(&group);