fix(app-iced): M104 r2 —— Route::Agent ⟺ Detached 的不变式 + 复审 P3 六条
p2-1(唯一 p2):`Route::Agent` 与 `RailState::Detached` 之前没有绑定——从左侧导航第五项 (本 mission 点名的入口)进独立页时档位还是 Collapsed/Expanded,于是页头出现「Open assistant」 「Collapse/Pop out」、挂着不化的未读胶囊、Esc 也收不走页面(复审用产品 bin 复现)。 - **单一入口**:`App::sync_agent_route()`(update/agent.rs)在 `refresh_view` 开头调用, 两条对向规则:在独立页 ⇒ Detached(顺带清未读);离开独立页而档位还是 Detached ⇒ 收回右栗。 每一次路由变化都经过 refresh_view,所以导航 / ULL_START_ROUTE / detach / back 共用这一处。 - **结构性兜底**:`conversation::actions` 先按宿主分流,`Host::Page` 的动作恒为「Dock back」。 - **启动顺序**:`boot_agent()`(窗口尺寸 adopt + 拆出档直达独立页)必须在 `dispatch(RefreshAll)` 之前——那次 dispatch 会 pump→auto_select 把路由拉到实例详情,同步器随即把档位收回(实测踩到)。 - 测试:`entering_the_agent_route_detaches_the_rail`(走 `Message::Select(NavItem::Ai)` 真路径, 含未读清零 / Esc 离开 / 从页上点别的导航收回)、`the_page_navigation_entry_also_detaches`。 变异自证:把 `sync_agent_route` 改成 no-op ⇒ 3 红(含这两条)。 - 图 13/14:导航入口(折叠档带 2 条未读 / 展开档)进页后都是 Dock back、无未读胶囊、副标题单行。 P3-2 Enter/Shift+Enter 有测试了:分流抽成纯函数 `composer::binding_for`, `enter_sends_and_shift_enter_breaks_the_line` 覆盖「发送 / 换行 / 未聚焦不抢 / 其它键交回默认」; `AgentUi::edit` 里与 fallthrough 等价的冗余 Enter 分支删掉;三档测试改走 `agent.edit(...)`。 P3-4 自证式断言换字面量(320+8+852=1180 等);变异 RESIZE_GUTTER 8→0 ⇒ 6 红(含这条)。 P3-5 两条死文案真用上:8px 拖拽缝有了 tooltip(AgentResize + AgentWidthLabel「当前多宽」)。 P3-6 `on_boot` 的两块逻辑搬进 `update/agent.rs::boot_agent`:update.rs 372→383(+11,见报告逐行)。 P3-7 拖拽层补 on_press/on_exit:窗外松手不再僵住(窗内按下→清态;离窗→收在当前值)。 P3-9 顺手:只有几何/路由会变的消息才重建视图模型(每个字符、每次指针移动不再重建)。 门禁:fmt 0 / clippy(workspace,-D warnings) 0 / pages_demo 0 / 全文件 ≤400(最大 view.rs 373 之外 conversation.rs 383、update.rs 383)
This commit is contained in:
1 parent
8db1c5ab16
commit
9253684387
11 files changed
+495
-208
No files matched your search
@@ -40,7 +40,7 @@ use crate::renderer::Kind;
|
||||
|
||||
use super::message::{route_of, Message};
|
||||
use super::state::{App, IDLE_TICK, TICK, TICK_MS, WATCH_WINDOW};
|
||||
use super::{CAPTURE_AT_FRAME, MIN_SIZE, WINDOW_SIZE};
|
||||
use super::CAPTURE_AT_FRAME;
|
||||
|
||||
mod agent;
|
||||
mod download;
|
||||
@@ -157,19 +157,15 @@ impl App {
|
||||
tasks.push(iced::system::theme().map(Message::SystemTheme));
|
||||
}
|
||||
|
||||
// M104:助手栏的启动尾巴(窗口尺寸 adopt + 「拆出档直接落到独立页」)在 update/agent.rs。
|
||||
// **必须在 RefreshAll 之前**:那次 dispatch 会 `pump → auto_select`,把路由拉到实例详情,
|
||||
// 而 `sync_agent_route` 看到「不在 Agent 页却还是 Detached」就会把档位收回来——顺序反了
|
||||
// 就会出现「`ULL_AGENT_RAIL=detached` 启动后停在实例页」(r2 实测踩到)。
|
||||
self.boot_agent();
|
||||
|
||||
// 「重新扫描实例目录 + 全部页面快照」:真 host 在这里发首批事件,mock 在构造时已预置
|
||||
self.dispatch(AppCommand::RefreshAll);
|
||||
|
||||
// 窗口尺寸的**唯一真源**是 `boot.rs` 开窗时用的那一个(`ULL_WINDOW_SIZE` + 最小尺寸钳位)。
|
||||
// `App::with_presenter` 只认识常量 1180×760,所以这里 adopt 一次:不 adopt 的话,验收矩阵
|
||||
// 开 900 或 1520 的窗时页面还按 1180 排版(图上就是「窄窗里内容被裁掉」)。
|
||||
let (window_size, _source) = crate::renderer::acceptance::window::window_size(
|
||||
(WINDOW_SIZE.width, WINDOW_SIZE.height),
|
||||
(MIN_SIZE.width, MIN_SIZE.height),
|
||||
);
|
||||
self.width = window_size.0;
|
||||
self.height = window_size.1;
|
||||
|
||||
// 取证开关 `ULL_START_ROUTE`:截图/冒烟直接落到某一页(`cli.rs` 不在本 mission 的 scope,
|
||||
// 而「外观」分组只在设置页上,出矩阵必须能直达)。未知值忽略。
|
||||
if let Some(route) = env_start_route() {
|
||||
@@ -179,16 +175,6 @@ impl App {
|
||||
self.auto_selected = true;
|
||||
}
|
||||
|
||||
// M104:三档状态若从「拆出」开始(`ULL_AGENT_RAIL=detached` 或将来持久化的偏好),
|
||||
// 会话就在独立页里——直接落到那一页,别再被「自动选中第一个实例」拉回详情页。
|
||||
if self.agent.rail == crate::shell::agent::RailState::Detached
|
||||
&& self.state.route() != &Route::Agent
|
||||
{
|
||||
eprintln!("[agent] rail=detached → Route::Agent");
|
||||
self.state.navigate(Route::Agent);
|
||||
self.auto_selected = true;
|
||||
}
|
||||
|
||||
self.auto_select();
|
||||
self.view_dirty = true;
|
||||
self.refresh_view();
|
||||
|
||||
Reference in new issue
Block a user