diff --git a/crates/app-iced/src/app/view.rs b/crates/app-iced/src/app/view.rs index 5910a61..b87b3c5 100644 --- a/crates/app-iced/src/app/view.rs +++ b/crates/app-iced/src/app/view.rs @@ -60,6 +60,8 @@ impl App { // 备好的**展示输入**(标题 catalog 键 + 已脱敏正文)。壳在这里不做任何脱敏。 let rail = self.agent_host.rail(); let failure = self.agent_failure(); + // 界面语言的真值源是 `App::lang`(M106):右栏的静态文案也走它,不再有 `const LANG` + let agent_catalog = self.lang().catalog(); let account = self.rail_account(); match pages::Screen::of(self.state.route()) { @@ -83,8 +85,15 @@ impl App { self.language(), ) .map(Message::Page), - agent::docked(&self.ui, &self.agent, rail, failure, self.width) - .map(|element| element.map(Message::Agent)), + agent::docked( + &self.ui, + &self.agent, + rail, + failure, + agent_catalog, + self.width, + ) + .map(|element| element.map(Message::Agent)), overlay, self.options.force_state, self.lang(), @@ -103,7 +112,15 @@ impl App { }, APP_TITLE, background, - agent::page(&self.ui, &self.agent, rail, failure, self.width).map(Message::Agent), + agent::page( + &self.ui, + &self.agent, + rail, + failure, + agent_catalog, + self.width, + ) + .map(Message::Agent), None, overlay, self.options.force_state, diff --git a/crates/app-iced/src/app/view/account_page.rs b/crates/app-iced/src/app/view/account_page.rs index e42e2ec..75a81dd 100644 --- a/crates/app-iced/src/app/view/account_page.rs +++ b/crates/app-iced/src/app/view/account_page.rs @@ -58,6 +58,7 @@ impl App { &self.agent, self.agent_host.rail(), self.agent_failure(), + self.lang().catalog(), self.width, ) .map(|element| element.map(Message::Agent)), diff --git a/crates/app-iced/src/pages/agent/conversation/banners.rs b/crates/app-iced/src/pages/agent/conversation/banners.rs index 83f62da..9585a44 100644 --- a/crates/app-iced/src/pages/agent/conversation/banners.rs +++ b/crates/app-iced/src/pages/agent/conversation/banners.rs @@ -129,18 +129,26 @@ fn banner<'a>( )); } - let mut content = Row::new() + // 文字行与动作**分行**:右栗只有 280~360,chip + 两个按钮已占掉大半宽, + // 把文字挤在同一条 Row 里会被压成一条竖缝(M119 实测:320 宽下标题整段看不见)。 + let head = Row::new() .spacing(ui.space(Space::X3)) .align_y(Alignment::Center) .width(Length::Fill) .push(chip) - .push(Element::from(container(lines).width(Length::Fill))); + .push(container(lines).width(Length::Fill)); + + let mut content = column![Element::from(head)].spacing(ui.space(Space::X2)); if !actions.is_empty() { - content = content.push(Element::from( - row(actions) - .spacing(ui.space(Space::X2)) - .align_y(Alignment::Center), - )); + content = content.push( + container( + row(actions) + .spacing(ui.space(Space::X2)) + .align_y(Alignment::Center), + ) + .width(Length::Fill) + .align_x(Alignment::End), + ); } container(content) diff --git a/crates/app-iced/src/pages/agent/mod.rs b/crates/app-iced/src/pages/agent/mod.rs index b59f926..15a8477 100644 --- a/crates/app-iced/src/pages/agent/mod.rs +++ b/crates/app-iced/src/pages/agent/mod.rs @@ -57,7 +57,7 @@ use unlucky_design::elevation::MaterialLayer; use unlucky_design::shape::ShapeScale; use unlucky_design::spacing::Space; use unlucky_design::typography::TypeRole; -use unlucky_i18n::{Catalog, Key, Lang}; +use unlucky_i18n::{Catalog, Key}; use unlucky_presenter::agent::AgentRail; use unlucky_presenter::dto::AppEvent; @@ -68,9 +68,6 @@ use crate::theme::Ui; use conversation::{Conversation, Host}; use metrics::RESIZE_GUTTER; -/// 界面语言(与产品其它页面同一口径:i18n 接线前是英文基线,D28 的「英文环境零中文负担」)。 -const LANG: Lang = Lang::En; - /// 助手栏消息(**唯一**的消息类型;`app/view.rs` 用 `Message::Agent(..)` 包一层)。 #[derive(Debug, Clone)] pub enum Message { @@ -137,14 +134,15 @@ pub fn docked<'a>( agent: &'a AgentUi, rail: &'a AgentRail, failure: Option>, + catalog: Catalog, window_width: f32, ) -> Option> { // 判档用**这一窗宽下实际生效**的档位:窗窄到放不下 280 时,`Expanded` 事实上就是折叠条 // (否则会画一条 48 宽、还白扣 8px 拖拽缝的「面板」)。 match agent.effective_rail(window_width) { RailState::Detached => None, - RailState::Collapsed => Some(strip::strip(ui, rail)), - RailState::Expanded => Some(panel(ui, agent, rail, failure, window_width)), + RailState::Collapsed => Some(strip::strip(ui, rail, catalog)), + RailState::Expanded => Some(panel(ui, agent, rail, failure, catalog, window_width)), } } @@ -156,15 +154,12 @@ pub fn page<'a>( agent: &'a AgentUi, rail: &'a AgentRail, failure: Option>, + catalog: Catalog, window_width: f32, ) -> Element<'a, Message> { let metrics = layout::frame_metrics(pages::PaneKit::Single, window_width); - let body = conversation::view( - ui, - spec(agent, rail, failure, Host::Page), - Catalog::of(LANG), - ); + let body = conversation::view(ui, spec(agent, rail, failure, Host::Page), catalog); container( container(body) @@ -219,10 +214,10 @@ fn panel<'a>( agent: &'a AgentUi, rail: &'a AgentRail, failure: Option>, + catalog: Catalog, window_width: f32, ) -> Element<'a, Message> { let width = agent.rail_width(window_width); - let catalog = Catalog::of(LANG); let body = container(conversation::view( ui, diff --git a/crates/app-iced/src/pages/agent/strip.rs b/crates/app-iced/src/pages/agent/strip.rs index 6254c90..d9d335b 100644 --- a/crates/app-iced/src/pages/agent/strip.rs +++ b/crates/app-iced/src/pages/agent/strip.rs @@ -26,8 +26,7 @@ use super::metrics::COLLAPSED_WIDTH; use super::{conversation, Message}; /// 折叠条。 -pub(super) fn strip<'a>(ui: &'a Ui, rail: &'a AgentRail) -> Element<'a, Message> { - let catalog = Catalog::of(super::LANG); +pub(super) fn strip<'a>(ui: &'a Ui, rail: &'a AgentRail, catalog: Catalog) -> Element<'a, Message> { let side = ui.metrics().control_height; // 图标按钮 40×40(M3 icon button),未读点叠在右上角;下面两行小字保证「不得只有图标」: diff --git a/crates/app-iced/src/pages/agent/tests.rs b/crates/app-iced/src/pages/agent/tests.rs index 6eff0b5..7c83a25 100644 --- a/crates/app-iced/src/pages/agent/tests.rs +++ b/crates/app-iced/src/pages/agent/tests.rs @@ -330,8 +330,9 @@ fn every_state_builds_in_both_hosts() { let mut agent = AgentUi::new(); agent.rail = state; for shown in [None, Some(failure)] { - let _: iced::Element<'_, Message> = page(&ui, &agent, rail, shown, window); - let _ = docked(&ui, &agent, rail, shown, window); + let _: iced::Element<'_, Message> = + page(&ui, &agent, rail, shown, catalog, window); + let _ = docked(&ui, &agent, rail, shown, catalog, window); let spec = Conversation { messages: &rail.messages, draft: &agent.draft, diff --git a/crates/app-iced/src/pages/agent/tests/drag.rs b/crates/app-iced/src/pages/agent/tests/drag.rs index d4e2de9..371cb2b 100644 --- a/crates/app-iced/src/pages/agent/tests/drag.rs +++ b/crates/app-iced/src/pages/agent/tests/drag.rs @@ -32,7 +32,15 @@ fn the_detached_state_frees_the_rail_slot() { let ui = ui(); let mut agent = AgentUi::new(); agent.detach(); - assert!(docked(&ui, &agent, &AgentRail::new(), None, 1180.0).is_none()); + assert!(docked( + &ui, + &agent, + &AgentRail::new(), + None, + unlucky_i18n::Catalog::of(unlucky_i18n::Lang::En), + 1180.0 + ) + .is_none()); assert_eq!(agent.rail_width(1180.0), 0.0); assert_eq!(agent.content_width(1180.0), 1180.0); } diff --git a/crates/app-iced/src/presenter/transport.rs b/crates/app-iced/src/presenter/transport.rs index 603fdfa..947d3d9 100644 --- a/crates/app-iced/src/presenter/transport.rs +++ b/crates/app-iced/src/presenter/transport.rs @@ -208,6 +208,10 @@ impl AgentTransport for RigTransport { })); } Script::WriteOp => { + events.push(agent_event(AgentEvent::MessageDelta { + index: assistant, + delta: "我准备把下载并发从 64 改成 16,改之前先问一句。".to_string(), + })); events.push(agent_event(AgentEvent::MessageFinished { index: assistant, }));