MooTool next-compose:用 *ActionEnabled 纯函数驱动 IPv4/Long 转换钮状态(DIFF-662 切片解析)

发布时间:2026/10/16 1:41:19

MooTool next-compose:用 *ActionEnabled 纯函数驱动 IPv4/Long 转换钮状态(DIFF-662 切片解析) 桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载本文围绕 MooTool 仓库next-compose目录下的 DIFF-662 切片文档展开讲清 F11 网络/IP 工具中 IPv4↔Long 两个转换按钮的可点击状态是如何被NetWiringPresentation的两个纯函数ipv4ToLongActionEnabled/longToIpv4ActionEnabled派生出来的以及它们如何委托给NetEngine做校验、在NetScreen中完成接线、并被 desktopTest 单测覆盖。读完你能掌握这套“展示层纯函数 引擎委托校验”的按钮状态控制写法并能复现该切片的验证命令。切片定位与验证基线DIFF 系列文档是next-compose/docs/diff/下逐片记录的增量开发日志每片只聚焦一个最小变更面。DIFF-662 文档 原文极简但信息完整基线DIFF-661工作区即本切片建立在 DIFF-661 之后的工作树上后续切片 DIFF-663 又以 DIFF-662 为基线形成链式演进。范围F11 的 IPv4↔Long 转换钮ipv4ToLongActionEnabled/longToIpv4ActionEnabled委托NetEngine校验NetScreen接线。验证JDK 21 环境./gradlew :composeApp:desktopTest --offline --no-daemon ./scripts/verify-product-evidence-prep.sh其中--offline表示不访问网络解析依赖--no-daemon避免 Gradle 守护进程残留证据准备脚本对应仓库中的 verify-product-evidence-prep.sh。验收台账 acceptance.md 的 F11 行也明确把「IPv4/Long 转换ipv4ToLongActionEnabled/longToIpv4ActionEnabled」标注为引用 DIFF-662 的已接线能力说明该切片在 F11 工具左侧命令输出区 右侧功能区的网络/IP 面板中属于 IPv4/Long 转换小节的核心状态控制。NetWiringPresentation把按钮 enabled 派生成可单测的纯函数本切片新增的两个函数位于 NetWiringPresentation.ktfun ipv4ToLongActionEnabled(ipv4: String): Boolean runCatching { NetEngine.ipv4ToLong(ipv4.trim()) true }.getOrDefault(false) fun longToIpv4ActionEnabled(longText: String): Boolean runCatching { NetEngine.longToIpv4(longText.trim()) true }.getOrDefault(false)写法上有三个值得注意的点校验逻辑零重复。NetWiringPresentation本身不重新实现“什么算合法 IPv4 / 合法 Long”的判断而是直接调用NetEngine.ipv4ToLong/NetEngine.longToIpv4并捕获其抛出的NetConvertException转换成功返回true按钮可点抛异常返回false按钮置灰。这样 UI 的可用态与引擎的真实转换规则永远同源不会出现“按钮可点但点下去报错”的分裂状态。trim()先行。两个函数都先去除首尾空白再校验与同文件中portScanStart等入口对输入统一 trim 的处理风格一致见 NetWiringPresentation.kt。纯函数、无 Compose 依赖。NetWiringPresentation是一个object内部只放fun不含Composable因此可以被 desktopTest 直接调用断言这正是该切片的可测试性来源。同文件还定义了PortScanStart/HostCommandStart这类sealed interfaceL5-L13把“可启动/被拦截 错误码”建模为数据供 UI 分支渲染转换钮场景更简单只需一个Boolean。NetEngine 侧的转换规则与边界两个按钮最终委托到的引擎实现位于 NetEngine.ktfun ipv4ToLong(value: String): Long { val parts value.trim().split(.) if (parts.size ! 4 || parts.any { !it.matches(Regex(^\d{1,3}$)) || it.toInt() 255 }) { throw NetConvertException(Invalid IPv4 address) } return parts.fold(0L) { acc, part - acc * 256 part.toInt() } } fun longToIpv4(value: String): String { val number value.trim().toDoubleOrNull() ?: throw NetConvertException(Invalid IPv4 number) if (number % 1.0 ! 0.0 || number 0 || number 0xffffffffL.toDouble()) { throw NetConvertException(Invalid IPv4 number) } return longToIpv4(number.toLong()) } fun longToIpv4(value: Long): String { if (value 0 || value 0xffffffffL) throw NetConvertException(Invalid IPv4 number) return listOf(24, 16, 8, 0).joinToString(.) { shift - ((value shr shift) and 0xffL).toString() } }规则可以从源码直接读出IPv4 → Long必须恰好 4 段、每段 1~3 位纯数字且不超过 255按acc * 256 段值折叠成无符号 32 位整数。注意前导零是被接受的——测试断言了ipv4ToLong(127.0.0.01) 2130706433LNetEngineTest.kt因为正则^\d{1,3}$不禁止01。Long → IPv4字符串入口先toDoubleOrNull()再用number % 1.0 ! 0.0排除小数如1.5并用0..0xffffffffL限制在 32 位无符号区间Long 重载则按 24/16/8/0 位移取低 8 位拼成点分十进制。失败语义非法输入统一抛NetConvertExceptionNetEngine.kt它区别于命令类错误的NetException后者携带NetworkErrorCode让 UI 能对“转换失败”与“命令失败”分别给出提示。对应的失败边界用例集中在 NetEngineTest.kt256.0.0.1段越界、1.2.3/1.2.3.4.5段数错误、::1IPv6 字面量、127.0.0.空段应全部抛出NetConvertException反向则-1、4294967296上界 1、1.5小数均被拒绝同时0.0.0.0 ↔ 0、255.255.255.255 ↔ 4294967295两个端点可往返。NetScreen 接线按钮 enabled 绑定与点击后的完整副作用UI 侧接线在 NetScreen.kt 的Section(container.t(net.ipv4Long))内布局为「IPv4 输入框 → 两个转换按钮 → Long 输入框」Section(container.t(net.ipv4Long)) { LabeledField(IPv4, session.ipv4) { session.ipv4 it; persist() } Row(horizontalArrangement Arrangement.spacedBy(8.dp)) { MooButton( ${container.t(common.convert)} ↓, p5Toolbar true, enabled NetWiringPresentation.ipv4ToLongActionEnabled(session.ipv4), onClick { runCatching { NetEngine.ipv4ToLong(session.ipv4).toString() } .onSuccess { value - session.longValue value session.error container.history.save( ToolId.Net.id, NetHistoryMetadata.OP_IPV4_TO_LONG, value, session.ipv4, value, ) persist() } .onFailure { notifyNetFailure(container, session, convertMessage(container, it)) { persist() } } }) MooButton( ↑ ${container.t(common.convert)}, p5Toolbar true, enabled NetWiringPresentation.longToIpv4ActionEnabled(session.longValue), onClick { /* 对称longToIpv4 → session.ipv4历史操作 OP_LONG_TO_IPV4 */ }) } LabeledField(Long, session.longValue) { session.longValue it; persist() } }这条链路的完整行为是enabled 实时派生MooButton的enabled直接调用本切片新增的NetWiringPresentation.*ActionEnabled。由于session.ipv4/session.longValue是 Compose 可观察状态用户每次改输入框onChange触发persist()都会引发重组按钮置灰/点亮随之自动更新无需手动刷新。点击后写回对侧字段转换成功时把结果写入另一端session.longValue或session.ipv4并清空session.error。写入通用历史通过container.history.save(ToolId.Net.id, ...)以NetHistoryMetadata.OP_IPV4_TO_LONG/OP_LONG_TO_IPV4操作类型记录本次转换的输入与输出纳入 F11 工具的历史恢复体系。失败兜底虽然按钮已按纯函数置灰但点击与点击前的状态仍可能存在竞态例如用户在 IME 合成过程中状态未更新因此onClick内部仍保留runCatching失败时经notifyNetFailureconvertMessage给出真实失败原因而不是静默或伪造结果——这与 acceptance.md 对 F11「失败显示真原因」的总体要求一致。单测覆盖与回归验证针对本切片NetWiringPresentationTest.kt 新增了ipv4LongConvertActionEnabled用例覆盖按钮态的四个关键输入assertTrue(NetWiringPresentation.ipv4ToLongActionEnabled(127.0.0.1)) assertFalse(NetWiringPresentation.ipv4ToLongActionEnabled()) assertFalse(NetWiringPresentation.ipv4ToLongActionEnabled(256.0.0.1)) assertTrue(NetWiringPresentation.longToIpv4ActionEnabled(2130706433)) assertFalse(NetWiringPresentation.longToIpv4ActionEnabled()) assertFalse(NetWiringPresentation.longToIpv4ActionEnabled(4294967296))即合法地址/合法数值 → 可点空串、段越界256.0.0.1、超上界4294967296比 32 位无符号最大值大 1→ 置灰。与 NetEngineTest 的引擎级用例配合形成「引擎转换规则 展示层派生规则」双层验证。回归方式沿用原切片文档给出的两条命令JDK 21./gradlew :composeApp:desktopTest --offline --no-daemon ./scripts/verify-product-evidence-prep.sh从源码结构看*ActionEnabled这类命名与纯函数化接线在同仓库 DIFF-654 至 DIFF-669 的多个切片中反复出现如时间、加密、Cron、计算器等工具各有对应的*ActionEnabled切片可以推断这是next-compose在逐工具对齐 Electron 行为时统一采用的展示层状态控制模式把“按钮何时可点”的判断从Composable体内剥离到可单测的纯函数中并以对应工具引擎作为唯一校验来源。本文所讲的 F11 IPv4/Long 转换正是该模式在网络工具上的具体落地。赞分享桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载相关推荐openclaw-cn 浏览器自动化 CLI 完全指南clawdbot browser 的配置、标签页管理、快照操作与远程控制openclaw cn 浏览器自动化 CLI 完全指南clawdbot browser 的配置、标签页管理、快照操作与远程控制 clawdbot browse桌面应用开发工具cppcheck incompatibleFileOpen 检查详解同一文件被读写双流并发打开cppcheck incompatibleFileOpen 检查详解同一文件被读写双流并发打开 导读 本文深入讲解 Cppcheck 静态分析工具中的 inc桌面应用开发工具Zabbix 8.0 Nextcloud by HTTP 模板完全指南基于 OCS API 的无脚本监控实战Zabbix 8.0 Nextcloud by HTTP 模板完全指南基于 OCS API 的无脚本监控实战 导读 本文围绕 Zabbix 官方模板仓库中桌面应用开发工具上一篇如何快速掌握threejsfundamentals核心概念场景、相机与渲染器解析下一篇Gleam分布式执行系统简介与使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/16 1:41:19

