diff --git a/README.md b/README.md index 38cc2ee..2a953fb 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ The project is under active development. Core blogging workflows are broadly ava - Persistent conversational AI with safe Markdown, streamed and cancellable responses, model/session/token tracking, bounded project-aware blog tools, and localized conversation management in the Chat workspace. Allowlisted render tools add persistent native cards, charts, forms, lists, metrics, mind maps, tables, and tabs without executing assistant-provided HTML or JavaScript. - SSH-agent-based SCP or rsync publishing. - Integrated Git workflow for each blog project's current repository, with repository initialization, read-only origin discovery, Git LFS image tracking, status and diffs, branch/file history with bDS2-compatible sync-status colors, commits, cancellable fetch/pull/push, and post-pull filesystem reconciliation; network actions respect airplane mode. -- Site, media, and translation validation plus `ruds://new-post` Blogmark capture and Lua transforms; captures open directly in the post editor and defer automatic translation until an explicit manual save, which queues one task per still-missing language. Publishing never starts automatic translation. bDS2 keeps its separate `bds2://` bookmarklet protocol. +- Site, media, and translation validation plus `ruds://new-post` Blogmark capture and Lua transforms; captures open directly in the post editor and defer automatic translation until an explicit manual save, which queues one task per still-missing language. Rendering tasks keep long generated URLs compact in progress messages. Publishing never starts automatic translation. bDS2 keeps its separate `bds2://` bookmarklet protocol. RuDS uses no JavaScript application runtime and loads no CSS or JavaScript from CDNs. The preview is served by the Rust application and displayed by the operating-system webview. diff --git a/crates/bds-ui/src/app/tasks.rs b/crates/bds-ui/src/app/tasks.rs index 3f678cf..fcad1e3 100644 --- a/crates/bds-ui/src/app/tasks.rs +++ b/crates/bds-ui/src/app/tasks.rs @@ -1,5 +1,18 @@ use super::*; +const TASK_URL_MAX_CHARS: usize = 60; + +fn shorten_task_url(url: &str) -> String { + if url.chars().count() <= TASK_URL_MAX_CHARS { + url.to_string() + } else { + format!( + "{}…", + url.chars().take(TASK_URL_MAX_CHARS - 1).collect::() + ) + } +} + impl BdsApp { pub(super) fn refresh_task_snapshots(&mut self) { self.task_snapshots = self @@ -524,6 +537,7 @@ fn run_site_generation_section( let on_page = |_current: usize, _total: usize, _url: &str| {}; let on_rendered = move |url: &str| { let current = rendered_count.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + 1; + let url = shorten_task_url(url); render_manager.report_progress( task_id, Some(if expected_pages == 0 { @@ -535,7 +549,7 @@ fn run_site_generation_section( locale, "engine.renderingPage", &[ - ("url", url), + ("url", &url), ("current", ¤t.to_string()), ("total", &expected_pages.to_string()), ], @@ -581,3 +595,16 @@ fn run_site_generation_section( } .map_err(|error| error.to_string()) } + +#[cfg(test)] +mod tests { + use super::shorten_task_url; + + #[test] + fn task_urls_stay_single_line_without_splitting_unicode() { + assert_eq!(shorten_task_url("/short"), "/short"); + let shortened = shorten_task_url(&format!("/{}", "ä".repeat(80))); + assert_eq!(shortened.chars().count(), 60); + assert!(shortened.ends_with('…')); + } +}