mirror of
https://github.com/rust-kotlin/ashell.git
synced 2026-09-22 08:01:00 +00:00
feat: optimize transfer history dialog UI and logic
- Add an independent scrollbar track to prevent it from overlapping with the content list - Add a "Clear History" button with text label, placed seamlessly next to the close button in the custom header - Implement a 100-record limit for transfer history and display this limit in the header - Persist the cleared transfer history into the session config immediately after clearing - Disable default dialog close button and reconstruct header to avoid state update collision and panic Resolves #25
This commit is contained in:
@@ -123,3 +123,5 @@ settings_group_font: "Font"
|
||||
settings_group_other: "Other"
|
||||
theme: "Theme"
|
||||
theme_mode: "Theme Mode"
|
||||
clear_transfers: "Clear History"
|
||||
transfers_limit: " (Max 100 records)"
|
||||
|
||||
@@ -126,3 +126,5 @@ settings_group_font: "字体"
|
||||
settings_group_other: "其它"
|
||||
theme: "主题"
|
||||
theme_mode: "主题模式"
|
||||
clear_transfers: "清空记录"
|
||||
transfers_limit: " (最多保留 100 条)"
|
||||
|
||||
+104
-32
@@ -398,11 +398,78 @@ impl Ashell {
|
||||
let view = cx.entity();
|
||||
window.open_dialog(cx, move |dialog: Dialog, _window, _| {
|
||||
dialog
|
||||
.title(t!("transfers").to_string())
|
||||
.w(px(600.))
|
||||
.close_button(false)
|
||||
.content({
|
||||
let view = view.clone();
|
||||
move |content, window, cx| {
|
||||
let can_clear = view.read(cx).transfers.iter().any(|t| {
|
||||
!matches!(
|
||||
t.state,
|
||||
crate::terminal::TransferState::Running
|
||||
| crate::terminal::TransferState::Paused
|
||||
)
|
||||
});
|
||||
|
||||
let clear_btn = if can_clear {
|
||||
Some(
|
||||
Button::new("clear_transfers_btn")
|
||||
.small()
|
||||
.ghost()
|
||||
.icon(IconName::Delete)
|
||||
.label(t!("clear_transfers").to_string())
|
||||
.on_click(window.listener_for(&view, |this, _, _, cx| {
|
||||
this.transfers.retain(|t| {
|
||||
matches!(
|
||||
t.state,
|
||||
crate::terminal::TransferState::Running
|
||||
| crate::terminal::TransferState::Paused
|
||||
)
|
||||
});
|
||||
this.config.set_transfers(this.transfers.clone());
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let header = h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.items_center()
|
||||
.child(
|
||||
h_flex()
|
||||
.items_baseline()
|
||||
.child(
|
||||
div()
|
||||
.text_lg()
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child(t!("transfers").to_string()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.ml_2()
|
||||
.child(t!("transfers_limit").to_string()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.children(clear_btn)
|
||||
.child(
|
||||
Button::new("close_dialog")
|
||||
.small()
|
||||
.ghost()
|
||||
.icon(IconName::Close)
|
||||
.on_click(|_, window, cx| {
|
||||
window.close_dialog(cx);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
let mut transfers = view.read(cx).transfers.clone();
|
||||
transfers.sort_by_key(|t| match t.state {
|
||||
crate::terminal::TransferState::Running
|
||||
@@ -412,14 +479,15 @@ impl Ashell {
|
||||
|
||||
if transfers.is_empty() {
|
||||
return content.child(
|
||||
div()
|
||||
.p_4()
|
||||
.text_center()
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(t!("no_transfers_yet").to_string()),
|
||||
v_flex().gap_2().child(header).child(
|
||||
div()
|
||||
.p_4()
|
||||
.text_center()
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(t!("no_transfers_yet").to_string()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
let list = v_flex().gap_2().children(transfers.into_iter().map(|t| {
|
||||
let (icon, _color) = match t.info.kind {
|
||||
crate::terminal::TransferType::Upload => {
|
||||
@@ -629,6 +697,7 @@ impl Ashell {
|
||||
)
|
||||
}));
|
||||
|
||||
|
||||
let scroll_handle = window
|
||||
.use_keyed_state("transfers-scroll", cx, |_, _| {
|
||||
gpui::ScrollHandle::default()
|
||||
@@ -637,31 +706,34 @@ impl Ashell {
|
||||
.clone();
|
||||
|
||||
content.child(
|
||||
div()
|
||||
.w_full()
|
||||
.relative()
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.max_h(px(400.))
|
||||
.flex_col()
|
||||
.id("transfers-scroll-view")
|
||||
.track_scroll(&scroll_handle)
|
||||
.overflow_y_scroll()
|
||||
.child(list),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.absolute()
|
||||
.top_0()
|
||||
.right_0()
|
||||
.bottom_0()
|
||||
.w(px(16.))
|
||||
.child(
|
||||
Scrollbar::vertical(&scroll_handle)
|
||||
.scrollbar_show(ScrollbarShow::Always),
|
||||
),
|
||||
),
|
||||
v_flex().gap_2().child(header).child(
|
||||
div()
|
||||
.w_full()
|
||||
.relative()
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.max_h(px(400.))
|
||||
.flex_col()
|
||||
.id("transfers-scroll-view")
|
||||
.track_scroll(&scroll_handle)
|
||||
.overflow_y_scroll()
|
||||
.pr(px(14.))
|
||||
.child(list),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.absolute()
|
||||
.top_0()
|
||||
.right_0()
|
||||
.bottom_0()
|
||||
.w(px(16.))
|
||||
.child(
|
||||
Scrollbar::vertical(&scroll_handle)
|
||||
.scrollbar_show(ScrollbarShow::Always),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -718,6 +718,9 @@ impl Ashell {
|
||||
state: crate::terminal::TransferState::Running,
|
||||
},
|
||||
);
|
||||
if self.transfers.len() > 100 {
|
||||
self.transfers.truncate(100);
|
||||
}
|
||||
transfers_changed = true;
|
||||
}
|
||||
BackendEvent::SftpHome { tab_id, home } => {
|
||||
|
||||
Reference in New Issue
Block a user