WSL 安装/迁移/适配

windows配置 打开控制面板-程序和功能-启用或关闭Windows功能 适用于Linux的Windows子系统虚拟机平台 / Windows 虚拟机监控程序平台Hyper-VWindows Hypervisor Platform 有的都选上 点击立即重新启动,等待电脑重新启动完成 安装WSL(win11&#xff09…

2026/10/16 1:41:19

C++学习笔记@TheCherno

油管技术大神@TheCherno的C++系列课程,本博客将按照我自己每天看的量记录笔记,欢迎大家来一起监督学习,与君共勉。 写在最前面的一些提醒,本系列课程可能需要一些c的基础,这样看本笔记要能简单些。 2025/3/15 [8]C++变量 1. 2. [9]C++函数 1. 2. 2025/3/17 [10]C++的…

2026/10/16 1:36:18

ng-zorro Modal组件实战:从基础用法到性能优化的完整指南

ng-zorro的Modal组件,我用了一年多,从最开始只会打开关闭,到后来处理各种嵌套表单、异步提交、动态数据、组件通信的复杂场景,踩了不少坑,也攒了不少心得。这篇就把我在实际项目中操作Modal的细节经验完整梳理一遍&…

2026/10/16 6:46:35

《派出你的AI同事:WorkBuddy案例实战》034:产品手册 RAG 精准客服

《派出你的AI同事:WorkBuddy案例实战》034:产品手册 RAG 精准客服 📌 卷三 第四部分 记得住、学得会的 AI 同事:记忆与知识库 第10章 知识库与 RAG 实战 10.2 10.2 产品手册 RAG 精准客服 背景与痛点 客服团队最大的敌人不是“态度”,而是“信息跟不上产品”: 产品…

2026/10/16 6:46:35

C# WinForms集成OpenTK实现可交互3D柱状图控件实战

简介:一款基于C#与OpenTK的WinForm 3D图表控件完整工程包,面向需要为桌面程序增加立体数据可视化的.NET开发者。 该控件通过OpenGL绘图实现真正的三维展示,支持鼠标拖拽旋转查看、自定义图表颜色与文字颜色,适合金融、科研、工业…

2026/10/16 6:46:35

魔改Informer实现滚动长期预测:数据、模型、实验全流程

简介:一套面向时间序列长期预测与科研论文实验的Informer魔改方案,针对官方代码仅支持固定长度预测的局限,新增滚动长期预测功能:首次预测未来24个时间点后自动回填,再继续预测下一段24个值,全过程无需手动…

2026/10/16 6:46:35

《派出你的AI同事:WorkBuddy案例实战》049:BIM 与 GIS 文档与变更管理

《派出你的AI同事:WorkBuddy案例实战》049:BIM 与 GIS 文档与变更管理 📌 卷三 第七部分 行业案例集 第15章 工程与水利数字孪生实战 15.2 15.2 BIM 与 GIS 文档与变更管理 背景与痛点 BIM(建筑信息模型)和 GIS(地理信息系统)是工程数字孪生的两根主梁。一座大型工…

2026/10/16 6:41:34

上海松江别墅室内甲醛检测方案设计:方法学与布点参数解析

摘要:别墅类住宅因楼层多、房间功能复杂、定制木作用量大,其室内甲醛检测方案与普通住宅存在显著差异。本文从方法学选择、布点参数设计、CMA资质核验(含2026年"一单一库"新规下的报告出具规则)、典型误差来源四个维度&…

2026/10/16 5:33:43

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/16 4:03:48

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/16 0:01:11

Cephadm实战指南:Linux系统工程师的生产级Ceph集群部署与排障

简介:本资源是一份完整的Ceph分布式存储系统中文技术文档合集,面向Linux系统运维工程师、云平台架构师及存储方向开发者,帮助读者系统掌握Ceph集群的部署、配置与运维核心能力。文档覆盖对象存储(RGW)、块设备&#xf…

2026/10/16 0:01:11

ITK中SpatialObject几何体系解析:坐标系、变换与管道集成

1. 空间对象的定位:为什么 ITK 需要一套几何描述体系很多刚开始接触 ITK 的朋友,包括我自己,最初都是被它的图像滤波、配准、分割这些“正统”功能吸引进来的。等真正上手做点实际项目,比如把分割出来的器官边界做量化分析、给血管…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