feat(app-iced): 单行输入框透出 on_submit,回车接上存档改名与强调色提交
债务台账 P18(M250 + M247 的共同缺口):iced 0.14 的 text_input 有 on_submit、 没有 on_unfocus(builder 逐条核过:on_input/on_input_maybe/on_submit/on_submit_maybe/ on_paste/on_paste_maybe,on_unfocus 零命中),而本仓的 text_field 只透出 on_input ⇒ 行内重命名只能点按钮、强调色拿不到「用户确认」这一下。 - field.rs:Field 变 `Field<'a, M>`(M 只被新加的 on_submit 用到,调用点的类型由 text_field 的 on_input 一并推出,一行都不用改),回车消息唯一从 submit_message() 取,`on_submit_maybe(None)` 是默认档 ⇒ 既有调用点逐位不变;禁用态与 on_input 同一 条规矩被摘掉。 - 存档改名:回车与「改名」按钮共用 commit_rename() 一个消息产地,空名/原名不变/ 非法字符那几道校验因此对回车同样成立。 - 强调色:回车发 Change::AccentCommit(不是又一次 Accent(原文))⇒ 立即 commit(), 把「打了一半就放着」的 #12 亮成红框 + 错行;逐键不报短错的规矩不变,落盘仍取 上一次合法值。 - 判据:submit_is_opt_in(未接就是 None)、text_field_forwards_the_submit_callback、 submit_is_wired_only_at_the_two_call_sites(白名单扫源码)、 enter_takes_the_same_message_as_the_rename_button、the_rename_field_wires_enter、 the_accent_field_wires_enter_to_commit、enter_commits_a_half_typed_value_and_ persists_only_legal_ones。真键盘回车量不到(Element 无内省、造不出 iced::Renderer 的测试替身),报告里单列。
This commit is contained in:
1 parent
026b9f6e94
commit
f7cfc8ded6
13 files changed
+384
-22
No files matched your search
@@ -51,7 +51,10 @@ pub(super) fn push<'a>(
|
||||
// 受控输入框 + 失败态:`Field::error()` 让框本身变成错误色,错行再补「错在哪」。
|
||||
let mut field = Field::new(accent.text())
|
||||
.label(t(Key::SettingsAppearanceAccent, lang))
|
||||
.placeholder("#RRGGBB");
|
||||
.placeholder("#RRGGBB")
|
||||
// P18:回车 = 立即提交(把「打了一半就放着」的 `#12` 亮成红框 + 错行)。
|
||||
// **不是**逐键报错:敲字那条路(`Change::Accent`)照旧只在「不可能再变合法」时才亮红。
|
||||
.on_submit(accent_commit);
|
||||
if accent.error().is_some() {
|
||||
field = field.error();
|
||||
}
|
||||
@@ -81,6 +84,15 @@ pub(super) fn push<'a>(
|
||||
));
|
||||
}
|
||||
|
||||
/// 回车那一下要发的那条消息——**唯一产地**(M252 / P18)。
|
||||
///
|
||||
/// 抽成函数是为了让「回车 = 提交」这件事在源码里只有一个写法:`section/accent.rs` 把它交给
|
||||
/// `Field::on_submit`,测试按它钉住「回车走的是 `AccentCommit` 而不是又一条 `Accent(原文)`」
|
||||
/// (后者是**逐键**路径,会把已经亮出来的错重新吞回去)。
|
||||
fn accent_commit() -> Message {
|
||||
Message::Appearance(Change::AccentCommit)
|
||||
}
|
||||
|
||||
/// 「预设」两行:先「标签 + 出厂」,再一排 8 颗色块。
|
||||
///
|
||||
/// 为什么分两行:一行放 9 个控件在设置卡片的正文宽度里会被挤成「7 + 1」折行,最后一颗色块
|
||||
@@ -217,6 +229,39 @@ fn visible(ch: char) -> String {
|
||||
mod tests {
|
||||
use super::visible;
|
||||
|
||||
/// 本文件源码(源码结构断言用,与 `pages/layout/source.rs` 同一条纪律)。
|
||||
const SOURCE: &str = include_str!("accent.rs");
|
||||
|
||||
/// **M252 / P18 回车接线的两条断言**:输入框接了 `on_submit`,且接的是「提交」那条消息。
|
||||
///
|
||||
/// iced 的 `Element` 没有内省接口(见 `pages::layout::source` 的模块文档),所以「回车真的
|
||||
/// 按下去」在这里量不到——能钉住的是**它接的是哪条消息**:
|
||||
///
|
||||
/// - 抓得住:`.on_submit(..)` 被删掉(T27 反例);接成 `Change::Accent(原文)`(那是**逐键**
|
||||
/// 路径,`retry(false)` 会把已经亮起来的错吞回去,等于回车把错误擦掉);接成别的控件消息。
|
||||
/// - 抓不住:按键真的到达控件(iced 的 `Widget::update`)、以及红框/错行画没画(出图负责)。
|
||||
#[test]
|
||||
fn the_accent_field_wires_enter_to_commit() {
|
||||
let body = crate::pages::layout::source::function_body(SOURCE, "fn push");
|
||||
assert!(
|
||||
body.contains(".on_submit("),
|
||||
"强调色输入框没接回车(去掉接线这条必须红),实际函数体:\n{body}"
|
||||
);
|
||||
assert!(
|
||||
body.contains("accent_commit"),
|
||||
"回车必须接 `accent_commit`(唯一产地),实际函数体:\n{body}"
|
||||
);
|
||||
// 那条产地发的到底是什么:`Message` 没有 `PartialEq`,比 `Debug` 文本(变体名 + 字段)。
|
||||
assert_eq!(
|
||||
format!("{:?}", super::accent_commit()),
|
||||
format!(
|
||||
"{:?}",
|
||||
crate::pages::Message::Appearance(super::Change::AccentCommit)
|
||||
),
|
||||
"回车那条消息必须是 `AccentCommit`(提交),不是 `Accent(原文)`(敲字)"
|
||||
);
|
||||
}
|
||||
|
||||
/// 错行里的字符必须**看得见**:不可见字符写成 `U+XXXX`,可见字符原样(r1 小事 2)。
|
||||
///
|
||||
/// 抓得住:把 `visible` 改回 `ch.to_string()`——`U+00A0` / `U+200B` 那两条立刻红(错行会变成
|
||||
|
||||
Reference in new issue
Block a user