fix(app-iced): M119 出图抓到的两处:右栏文案没跟 lang 走、确认条文字被压成竖缝

两张验收图(`DevDocs/artifacts/m119/`)暴露的问题,都是测试抓不住、只有图能看出来的那类:

1. **同屏两语**:`pages/agent/mod.rs` 里还留着 M104 的 `const LANG: Lang = Lang::En`,所以右栏的
   标题/按钮恒英文,而 M119 新加的失败横幅走 `App::lang()`(这台机器是 zh-CN)⇒ 一屏里
   「Assistant / Collapse」和「连不上助手后端」并排。现在删掉那个常量,`docked`/`page` 收一个
   `Catalog` 形参,由 `App::lang().catalog()` 给——与设置页/账户页同一条口径(M106 的真值源)。

2. **确认条没有字**:`chip + 文字 + 两个按钮` 挤在同一条 `Row` 里,而右栗只有 280~360:320 宽下
   文字列被压成一条竖缝,标题整段看不见(图 05 第一版就是这个样子)。改成文字行与动作**分行**,
   动作右对齐——窄栏里才是可读的 M3 告警形态。

顺带:`Script::WriteOp` 补一句增量,免得那条助手气泡是空壳(出图更接近真后端)。

`cargo test -p unlucky-app-iced --lib`:599 passed / 0 failed;14 张图重出后逐张看过。
This commit is contained in:
AskaEth committed 2026-11-05 08:11:14 +08:00
1 parent d4fd675935
commit b5e96c61ac
8 files changed
+60 -27

No files matched your search

+20 -3
View File
@@ -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,
@@ -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)),
@@ -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)
+7 -12
View File
@@ -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<Failure<'a>>,
catalog: Catalog,
window_width: f32,
) -> Option<Element<'a, Message>> {
// 判档用**这一窗宽下实际生效**的档位:窗窄到放不下 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<Failure<'a>>,
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<Failure<'a>>,
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,
+1 -2
View File
@@ -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),未读点叠在右上角;下面两行小字保证「不得只有图标」:
+3 -2
View File
@@ -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,
@@ -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);
}
@@ -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,
}));