feat(app-iced): M104 AGENTRAIL —— 右栗三档 + 布局数学 + 独立页复用同一会话视图
用户定案(D16):右侧常驻可折叠、允许拆分成独立页、中栗宽度可调(磁铁吸附)。 本 mission 只做壳:三档状态 + 布局数学 + 一份会话视图;真数据仍归 M103,一行 presenter 都不调。 - 右栗三档:Collapsed(48) / Expanded(280~360,默认 320,锚=令牌 ai_panel_width) / Detached(Route::Agent); 会话、草稿、未读在切档时一条不丢(拆出去再收回,话说了一半还在) - 布局数学:中栗 = 窗口 − 右栗 − 拖拽缝(8),下限 472(= 行宽上限 424 + 两侧页边距); 右栗一展开,页面按更窄的宽度重新排版(收缩而不是溢出);拖拽磁铁吸附到 280/320/360,超上限夹紧 - 独立页与右栗共用 conversation::view 这一份实现(输入=纯数据,输出=agent::Message) - 控件:多行输入框(Enter 发送 / Shift+Enter 换行,走 text_editor::key_binding 的 modifiers 分流)、 发送禁用态、流式中断、未读点 + 可读计数、⌄ 收起 / ⇥ 拆出 / ⇤ 收回;Esc 收栗、Tab 焦点环、Enter 激活 - 文案全部进 crates/i18n 的新域 catalog/agent.rs(+ golden 追加 20 行),零硬编码中文 - 取证:ULL_AGENT_RAIL / ULL_AGENT_FIXTURE / ULL_AGENT_WIDTH(截图走产品 bin,标题栏与三键可见) - 消息不走 pages::Message(外壳级视图),走 app::Message::Agent(..) → app/update/agent.rs - 删掉 M68 骨架回落(shell::view + shell/fallback.rs):Route::Agent 现在有真页面 门禁:fmt 0 / clippy(workspace,-D warnings) 0 / pages_demo 0 / app-iced lib 418 条全绿
This commit is contained in:
1 parent
875ac159ee
commit
c3f20784a8
20 files changed
+2463
-153
No files matched your search
@@ -12,7 +12,7 @@ use unlucky_presenter::state::AppState;
|
||||
use crate::app::components::interaction::Interaction;
|
||||
use crate::cli::Screen;
|
||||
use crate::pages::{self, Detail, Meta, Row};
|
||||
use crate::shell::{self, NavItem};
|
||||
use crate::shell::{self, agent, NavItem};
|
||||
|
||||
use super::message::{nav_item_of, Message};
|
||||
use super::state::{log_first_frame, App};
|
||||
@@ -57,6 +57,13 @@ impl App {
|
||||
pages::appearance::layer(&self.ui, &self.appearance, (self.width, self.height))
|
||||
.map(|element| element.map(Message::Page));
|
||||
|
||||
// 右栗(M104):`Detached` 档返回 `None`(会话已经在独立页里);拖拽期间另有一层
|
||||
// 铺满窗口的取指针层,所以两件东西分开传。
|
||||
let right = agent::docked(&self.ui, &self.agent, self.width)
|
||||
.map(|element| element.map(Message::Agent));
|
||||
let overlay =
|
||||
agent::drag_overlay(&self.agent).map(|element| element.map(Message::Agent));
|
||||
|
||||
shell::view_with_background(
|
||||
&self.ui,
|
||||
nav_item_of(self.state.route()),
|
||||
@@ -73,19 +80,31 @@ impl App {
|
||||
},
|
||||
)
|
||||
.map(Message::Page),
|
||||
right,
|
||||
overlay,
|
||||
self.options.force_state,
|
||||
)
|
||||
}
|
||||
// `Route::Agent`:AI 独立页(M104)。它与右栗**共用**同一个会话视图
|
||||
// (`agent::page` 内部调的是 `conversation::view`),这里只是把会话摆进页面槽位。
|
||||
None => {
|
||||
let background =
|
||||
pages::appearance::layer(&self.ui, &self.appearance, (self.width, self.height))
|
||||
.map(|element| element.map(Message::Page));
|
||||
let overlay =
|
||||
agent::drag_overlay(&self.agent).map(|element| element.map(Message::Agent));
|
||||
|
||||
shell::view_with_background(
|
||||
&self.ui,
|
||||
NavItem::Ai,
|
||||
APP_TITLE,
|
||||
background,
|
||||
agent::page(&self.ui, &self.agent, self.width).map(Message::Agent),
|
||||
None,
|
||||
overlay,
|
||||
self.options.force_state,
|
||||
)
|
||||
}
|
||||
// `Route::Agent`:AI 独立页还没有页面实现(P1),回退到 M68 的外壳卡(同一套装饰)。
|
||||
None => shell::view(
|
||||
&self.ui,
|
||||
NavItem::Ai,
|
||||
APP_TITLE,
|
||||
NavItem::Ai.label(),
|
||||
"The assistant page is not built yet (P1). Chat lives in the docked panel once \
|
||||
the AI mission lands; this screen is the M68 skeleton fallback.",
|
||||
self.options.force_state,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,6 +114,10 @@ impl App {
|
||||
/// 把 presenter 的快照转成页面视图模型(**唯一**的展示转换点)。
|
||||
///
|
||||
/// `forced` 是 `--force-state` 的落点(P3-1):它只影响**画出来的**状态层,不改任何状态机。
|
||||
///
|
||||
/// `width` 是**中栗可用宽度**(窗口 − 右栗 − 拖拽缝,由 `AgentUi::content_width` 算),不是窗口宽:
|
||||
/// 页面布局系统仍按「一个窗口宽」扣左轨与页边距,所以右栗占掉的那一段必须在这里先减掉——
|
||||
/// 否则助手栏一展开,页面还按 1180 排版,内容就顶到面板底下了(任务里的「收缩而不是溢出」)。
|
||||
pub(super) fn model(
|
||||
state: &AppState,
|
||||
width: f32,
|
||||
|
||||
Reference in new issue
Block a user