diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-18 09:50:57 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-18 13:01:01 +0000 |
| commit | ef53dce22cb363d9b373cae033f4be91f6cfb194 (patch) | |
| tree | c9d4c20395eff9b9790ade9d43a9acec908c1cd9 /src/lib | |
| parent | 10f5dd5f48659d6e99abc762d46be397d24b48d9 (diff) | |
report event kinds in publish progress messages
instead of generic 'Publishing to nostr relays...' messages, describe
what is being published e.g. 'Publishing 3 patches to nostr relays...'
or 'Publishing 1 announcement and 1 state event to nostr relays...'
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/client.rs | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/src/lib/client.rs b/src/lib/client.rs index 42f3f6d..34fdb50 100644 --- a/src/lib/client.rs +++ b/src/lib/client.rs | |||
| @@ -2459,6 +2459,8 @@ pub async fn send_events( | |||
| 2459 | let is_test = std::env::var("NGITTEST").is_ok(); | 2459 | let is_test = std::env::var("NGITTEST").is_ok(); |
| 2460 | let use_concise = !is_test || (!verbose && !silent && animate); | 2460 | let use_concise = !is_test || (!verbose && !silent && animate); |
| 2461 | 2461 | ||
| 2462 | let events_description = describe_events(&events); | ||
| 2463 | |||
| 2462 | // Set up the two-MultiProgress pattern (same as fetch_all): | 2464 | // Set up the two-MultiProgress pattern (same as fetch_all): |
| 2463 | // 1. A spinner MultiProgress shown immediately (concise mode only) | 2465 | // 1. A spinner MultiProgress shown immediately (concise mode only) |
| 2464 | // 2. A detail MultiProgress that starts hidden and becomes visible after a | 2466 | // 2. A detail MultiProgress that starts hidden and becomes visible after a |
| @@ -2472,7 +2474,9 @@ pub async fn send_events( | |||
| 2472 | .unwrap() | 2474 | .unwrap() |
| 2473 | .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈"), | 2475 | .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈"), |
| 2474 | ) | 2476 | ) |
| 2475 | .with_message("Publishing to nostr relays..."), | 2477 | .with_message(format!( |
| 2478 | "Publishing {events_description} to nostr relays..." | ||
| 2479 | )), | ||
| 2476 | ); | 2480 | ); |
| 2477 | spinner.enable_steady_tick(Duration::from_millis(100)); | 2481 | spinner.enable_steady_tick(Duration::from_millis(100)); |
| 2478 | Some((sm, spinner)) | 2482 | Some((sm, spinner)) |
| @@ -2492,7 +2496,9 @@ pub async fn send_events( | |||
| 2492 | let bar = | 2496 | let bar = |
| 2493 | m.add(ProgressBar::new(0).with_style(ProgressStyle::with_template("{msg}").unwrap())); | 2497 | m.add(ProgressBar::new(0).with_style(ProgressStyle::with_template("{msg}").unwrap())); |
| 2494 | if !is_test { | 2498 | if !is_test { |
| 2495 | bar.set_message("Publishing to nostr relays..."); | 2499 | bar.set_message(format!( |
| 2500 | "Publishing {events_description} to nostr relays..." | ||
| 2501 | )); | ||
| 2496 | } | 2502 | } |
| 2497 | Some(bar) | 2503 | Some(bar) |
| 2498 | }; | 2504 | }; |
| @@ -2511,6 +2517,7 @@ pub async fn send_events( | |||
| 2511 | let spinner_for_timer = spinner_multi.as_ref().map(|(_, s)| s.clone()); | 2517 | let spinner_for_timer = spinner_multi.as_ref().map(|(_, s)| s.clone()); |
| 2512 | let reveal_state_for_timer = reveal_state.clone(); | 2518 | let reveal_state_for_timer = reveal_state.clone(); |
| 2513 | let heading_bar_for_timer = heading_bar.clone(); | 2519 | let heading_bar_for_timer = heading_bar.clone(); |
| 2520 | let events_description_for_timer = events_description.clone(); | ||
| 2514 | let timer_handle = if use_concise { | 2521 | let timer_handle = if use_concise { |
| 2515 | let handle = tokio::spawn(async move { | 2522 | let handle = tokio::spawn(async move { |
| 2516 | tokio::time::sleep(Duration::from_millis(SPINNER_EXPAND_DELAY_MS)).await; | 2523 | tokio::time::sleep(Duration::from_millis(SPINNER_EXPAND_DELAY_MS)).await; |
| @@ -2519,7 +2526,9 @@ pub async fn send_events( | |||
| 2519 | } | 2526 | } |
| 2520 | detail_multi_for_timer.set_draw_target(ProgressDrawTarget::stderr()); | 2527 | detail_multi_for_timer.set_draw_target(ProgressDrawTarget::stderr()); |
| 2521 | if let Some(heading) = heading_bar_for_timer { | 2528 | if let Some(heading) = heading_bar_for_timer { |
| 2522 | heading.finish_with_message("publishing to nostr relays..."); | 2529 | heading.finish_with_message(format!( |
| 2530 | "Publishing {events_description_for_timer} to nostr relays..." | ||
| 2531 | )); | ||
| 2523 | } | 2532 | } |
| 2524 | if let Some(state) = reveal_state_for_timer { | 2533 | if let Some(state) = reveal_state_for_timer { |
| 2525 | let mut deferred = state.deferred.lock().unwrap(); | 2534 | let mut deferred = state.deferred.lock().unwrap(); |
| @@ -2650,12 +2659,76 @@ pub async fn send_events( | |||
| 2650 | } | 2659 | } |
| 2651 | if let Some((_, spinner)) = &spinner_multi { | 2660 | if let Some((_, spinner)) = &spinner_multi { |
| 2652 | spinner.set_style(ProgressStyle::with_template("{msg}").unwrap()); | 2661 | spinner.set_style(ProgressStyle::with_template("{msg}").unwrap()); |
| 2653 | spinner.finish_with_message("Published to nostr relays"); | 2662 | spinner.finish_with_message(format!("Published {events_description} to nostr relays")); |
| 2654 | } | 2663 | } |
| 2655 | 2664 | ||
| 2656 | Ok(()) | 2665 | Ok(()) |
| 2657 | } | 2666 | } |
| 2658 | 2667 | ||
| 2668 | /// Builds a human-readable description of what is being published, e.g. | ||
| 2669 | /// "3 patches", "1 announcement and 1 state event", "2 patches and 1 cover | ||
| 2670 | /// letter". | ||
| 2671 | fn describe_events(events: &[nostr::Event]) -> String { | ||
| 2672 | use crate::git_events::{KIND_PULL_REQUEST, KIND_PULL_REQUEST_UPDATE, KIND_USER_GRASP_LIST}; | ||
| 2673 | |||
| 2674 | // key = singular, value = (plural, count) | ||
| 2675 | let mut counts: std::collections::BTreeMap<&str, (&str, usize)> = | ||
| 2676 | std::collections::BTreeMap::new(); | ||
| 2677 | |||
| 2678 | for event in events { | ||
| 2679 | let (singular, plural) = if event.kind.eq(&Kind::GitRepoAnnouncement) { | ||
| 2680 | ("announcement", "announcements") | ||
| 2681 | } else if event.kind.eq(&STATE_KIND) { | ||
| 2682 | ("state event", "state events") | ||
| 2683 | } else if event_is_cover_letter(event) { | ||
| 2684 | ("cover letter", "cover letters") | ||
| 2685 | } else if event.kind.eq(&Kind::GitPatch) { | ||
| 2686 | ("patch", "patches") | ||
| 2687 | } else if event.kind.eq(&KIND_PULL_REQUEST) { | ||
| 2688 | ("PR", "PRs") | ||
| 2689 | } else if event.kind.eq(&KIND_PULL_REQUEST_UPDATE) { | ||
| 2690 | ("PR update", "PR updates") | ||
| 2691 | } else if [ | ||
| 2692 | Kind::GitStatusOpen, | ||
| 2693 | Kind::GitStatusDraft, | ||
| 2694 | Kind::GitStatusClosed, | ||
| 2695 | Kind::GitStatusApplied, | ||
| 2696 | ] | ||
| 2697 | .contains(&event.kind) | ||
| 2698 | { | ||
| 2699 | ("status update", "status updates") | ||
| 2700 | } else if event.kind.eq(&KIND_USER_GRASP_LIST) { | ||
| 2701 | ("user relay list", "user relay lists") | ||
| 2702 | } else { | ||
| 2703 | ("event", "events") | ||
| 2704 | }; | ||
| 2705 | counts | ||
| 2706 | .entry(singular) | ||
| 2707 | .and_modify(|(_, c)| *c += 1) | ||
| 2708 | .or_insert((plural, 1)); | ||
| 2709 | } | ||
| 2710 | |||
| 2711 | let parts: Vec<String> = counts | ||
| 2712 | .iter() | ||
| 2713 | .map(|(singular, (plural, n))| { | ||
| 2714 | if *n == 1 { | ||
| 2715 | format!("1 {singular}") | ||
| 2716 | } else { | ||
| 2717 | format!("{n} {plural}") | ||
| 2718 | } | ||
| 2719 | }) | ||
| 2720 | .collect(); | ||
| 2721 | |||
| 2722 | match parts.len() { | ||
| 2723 | 0 => "0 events".to_string(), | ||
| 2724 | 1 => parts[0].clone(), | ||
| 2725 | _ => { | ||
| 2726 | let (last, rest) = parts.split_last().unwrap(); | ||
| 2727 | format!("{} and {last}", rest.join(", ")) | ||
| 2728 | } | ||
| 2729 | } | ||
| 2730 | } | ||
| 2731 | |||
| 2659 | fn remove_trailing_slash(s: &str) -> String { | 2732 | fn remove_trailing_slash(s: &str) -> String { |
| 2660 | match s.strip_suffix('/') { | 2733 | match s.strip_suffix('/') { |
| 2661 | Some(s) => s, | 2734 | Some(s) => s, |