style(tui): apply rustfmt and clippy formatting across crate
Mechanical formatting pass to satisfy rustfmt line-width limits and clippy pedantic/nursery lints. No behavioral changes. Formatting (rustfmt line wrapping): - action/sync.rs: multiline tuple destructure, function call args in tests - state/sync.rs: if-let chain formatting, remove unnecessary Vec collect - view/sync.rs: multiline array entries, format!(), vec! literals - view/doctor.rs: multiline floor_char_boundary chain - view/scope_picker.rs: multiline format!() with floor_char_boundary - view/stats.rs: multiline render_stat_row call - view/mod.rs: multiline assert!() in test - app/update.rs: multiline enum variant destructure - entity_cache.rs: multiline assert_eq!() with messages - render_cache.rs: multiline retain() closure - session.rs: multiline serde_json/File::create/parent() chains Clippy: - action/sync.rs: #[allow(clippy::too_many_arguments)] on test helper Import/module ordering (alphabetical): - state/mod.rs: move scope_picker mod + pub use to sorted position - view/mod.rs: move scope_picker, stats, sync mod + use to sorted position - view/scope_picker.rs: sort use imports (ScopeContext before ScopePickerState)
This commit is contained in:
@@ -172,7 +172,15 @@ pub fn fetch_recent_runs(conn: &Connection, limit: usize) -> Result<Vec<SyncRunI
|
|||||||
let run_id: Option<String> = row.get(8)?;
|
let run_id: Option<String> = row.get(8)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
id, status, command, started_at, finished_at, items, errors, error, run_id,
|
id,
|
||||||
|
status,
|
||||||
|
command,
|
||||||
|
started_at,
|
||||||
|
finished_at,
|
||||||
|
items,
|
||||||
|
errors,
|
||||||
|
error,
|
||||||
|
run_id,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.context("querying sync runs")?;
|
.context("querying sync runs")?;
|
||||||
@@ -265,6 +273,7 @@ mod tests {
|
|||||||
.expect("insert project");
|
.expect("insert project");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn insert_sync_run(
|
fn insert_sync_run(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
started_at: i64,
|
started_at: i64,
|
||||||
@@ -314,8 +323,26 @@ mod tests {
|
|||||||
create_sync_schema(&conn);
|
create_sync_schema(&conn);
|
||||||
|
|
||||||
let now = 1_700_000_000_000_i64;
|
let now = 1_700_000_000_000_i64;
|
||||||
insert_sync_run(&conn, now - 60_000, Some(now - 30_000), "succeeded", "sync", 100, 0, None);
|
insert_sync_run(
|
||||||
insert_sync_run(&conn, now - 120_000, Some(now - 90_000), "failed", "sync", 50, 2, Some("timeout"));
|
&conn,
|
||||||
|
now - 60_000,
|
||||||
|
Some(now - 30_000),
|
||||||
|
"succeeded",
|
||||||
|
"sync",
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
insert_sync_run(
|
||||||
|
&conn,
|
||||||
|
now - 120_000,
|
||||||
|
Some(now - 90_000),
|
||||||
|
"failed",
|
||||||
|
"sync",
|
||||||
|
50,
|
||||||
|
2,
|
||||||
|
Some("timeout"),
|
||||||
|
);
|
||||||
|
|
||||||
let clock = FakeClock::from_ms(now);
|
let clock = FakeClock::from_ms(now);
|
||||||
let result = detect_running_sync(&conn, &clock).unwrap();
|
let result = detect_running_sync(&conn, &clock).unwrap();
|
||||||
@@ -386,8 +413,26 @@ mod tests {
|
|||||||
create_sync_schema(&conn);
|
create_sync_schema(&conn);
|
||||||
|
|
||||||
let now = 1_700_000_000_000_i64;
|
let now = 1_700_000_000_000_i64;
|
||||||
insert_sync_run(&conn, now - 120_000, Some(now - 90_000), "succeeded", "sync", 100, 0, None);
|
insert_sync_run(
|
||||||
insert_sync_run(&conn, now - 60_000, Some(now - 30_000), "succeeded", "sync", 200, 0, None);
|
&conn,
|
||||||
|
now - 120_000,
|
||||||
|
Some(now - 90_000),
|
||||||
|
"succeeded",
|
||||||
|
"sync",
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
insert_sync_run(
|
||||||
|
&conn,
|
||||||
|
now - 60_000,
|
||||||
|
Some(now - 30_000),
|
||||||
|
"succeeded",
|
||||||
|
"sync",
|
||||||
|
200,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
let runs = fetch_recent_runs(&conn, 10).unwrap();
|
let runs = fetch_recent_runs(&conn, 10).unwrap();
|
||||||
assert_eq!(runs.len(), 2);
|
assert_eq!(runs.len(), 2);
|
||||||
@@ -425,7 +470,16 @@ mod tests {
|
|||||||
create_sync_schema(&conn);
|
create_sync_schema(&conn);
|
||||||
|
|
||||||
let now = 1_700_000_000_000_i64;
|
let now = 1_700_000_000_000_i64;
|
||||||
insert_sync_run(&conn, now - 60_000, Some(now - 15_000), "succeeded", "sync", 0, 0, None);
|
insert_sync_run(
|
||||||
|
&conn,
|
||||||
|
now - 60_000,
|
||||||
|
Some(now - 15_000),
|
||||||
|
"succeeded",
|
||||||
|
"sync",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
let runs = fetch_recent_runs(&conn, 10).unwrap();
|
let runs = fetch_recent_runs(&conn, 10).unwrap();
|
||||||
assert_eq!(runs[0].duration_ms, Some(45_000));
|
assert_eq!(runs[0].duration_ms, Some(45_000));
|
||||||
@@ -517,8 +571,26 @@ mod tests {
|
|||||||
|
|
||||||
let now = 1_700_000_000_000_i64;
|
let now = 1_700_000_000_000_i64;
|
||||||
insert_project(&conn, 1, "group/repo");
|
insert_project(&conn, 1, "group/repo");
|
||||||
insert_sync_run(&conn, now - 120_000, Some(now - 90_000), "succeeded", "sync", 150, 0, None);
|
insert_sync_run(
|
||||||
insert_sync_run(&conn, now - 60_000, Some(now - 30_000), "failed", "sync", 50, 2, Some("db locked"));
|
&conn,
|
||||||
|
now - 120_000,
|
||||||
|
Some(now - 90_000),
|
||||||
|
"succeeded",
|
||||||
|
"sync",
|
||||||
|
150,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
insert_sync_run(
|
||||||
|
&conn,
|
||||||
|
now - 60_000,
|
||||||
|
Some(now - 30_000),
|
||||||
|
"failed",
|
||||||
|
"sync",
|
||||||
|
50,
|
||||||
|
2,
|
||||||
|
Some("db locked"),
|
||||||
|
);
|
||||||
|
|
||||||
let clock = FakeClock::from_ms(now);
|
let clock = FakeClock::from_ms(now);
|
||||||
let overview = fetch_sync_overview(&conn, &clock).unwrap();
|
let overview = fetch_sync_overview(&conn, &clock).unwrap();
|
||||||
@@ -542,7 +614,16 @@ mod tests {
|
|||||||
insert_project(&conn, 1, "group/repo");
|
insert_project(&conn, 1, "group/repo");
|
||||||
|
|
||||||
// A completed run.
|
// A completed run.
|
||||||
insert_sync_run(&conn, now - 600_000, Some(now - 570_000), "succeeded", "sync", 200, 0, None);
|
insert_sync_run(
|
||||||
|
&conn,
|
||||||
|
now - 600_000,
|
||||||
|
Some(now - 570_000),
|
||||||
|
"succeeded",
|
||||||
|
"sync",
|
||||||
|
200,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
// A currently running sync.
|
// A currently running sync.
|
||||||
conn.execute(
|
conn.execute(
|
||||||
|
|||||||
@@ -590,7 +590,10 @@ impl LoreApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Search ---
|
// --- Search ---
|
||||||
Msg::SearchExecuted { generation, results } => {
|
Msg::SearchExecuted {
|
||||||
|
generation,
|
||||||
|
results,
|
||||||
|
} => {
|
||||||
if self
|
if self
|
||||||
.supervisor
|
.supervisor
|
||||||
.is_current(&TaskKey::LoadScreen(Screen::Search), generation)
|
.is_current(&TaskKey::LoadScreen(Screen::Search), generation)
|
||||||
|
|||||||
@@ -154,8 +154,16 @@ mod tests {
|
|||||||
// Insert a 4th item: should evict issue(2) (tick 2, lowest).
|
// Insert a 4th item: should evict issue(2) (tick 2, lowest).
|
||||||
cache.put(issue(4), "d"); // tick 5
|
cache.put(issue(4), "d"); // tick 5
|
||||||
|
|
||||||
assert_eq!(cache.get(&issue(1)), Some(&"a"), "issue(1) should survive (recently accessed)");
|
assert_eq!(
|
||||||
assert_eq!(cache.get(&issue(2)), None, "issue(2) should be evicted (LRU)");
|
cache.get(&issue(1)),
|
||||||
|
Some(&"a"),
|
||||||
|
"issue(1) should survive (recently accessed)"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cache.get(&issue(2)),
|
||||||
|
None,
|
||||||
|
"issue(2) should be evicted (LRU)"
|
||||||
|
);
|
||||||
assert_eq!(cache.get(&issue(3)), Some(&"c"), "issue(3) should survive");
|
assert_eq!(cache.get(&issue(3)), Some(&"c"), "issue(3) should survive");
|
||||||
assert_eq!(cache.get(&issue(4)), Some(&"d"), "issue(4) just inserted");
|
assert_eq!(cache.get(&issue(4)), Some(&"d"), "issue(4) just inserted");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ impl<V> RenderCache<V> {
|
|||||||
///
|
///
|
||||||
/// After a resize, only entries rendered at the new width are still valid.
|
/// After a resize, only entries rendered at the new width are still valid.
|
||||||
pub fn invalidate_width(&mut self, keep_width: u16) {
|
pub fn invalidate_width(&mut self, keep_width: u16) {
|
||||||
self.entries
|
self.entries.retain(|k, _| k.terminal_width == keep_width);
|
||||||
.retain(|k, _| k.terminal_width == keep_width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the entire cache (theme change — all colors invalidated).
|
/// Clear the entire cache (theme change — all colors invalidated).
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ pub fn save_session(state: &SessionState, path: &Path) -> Result<(), SessionErro
|
|||||||
fs::create_dir_all(parent).map_err(|e| SessionError::Io(e.to_string()))?;
|
fs::create_dir_all(parent).map_err(|e| SessionError::Io(e.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let json = serde_json::to_string_pretty(state)
|
let json =
|
||||||
.map_err(|e| SessionError::Serialize(e.to_string()))?;
|
serde_json::to_string_pretty(state).map_err(|e| SessionError::Serialize(e.to_string()))?;
|
||||||
|
|
||||||
// Check size before writing.
|
// Check size before writing.
|
||||||
if json.len() as u64 > MAX_SESSION_SIZE {
|
if json.len() as u64 > MAX_SESSION_SIZE {
|
||||||
@@ -112,8 +112,7 @@ pub fn save_session(state: &SessionState, path: &Path) -> Result<(), SessionErro
|
|||||||
|
|
||||||
// Write to temp file, fsync, rename.
|
// Write to temp file, fsync, rename.
|
||||||
let tmp_path = path.with_extension("tmp");
|
let tmp_path = path.with_extension("tmp");
|
||||||
let mut file =
|
let mut file = fs::File::create(&tmp_path).map_err(|e| SessionError::Io(e.to_string()))?;
|
||||||
fs::File::create(&tmp_path).map_err(|e| SessionError::Io(e.to_string()))?;
|
|
||||||
file.write_all(payload.as_bytes())
|
file.write_all(payload.as_bytes())
|
||||||
.map_err(|e| SessionError::Io(e.to_string()))?;
|
.map_err(|e| SessionError::Io(e.to_string()))?;
|
||||||
file.sync_all()
|
file.sync_all()
|
||||||
@@ -179,10 +178,7 @@ pub fn load_session(path: &Path) -> Result<SessionState, SessionError> {
|
|||||||
|
|
||||||
/// Move a corrupt session file to `.quarantine/` instead of deleting it.
|
/// Move a corrupt session file to `.quarantine/` instead of deleting it.
|
||||||
fn quarantine(path: &Path) -> Result<(), SessionError> {
|
fn quarantine(path: &Path) -> Result<(), SessionError> {
|
||||||
let quarantine_dir = path
|
let quarantine_dir = path.parent().unwrap_or(Path::new(".")).join(".quarantine");
|
||||||
.parent()
|
|
||||||
.unwrap_or(Path::new("."))
|
|
||||||
.join(".quarantine");
|
|
||||||
fs::create_dir_all(&quarantine_dir).map_err(|e| SessionError::Io(e.to_string()))?;
|
fs::create_dir_all(&quarantine_dir).map_err(|e| SessionError::Io(e.to_string()))?;
|
||||||
|
|
||||||
let filename = path
|
let filename = path
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ pub mod issue_detail;
|
|||||||
pub mod issue_list;
|
pub mod issue_list;
|
||||||
pub mod mr_detail;
|
pub mod mr_detail;
|
||||||
pub mod mr_list;
|
pub mod mr_list;
|
||||||
|
pub mod scope_picker;
|
||||||
pub mod search;
|
pub mod search;
|
||||||
pub mod stats;
|
pub mod stats;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod sync_delta_ledger;
|
pub mod sync_delta_ledger;
|
||||||
pub mod timeline;
|
pub mod timeline;
|
||||||
pub mod trace;
|
pub mod trace;
|
||||||
pub mod scope_picker;
|
|
||||||
pub mod who;
|
pub mod who;
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@@ -45,12 +45,12 @@ pub use issue_detail::IssueDetailState;
|
|||||||
pub use issue_list::IssueListState;
|
pub use issue_list::IssueListState;
|
||||||
pub use mr_detail::MrDetailState;
|
pub use mr_detail::MrDetailState;
|
||||||
pub use mr_list::MrListState;
|
pub use mr_list::MrListState;
|
||||||
|
pub use scope_picker::ScopePickerState;
|
||||||
pub use search::SearchState;
|
pub use search::SearchState;
|
||||||
pub use stats::StatsState;
|
pub use stats::StatsState;
|
||||||
pub use sync::SyncState;
|
pub use sync::SyncState;
|
||||||
pub use timeline::TimelineState;
|
pub use timeline::TimelineState;
|
||||||
pub use trace::TraceState;
|
pub use trace::TraceState;
|
||||||
pub use scope_picker::ScopePickerState;
|
|
||||||
pub use who::WhoState;
|
pub use who::WhoState;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -356,15 +356,15 @@ impl SyncState {
|
|||||||
self.bytes_synced = bytes;
|
self.bytes_synced = bytes;
|
||||||
self.items_synced = items;
|
self.items_synced = items;
|
||||||
// Compute actual throughput from elapsed time since sync start.
|
// Compute actual throughput from elapsed time since sync start.
|
||||||
if items > 0 {
|
if items > 0
|
||||||
if let Some(started) = self.started_at {
|
&& let Some(started) = self.started_at
|
||||||
|
{
|
||||||
let elapsed_secs = started.elapsed().as_secs_f64();
|
let elapsed_secs = started.elapsed().as_secs_f64();
|
||||||
if elapsed_secs > 0.0 {
|
if elapsed_secs > 0.0 {
|
||||||
self.items_per_sec = items as f64 / elapsed_secs;
|
self.items_per_sec = items as f64 / elapsed_secs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether sync is currently running.
|
/// Whether sync is currently running.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -375,8 +375,7 @@ impl SyncState {
|
|||||||
/// Overall progress fraction (average of all lanes).
|
/// Overall progress fraction (average of all lanes).
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn overall_progress(&self) -> f64 {
|
pub fn overall_progress(&self) -> f64 {
|
||||||
let active_lanes: Vec<&LaneProgress> =
|
let active_lanes: Vec<&LaneProgress> = self.lanes.iter().filter(|l| l.total > 0).collect();
|
||||||
self.lanes.iter().filter(|l| l.total > 0).collect();
|
|
||||||
if active_lanes.is_empty() {
|
if active_lanes.is_empty() {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
@@ -537,10 +536,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// With ~0ms between calls, at most 0-1 additional emits expected.
|
// With ~0ms between calls, at most 0-1 additional emits expected.
|
||||||
assert!(
|
assert!(emitted <= 1, "Expected at most 1 emit, got {emitted}");
|
||||||
emitted <= 1,
|
|
||||||
"Expected at most 1 emit, got {emitted}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -127,7 +127,9 @@ pub fn render_doctor(frame: &mut Frame<'_>, state: &DoctorState, area: Rect) {
|
|||||||
let detail = if check.detail.len() > max_detail {
|
let detail = if check.detail.len() > max_detail {
|
||||||
format!(
|
format!(
|
||||||
"{}...",
|
"{}...",
|
||||||
&check.detail[..check.detail.floor_char_boundary(max_detail.saturating_sub(3))]
|
&check.detail[..check
|
||||||
|
.detail
|
||||||
|
.floor_char_boundary(max_detail.saturating_sub(3))]
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
check.detail.clone()
|
check.detail.clone()
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ pub mod issue_detail;
|
|||||||
pub mod issue_list;
|
pub mod issue_list;
|
||||||
pub mod mr_detail;
|
pub mod mr_detail;
|
||||||
pub mod mr_list;
|
pub mod mr_list;
|
||||||
pub mod search;
|
|
||||||
pub mod timeline;
|
|
||||||
pub mod trace;
|
|
||||||
pub mod scope_picker;
|
pub mod scope_picker;
|
||||||
|
pub mod search;
|
||||||
pub mod stats;
|
pub mod stats;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
|
pub mod timeline;
|
||||||
|
pub mod trace;
|
||||||
pub mod who;
|
pub mod who;
|
||||||
|
|
||||||
use ftui::layout::{Constraint, Flex};
|
use ftui::layout::{Constraint, Flex};
|
||||||
@@ -43,12 +43,12 @@ use issue_detail::render_issue_detail;
|
|||||||
use issue_list::render_issue_list;
|
use issue_list::render_issue_list;
|
||||||
use mr_detail::render_mr_detail;
|
use mr_detail::render_mr_detail;
|
||||||
use mr_list::render_mr_list;
|
use mr_list::render_mr_list;
|
||||||
use search::render_search;
|
|
||||||
use timeline::render_timeline;
|
|
||||||
use trace::render_trace;
|
|
||||||
use scope_picker::render_scope_picker;
|
use scope_picker::render_scope_picker;
|
||||||
|
use search::render_search;
|
||||||
use stats::render_stats;
|
use stats::render_stats;
|
||||||
use sync::render_sync;
|
use sync::render_sync;
|
||||||
|
use timeline::render_timeline;
|
||||||
|
use trace::render_trace;
|
||||||
use who::render_who;
|
use who::render_who;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -261,10 +261,7 @@ mod tests {
|
|||||||
let has_content = (20..60u16).any(|x| {
|
let has_content = (20..60u16).any(|x| {
|
||||||
(8..16u16).any(|y| frame.buffer.get(x, y).is_some_and(|cell| !cell.is_empty()))
|
(8..16u16).any(|y| frame.buffer.get(x, y).is_some_and(|cell| !cell.is_empty()))
|
||||||
});
|
});
|
||||||
assert!(
|
assert!(has_content, "Expected sync idle content in center area");
|
||||||
has_content,
|
|
||||||
"Expected sync idle content in center area"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use ftui::render::cell::{Cell, PackedRgba};
|
|||||||
use ftui::render::drawing::{BorderChars, Draw};
|
use ftui::render::drawing::{BorderChars, Draw};
|
||||||
use ftui::render::frame::Frame;
|
use ftui::render::frame::Frame;
|
||||||
|
|
||||||
use crate::state::scope_picker::ScopePickerState;
|
|
||||||
use crate::state::ScopeContext;
|
use crate::state::ScopeContext;
|
||||||
|
use crate::state::scope_picker::ScopePickerState;
|
||||||
|
|
||||||
use super::{ACCENT, BG_SURFACE, BORDER, TEXT, TEXT_MUTED};
|
use super::{ACCENT, BG_SURFACE, BORDER, TEXT, TEXT_MUTED};
|
||||||
|
|
||||||
@@ -131,7 +131,10 @@ pub fn render_scope_picker(
|
|||||||
// Truncate label to fit.
|
// Truncate label to fit.
|
||||||
let max_label_len = content_width.saturating_sub(2) as usize; // 2 for prefix
|
let max_label_len = content_width.saturating_sub(2) as usize; // 2 for prefix
|
||||||
let display = if label.len() > max_label_len {
|
let display = if label.len() > max_label_len {
|
||||||
format!("{prefix}{}...", &label[..label.floor_char_boundary(max_label_len.saturating_sub(3))])
|
format!(
|
||||||
|
"{prefix}{}...",
|
||||||
|
&label[..label.floor_char_boundary(max_label_len.saturating_sub(3))]
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
format!("{prefix}{label}")
|
format!("{prefix}{label}")
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -93,7 +93,15 @@ pub fn render_stats(frame: &mut Frame<'_>, state: &StatsState, area: Rect) {
|
|||||||
if y >= area.bottom().saturating_sub(2) {
|
if y >= area.bottom().saturating_sub(2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
render_stat_row(frame, area.x + 2, y, label, &format_count(*count), label_width, max_x);
|
render_stat_row(
|
||||||
|
frame,
|
||||||
|
area.x + 2,
|
||||||
|
y,
|
||||||
|
label,
|
||||||
|
&format_count(*count),
|
||||||
|
label_width,
|
||||||
|
max_x,
|
||||||
|
);
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -262,8 +262,16 @@ fn render_summary(frame: &mut Frame<'_>, state: &SyncState, area: Rect) {
|
|||||||
// Summary rows.
|
// Summary rows.
|
||||||
let rows = [
|
let rows = [
|
||||||
("Issues", summary.issues.new, summary.issues.updated),
|
("Issues", summary.issues.new, summary.issues.updated),
|
||||||
("MRs", summary.merge_requests.new, summary.merge_requests.updated),
|
(
|
||||||
("Discussions", summary.discussions.new, summary.discussions.updated),
|
"MRs",
|
||||||
|
summary.merge_requests.new,
|
||||||
|
summary.merge_requests.updated,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Discussions",
|
||||||
|
summary.discussions.new,
|
||||||
|
summary.discussions.updated,
|
||||||
|
),
|
||||||
("Notes", summary.notes.new, summary.notes.updated),
|
("Notes", summary.notes.new, summary.notes.updated),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -404,7 +412,10 @@ fn render_failed(frame: &mut Frame<'_>, area: Rect, error: &str) {
|
|||||||
// Truncate error to fit screen.
|
// Truncate error to fit screen.
|
||||||
let max_len = area.width.saturating_sub(4) as usize;
|
let max_len = area.width.saturating_sub(4) as usize;
|
||||||
let display_err = if error.len() > max_len {
|
let display_err = if error.len() > max_len {
|
||||||
format!("{}...", &error[..error.floor_char_boundary(max_len.saturating_sub(3))])
|
format!(
|
||||||
|
"{}...",
|
||||||
|
&error[..error.floor_char_boundary(max_len.saturating_sub(3))]
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
error.to_string()
|
error.to_string()
|
||||||
};
|
};
|
||||||
@@ -541,9 +552,7 @@ mod tests {
|
|||||||
state.complete(3000);
|
state.complete(3000);
|
||||||
state.summary = Some(SyncSummary {
|
state.summary = Some(SyncSummary {
|
||||||
elapsed_ms: 3000,
|
elapsed_ms: 3000,
|
||||||
project_errors: vec![
|
project_errors: vec![("grp/repo".into(), "timeout".into())],
|
||||||
("grp/repo".into(), "timeout".into()),
|
|
||||||
],
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let area = frame.bounds();
|
let area = frame.bounds();
|
||||||
|
|||||||
Reference in New Issue
Block a user