feat: progress of each task (#3121)

Co-authored-by: sxyazi <sxyazi@gmail.com>
This commit is contained in:
Cattyman 2025-09-04 17:55:28 +07:00 committed by GitHub
parent b997e56a60
commit 49910fcfe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 109 additions and 16 deletions

View file

@ -202,7 +202,7 @@ icon_command = ""
[tasks]
border = { fg = "blue" }
title = {}
hovered = { fg = "magenta", underline = true }
hovered = { fg = "magenta", bold = true }
# : }}}

View file

@ -202,7 +202,7 @@ icon_command = ""
[tasks]
border = { fg = "blue" }
title = {}
hovered = { fg = "magenta", underline = true }
hovered = { fg = "magenta", bold = true }
# : }}}

View file

@ -54,8 +54,9 @@ impl Tasks {
}
pub fn limit() -> usize {
(Dimension::available().rows * TASKS_PERCENT / 100).saturating_sub(TASKS_BORDER + TASKS_PADDING)
as usize
((Dimension::available().rows * TASKS_PERCENT / 100)
.saturating_sub(TASKS_BORDER + TASKS_PADDING) as usize)
/ 3
}
pub fn paginate(&self) -> Vec<TaskSnap> {

View file

@ -2,21 +2,113 @@ Tasks = {
_id = "tasks",
}
function Tasks:new(area) return setmetatable({ _area = area }, { __index = self }) end
function Tasks:new(area)
local me = setmetatable({ _area = area }, { __index = self })
me:layout()
return me
end
function Tasks:layout()
self._area = self._area:pad(ui.Pad(1, 1, 1, 3))
self._chunks = ui.Layout()
:direction(ui.Layout.HORIZONTAL)
:constraints({
ui.Constraint.Percentage(60),
ui.Constraint.Percentage(40),
})
:split(self._area)
end
function Tasks:reflow() return { self } end
function Tasks:redraw()
local rows = {}
for _, snap in ipairs(cx.tasks.snaps) do
rows[#rows + 1] = ui.Row { snap.name }
local elements = {}
for i, snap in ipairs(cx.tasks.snaps) do
local y = self._area.y + (i - 1) * 3
if y >= self._area.bottom then
break
end
elements[#elements + 1] = ui.Line({ self:icon(snap), snap.name }):area(ui.Rect {
x = self._area.x,
y = y,
w = self._area.w,
h = 1,
})
if i == cx.tasks.cursor + 1 then
elements[#elements] = elements[#elements]:style(th.tasks.hovered)
end
for _, e in ipairs(self:progress_redraw(snap, y + 1)) do
elements[#elements + 1] = e
end
elements[#elements + 1] = ui.Bar(ui.Edge.LEFT)
:area(ui.Rect {
x = math.max(0, self._area.x - 2),
y = y,
w = self._area.w,
h = 2,
})
:symbol("")
if i == cx.tasks.cursor + 1 then
elements[#elements] = elements[#elements]:style(th.tasks.hovered)
end
end
local tbl = ui.Table(rows)
:area(self._area:pad(ui.Pad.x(1)))
:row(cx.tasks.cursor)
:row_style(th.tasks.hovered)
:widths { ui.Constraint.Fill(1) }
return { tbl }
return elements
end
function Tasks:icon(snap)
if snap.prog.kind == "FilePaste" then
return ""
elseif snap.prog.kind == "FileDelete" then
return ""
else
return ""
end
end
function Tasks:progress_redraw(snap, y)
local kind = snap.prog.kind
if kind == "FilePaste" or kind == "FileDelete" then
local label = string.format(
"%3d%% - %s / %s",
math.floor(snap.percent),
ya.readable_size(snap.prog.processed_bytes),
ya.readable_size(snap.prog.total_bytes)
)
local style = th.status.progress_normal
if snap.prog.failed_files > 0 then
style = th.status.progress_error
end
return {
ui.Gauge()
:area(ui.Rect { x = self._chunks[1].x, y = y, w = self._chunks[1].w, h = 1 })
:percent(snap.percent)
:label(ui.Span(label):style(th.status.progress_label))
:gauge_style(style),
ui.Line(string.format("%d/%d", snap.prog.success_files, snap.prog.total_files))
:fg("gray")
:area(ui.Rect { x = self._chunks[2].x, y = y, w = self._chunks[2].w, h = 1 })
:align(ui.Align.RIGHT),
}
else
local text
if snap.running then
text = "Running…"
elseif snap.success then
text = "Completing…"
else
text = "Failed, press Enter to view log…"
end
return {
ui.Line(text):fg("gray"):area(ui.Rect { x = self._chunks[1].x, y = y, w = self._chunks[1].w, h = 1 }),
}
end
end

View file

@ -339,7 +339,7 @@ mod tests {
for (path, expected) in cases {
let path: UrlBuf = path.parse()?;
assert_eq!(path.parent().map(|u| format!("{:?}", u)).as_deref(), expected);
assert_eq!(path.parent().map(|u| format!("{u:?}")).as_deref(), expected);
}
Ok(())