本文记录 XDial 的产品表面、状态含义和交互边界;网络与事务契约见 ARCHITECTURE.md。macOS 以菜单栏为入口;iOS / tvOS 可以采用平台布局, 但共享领域词汇、状态含义与直接操作逻辑。
XDial 是常驻菜单栏、按场景切换网络裁决的工具。Popover 优先呈现当前场景、连接状态、 时长与速率;场景本身就是操作入口。步骤、线路事实和配置字段按需展开,避免仪表盘式的 信息堆叠。
| 界面词汇 | 领域对象 | 含义 |
|---|---|---|
| 线路 | Line |
可建立、复用并承载流量的出口 |
| 线路组 | selector / urltest Line |
引用共享线路或组,手动选择或自动测速选线;独立配置类别 |
| 规则 | RuleSet |
一组匹配条件 |
| 场景 | Scenario |
规则与线路的连接点,也是用户选择和连接的入口 |
| 订阅 | Subscription |
产生或更新线路等资源的数据源 |
| 直连 | Direct |
不经过代理线路的明确出口 |
“场景”不用“模式”“方案”或“策略”替代。“反向”只表达 RuleSet 的匹配属性;SSID 只表达 Scenario 的激活条件,两者互不关联。用户输入的名称、SSID、URL、地址与原始错误保持原样。
Profile 下依次为「线路 / 线路组 / 规则 / 场景」四个并列类别。创建规则先命名, 再添加域名、IP、应用或远程规则集;内容默认任一命中,详情在同一页面展开。机场导入 先按原策略名生成完整规则,同名策略的匹配内容归为一个规则,再简化出口关系。 业务手动策略组若只是重复引用同一个节点池、直连及同类选择器,其独立选择由场景绑定承接, 不另建同名线路组;不因最终出口相同而合并 AI、Netflix 等规则。真正共享的节点池、测速组、 成员范围不同的组,以及仍被其他组或资源下载引用的组保留。Naixi 这类配置的导入结果为一个 Proxies 线路组,多个业务规则默认绑定 Proxies 或直连,FINAL 对应场景默认出口。 默认场景还原原配置,新场景共用资源并保存自己的分流安排。 原始条件存在交错时,默认场景显示「沿用原配置的匹配顺序」;用户可以显式改用规则 列表顺序再拖动,界面说明这会影响重叠条件。迁移已有场景时,部分引用必须明确显示, 不得因规则归类扩大匹配范围;用户可选择「使用完整规则」。
| 表面 | 内容与操作 | 边界 |
|---|---|---|
| 菜单栏图标 | 常驻入口、最小连接状态、错误或更新提示 | 不展开配置清单 |
| Popover | 场景连接与切换、时长、速率、事务步骤、线路与规则事实 | 不编辑 Line / RuleSet / Scenario,不设永久操作栏 |
| 配置与通用窗口 | 配置窗口编辑 Profile 及其资源;通用窗口管理应用偏好 | 配置是否启用不等于正在运行;打开或展开设置不发起网络动作 |
| 安装与卸载窗口 | 平台事务、系统批准、卸载选项、进度与错误 | 安装不创建网络配置或接管流量 |
| 更新窗口 | 版本、更新说明、下载、验证与交接 | 不复制平台组件安装任务;打开窗口或下载不停止当前连接 |
主实例以 LSUIElement 菜单栏应用常驻。设置可见或最小化时,独立签名的轻量载体提供 Dock
和 App Switcher 入口;它不加载 AppState、网络控制面或第二个菜单栏。设置关闭后载体退出,
主实例继续运行;安装与卸载窗口由主实例置顶承载。载体与宿主均不进入 Dock 最近应用,
不改写用户 Dock 偏好。载体对外显示 XDial 与包内固定图标,不暴露内部 Target 名,也不在退出时
切换图标。对应生命周期见 SettingsDockProxyCoordinator.swift。
窗口只保留一份标题。设置与退出入口固定在 Popover 右上角,⌘, 在 Popover 与各窗口中 都打开设置;安装状态、检查更新等低频操作位于其上下文菜单,不占主界面空间。
产品使用低彩度石板蓝灰、钢灰、松针、琥珀和氧化红,配冷灰白或石墨灰表面。颜色按含义 使用,同一状态在各窗口保持一致:
| 语义色 | 含义 |
|---|---|
| Accent / Progress | 主要操作、进行中、一般信息 |
| Selection | 已选中、当前 Tab、反向开启;不表示连接成功 |
| Success | 已连接、已提交、成功 |
| Warning | 等待外部批准、待应用配置、能力尚未开启 |
| Danger | 失败、破坏性操作 |
| ProxyOnly(暮紫) | 仅 SOCKS5 的已连接:XDial 在运行,但系统流量未经过它 |
颜色及明暗、高对比变体集中在 XDialPalette.swift 与 XDialBrandPalette.swift。画布、卡片与边界保持 可见层次;实色用于细环、小徽标和图标,状态背景只用低透明度填充,不把整张卡片涂成状态色。 状态同时通过文字、图标或轮廓表达,系统焦点环保持可见。
布局采用外部留白充分、内部信息紧凑的层次,避免重复标题与层层边框。设置中的布尔项使用 紧凑开关,图形缩小不压缩文字、命中区或辅助功能。状态胶囊只承载短状态、速率、步骤及 紧凑操作,不包裹普通段落。Popover 与设置的尺寸、间距和字体数值见 MainPopover.swift、 SettingsView.swift;设置窗口尺寸与顶栏行为见 XDialApp.swift。
时长、速率、IP 与计数使用等宽数字;速率值槽固定,数值或单位更新不移动布局。普通名称 尾部截断、路径与 URL 优先中间截断,同时保留完整可访问值;错误完整换行、可选择与复制。 界面支持中英文,文案集中在 Localizable.xcstrings, 数字、日期、单位与复数遵循当前语言和 locale。大文字和长文案通过换行、扩展或滚动保持 可读,不靠缩小文字或裁掉关键内容适配。
App、Dock 和移动端图标共享 RotaryDial.swift 的拨号盘 几何与品牌色。App 图标不表达连接状态;设置载体的齿轮徽标与阴影位于底块内。macOS 保留 圆角底块留白,移动端背景满幅不透明并由系统裁切。
菜单栏使用电话拨号盘:转盘、六个指孔与指停器。其状态由 MenuBarStatusIcon.swift 表达:
| 状态 | 字形 |
|---|---|
| 未连接 | 降低整体墨色的空心盘与六个实心指孔 |
| 连接中 | 完整外环,指孔按拨号顺序脉动;Reduce Motion 下静止 |
| 已连接 | 实心盘,指孔与指停器镂空 |
| 错误 | 独立的空心环与叹号,不与连接底图叠加 |
| 有更新 | 当前连接底图右上角的 Danger 圆点 |
| 仅 SOCKS5 已连接 | 已连接的实心盘右下咬口,缺口处一枚实心端口点 |
错误优先于更新圆点。普通字形由系统 template 着色;更新圆点需要非 template 图像,底图墨色 跟随真实菜单栏明暗,包括壁纸造成的变化,不跟随 XDial 自身的外观覆盖。
从上到下是标题、场景、必要的状态或进度、速率与详情。标题包含 XDial、小状态点与连接
时长;发现更新时增加紧凑的候选发布标签入口(beta 显示 vX.Y.Z,后接与更新窗口同样式的 beta.N 标记),右上角设置齿轮与退出按钮始终可见。时长不在其他区域重复。
场景每行最多四个,每行居中。超过四个时先取最少行数,再取能保持行数的最少列数并均衡
分行,例如五个排为 3 + 2,六个为 3 + 3,九个为 3 + 3 + 3。场景数量变化采用短暂
尺寸过渡;不使用横向滚动或 Cover Flow。Popover 高度受屏幕可用区域约束,内容过多时整体
纵向滚动,优先保留标题与主操作。
场景圆球是连接、取消、断开、切换和重试的唯一主操作,不另设对应文字按钮。鼠标、键盘与 VoiceOver 执行相同动作;悬停只增加下一步动作的小徽标,不改变布局。
| 当前状态 | 表达 | 点击当前场景 | 点击其他场景 |
|---|---|---|---|
| 未连接 | 中性轮廓;选中只表示选择 | 连接 | 选择并连接 |
| 连接中 | 中性虚线底环与实际 Progress | 取消本次连接 | 改为目标场景 |
| 已连接 | Success 闭环与勾;仅 SOCKS5 为 ProxyOnly 虚线环与插头 | 断开 | Switch |
| 失败 | Danger 断环与叹号 | 重试 | 改为目标场景 |
Switch 准备期间,旧场景仍以 Success 和原连接时长表示当前承载连接,目标场景显示 Progress。 候选失败只把目标场景标为失败,并说明“仍在使用〈当前场景〉”;只有旧运行 generation 也失效, 才把当前连接转为失败。复用 Line 是底层事务语义,不在 UI 增加技术说明。
关闭 Switch 失败提示代表确认该候选 transaction 的错误,Popover 错误条与菜单栏叹号同步
消失,不影响当前连接。确认状态跨 Popover 重建保留;新的候选失败重新提示。
reconnecting、disconnecting、rollingBack、rolledBack、disabled 与 configDirty
沿用同一套进行中、中性、Warning 和 Danger 语义,并用文字或图标区分具体状态。
忙碌时显示已完成数与总数,点击展开真实事务步骤。首次连接消费当前 ConnectionReport;
Switch 使用独立候选报告,不覆盖仍在承载流量的 committed 报告。步骤胶囊按内容排布、自动
换行,过长或失败的步骤完整展示;等待、执行、成功、失败与回滚均有文字和图标。
连接步骤与连接后的 Line / RuleSet 详情共用一个展开状态和 disclosure 图标。阶段或事务 更新不重置用户选择;首次详情默认展开,之后沿用选择。展开箭头只控制内容,不收缩外框。 上传与下载合为居中紧凑胶囊,保留一位小数并自动选择速率单位,右侧只放详情箭头。
已连接详情分别展示本次事务实际使用的 Line 及观察地址、当前 Scenario 完整的
RuleSet → Line 清单。Line 名称与地址分列,规则映射优先两列并允许换行;没有本次事务
事实时不伪造“运行中”,没有错误时不保留空的错误区。
出口地址是当前事务经该 Line 查询到的观察,不代表所有目标共用唯一出口。 IPv4 使用 Cloudflare 与腾讯:优先上次成功源,500 ms 未成功则补发另一源,明确失败立即补发; 首个有效结果获胜并取消其余请求。IPv6 暂保留 Cloudflare,腾讯 IPv6 未验证。 偏好仅在 Provider 进程内保留,按 Line / 地址族隔离,不跨事务复用 IP。 所有线路的地址查询合计最多两个在途请求;每源每地址族每秒最多一次,连续三次失败后 暂停 30 秒,继续失败逐次翻倍、最长 5 分钟。取消和限流拒绝不增加失败次数。 成功后不轮询;保留最多四轮的有限重试,失败仅表示暂未获取地址,不改变线路就绪状态。
失败信息包含三种独立内容:结构化运行事实、用户可读结论、完整原始错误。摘要由 error code、 task/resource 与 layer 生成,能归因到任务时带任务名;不靠错误字符串或日志猜类别。 系统接管是否提交、回滚是否完成、原网络是否可用分别表达,回滚结果不覆盖最初故障。
配置待应用由 §5.6 的有效运行指纹决定。场景区之后显示 Warning 状态轨: “修改已保存,当前连接尚未应用”,不改变当前场景的 Success 闭环,也不藏进详情。 整条状态轨执行“应用并重连”,触发后原位进入进度状态,不另加大型操作按钮。 状态优先级为:完整失败信息 > 连接或切换进度 > 待应用配置 > 普通已连接详情。
自动重连因网络相关失败用完预算后停泊:场景区之后显示 Warning 状态轨“自动重连已暂停, 网络变化时会再试”,右侧小按钮“立即重试”以新预算重新开始自动重连;完整失败信息与回滚 事实仍在详情中,场景圆球仍是失败表达,点击它是一次用户连接。网络变化、唤醒或慢尾尝试 开始时原位进入进度状态;凭据、登录或配置等终止错误不停泊,也不显示这条状态轨。
位置权限首次检查完成前不判为缺失,不显示权限 Warning 或自动打开安装窗口。
Profile 存在非空 match_ssids 且确认位置权限未就绪时,场景区之后持续显示不可关闭的 Warning:
“Wi-Fi 自动切换不可用”,说明无法读取当前 Wi-Fi、场景不会自动切换。未决定时提供“开启位置
权限”;已拒绝或受限时提供“打开定位服务设置”,不反复请求。
系统授权只由前台可见界面的明确点击触发。权限缺失只停用 SSID 自动匹配,手动连接、断开 与切换仍可用,当前连接状态不变。权限恢复后重新读取 Wi-Fi、刷新匹配并移除 Warning,无需重启。
620 × 580 的配置窗口提供线路 / 规则 / 线路组 / 场景 / 通用五页。
顶栏分成 [Profile ▾ | 线路 规则] [线路组 场景] [通用] 三块,块间距为 10 pt,整体按整个标题栏宽度居中。
标题区域隐藏系统标题、保留原生窗口控制与拖动;内容区域的控件不承担窗口拖动。
Profile 是线路与规则的来源边界,下拉始终放在左侧资源分组内,不另占内容行。选择来源时按白名单保留当前分类:
当前页为「线路」或「规则」时保持该页,其他页面回到默认的「线路」。新建、复制、导入或删除当前 Profile 后也遵循此规则。
删除其他 Profile 保留当前页面。管理弹窗由设置窗口承载,复制或删除成功后关闭相关管理弹窗。
这些操作不连接、不改变全局线路组或场景的范围。下拉每行可进入管理界面,修改名称与订阅设置、
更新订阅、查看兼容提示、创建资源副本、导出和删除;引用中的来源不允许直接删除。
线路组与场景可跨来源引用,选择器显示来源名称以区分同名对象。菜单栏直接展示全局场景。
订阅首次导入创建全局线路组与场景,单个场景采用订阅名,多个采用“订阅名 · 场景名”。 普通更新只替换源线路、规则,并同步明确跟随的源组成员;保持场景全部设置、组名称、 选线、测速参数和额外手动成员。关闭跟随后保留静态成员;新增源组与场景由管理页显式导入。 “从订阅重新生成”需确认,会覆盖该来源已有组和场景的设置,保留已有 SSID 与独立手动对象。 引用失效、固定成员被删除、循环或自动组包含直连等不兼容变化使更新整体失败并保留旧配置。
所有支持新版配置格式的版本共用一份 Profile 库。首次启动仅在新库不存在时自动转换旧配置, 作为默认 Profile;原文件保留,新版修改不回写。已有旧 Next 配置库迁入共享目录时保留全部 Profile。 界面不提供“导入旧版配置”操作。卸载不勾选删除数据时保留配置;勾选后清理共享库、旧配置和 保存的密码。其他版本仍在运行时提示先退出,不能让旧进程将数据重新写回。
“通用”嵌入同一窗口,左侧按启动与连接、外观与语言、系统与权限、关于与更新分类, 右侧以紧凑表单呈现对应功能。五页切换保留来源选择和编辑位置,不创建另一扇通用窗口。 关闭设置窗口不影响菜单栏和连接。
外观单独持久化,不进入 Profile、不产生待重连提示或网络动作;跟随系统时清除窗口外观覆盖。
“启动与连接”中的连接方式分为“接管系统”(默认)与“仅 SOCKS5”,是全局偏好,不随场景变化。
SOCKS5 端口默认 5181,只监听 127.0.0.1。接管系统时可另开本机 SOCKS5,已连接时开关与端口
立即生效,失败在原处说明并提供重试,不产生待应用提示。仅 SOCKS5 的说明以 ProxyOnly 呈现;
已连接时切换连接方式或修改仅 SOCKS5 的端口,原处与 Popover 都显示待应用状态,“应用并重连”
完整重连;当前连接在此之前保持原方式。
仅 SOCKS5 连接期间,ProxyOnly 替代 Success 表达“已连接”:标题状态与时长、“仅 SOCKS5”胶囊(点击打开
通用 › 启动与连接)、
场景圆球的虚线环与插头、映射中的线路名均使用它。场景区下方常驻不可关闭的提示:“系统流量
没有经过 XDial”,并给出 127.0.0.1:<port> 与复制按钮。菜单栏使用独立字形,不靠颜色区分。
通用版本来自运行中 App 的 bundle,以发布标签显示(已装 beta 为 vX.Y.Z-beta.N),缺失值显示 ?。
“检查更新”只打开更新窗口;候选版本、说明、下载进度与更新操作均留在 §6.2。其下的“接收 beta
版本”默认关闭,每次切换都立即检查一次(已下载待安装时也检查),检查、下载、验证或交接期间
禁用;说明写明关闭不降级:已装的 beta 继续接收这条线的修复,正式版追上后自动回到正式版。
Debug 只说明从源码重新构建升级,不显示检查更新入口和 beta 开关。
Line、Subscription、RuleSet、Scenario 默认折叠,短按标题展开。标题依次表达展开状态、 运行或活动状态、名称、摘要、类型或紧凑操作、启用、删除;删除固定最右侧。启用不是运行, 活动 Scenario 使用 Selection 的勾与细强调条,Success 只表示当前事务运行成功。 行内控件消费自己的点击,不带动展开或外层拖动。
顶层排序通过按住整条卡片约 300 ms 起拖,不增加永久把手或排序说明;展开的 Scenario
不作为顶层拖动源。其内部 binding 只从行首固定的小型系统把手起拖,悬停为手形指针;名称、
行本体、目标 Picker 与删除按钮不参与起拖。各类顶层对象只在同类内排序,binding 只在当前
Scenario 内排序。
拖动时卡片或整行跟随指针,列表仅留下等高透明空位;无插入线、提示文案、额外边框或换位 动画,松手立即显示最终位置。binding 只在成功落下并改变顺序时保存一次;取消不保存排序。 拖动结束不附带展开、开关、删除或激活,取消后也不残留阻碍窗口操作的拖动状态。键盘与 VoiceOver 提供不占视觉空间的“上移 / 下移”动作。
线路组展开后只展示已有成员,以「添加线路或组」搜索并逐项加入共享引用。成员区最多 显示七行,更多成员在区内滚动;移除只解除引用。新建组从空成员开始。测速组由核心自动 选用成员,配置页只编辑成员及测速参数;手动选择组另保留选用成员。嵌套组禁止循环引用, 订阅提供的成员只读。
“反向”覆盖 URL、手动与应用规则,入口位于折叠标题行。开启以勾、Selection 填充与强轮廓 共同表达,关闭为反向图标与中性轮廓,不在详情重复解释行。URL 后紧跟获取 Line 选择器, 默认 Direct;格式等低频字段另行排列。域名、CIDR 和程序匹配条件分组清楚。
场景图标与活动状态是独立信息:折叠标题在活动状态之后、名称之前保留图标槽;展开后的 名称行右侧提供图标选择器,点击才显示限宽六列网格,不展示 SF Symbol 技术名。
配置保存稳定语义 Key,各平台映射为系统图标。nil 表示自动:先匹配场景名称,无结果再
匹配已保存 SSID,不读取当前 Wi-Fi、Line、RuleSet 或出口反推图标。手动选择永久优先;未知
手动 Key 保持原值并显示网格 fallback,不转回自动。选择器首项“自动匹配”预览当前结果,
手选立即保存并关闭。连接状态只改变环、徽标与颜色,不替换主图标。图标规则集中在
ScenarioIconCatalog.swift。
场景名称、规则摘要与全部已绑定 SSID 保持在同一折叠标题行,每个 SSID 为独立胶囊。空间 不足时先压缩宽胶囊,至少保留约两个中文字符宽度并从尾部省略;完整值通过 help 和辅助功能 提供。胶囊达到最小宽度后裁切末尾内容,不挤压名称、状态与右侧控件。
展开后展示当前 Wi-Fi、绑定列表、添加入口与完整 RuleSet → Line 顺序。一个 SSID 只属于
一个 Scenario,冲突在输入旁指出现有归属。SSID 只选择场景,不表达网络信任或流量规则。
启动、后台恢复与初始化仅读取权限状态;明确点击“读取当前 Wi-Fi”或权限入口才请求系统
授权,拒绝或受限后改为系统设置入口。
文本输入在输入框中保留草稿,回车、失焦、离开页面或关闭窗口时提交保存;多行输入的回车仍为换行。 开关、选择和其他明确操作立即保存。大型规则的匹配内容每页显示 20 项,搜索覆盖全部内容。 当前连接继续使用其已提交配置。待应用状态只比较已保存配置与当前事务的 有效运行指纹:当前 Scenario 的有效 binding 顺序与默认出口、实际使用的 Line / RuleSet / Subscription,以及 URL RuleSet 获取 Line 等参与生成的内容属于比较范围。
未使用对象、顶层视觉排序、名称、图标、SSID、验证标记、订阅更新时间、语言、登录启动、 自动连接和接管系统时的附加 SOCKS5 偏好不触发待应用提示;连接方式与仅 SOCKS5 的端口 不同于当前连接时触发。失效配置若改变指纹仍提示,由重新规划给出具体错误。 指纹由 Go 与 ConnectionPlan 同源生成并记录在 ConnectionReport;Swift 只比较不透明结果。
三个配置 Tab 共用 Tab 行下方的轻量 Warning 状态轨,文案与 Popover 一致,提供“应用并重连”。 用户明确重连或切换才应用配置编辑;展开、切页和排序自身不发起网络请求。
安装和卸载共享一个窗口与紧凑页签,通用页仅保留入口。窗口使用一个状态图标、一个标题和 一句说明,任务按 InstallationReport 顺序展示名称、状态、详情与必要操作。安装与卸载事务 互斥,允许查看另一页但不并发执行;错误在原窗口完整展示并提供适用的重试入口。
安装页明确说明不创建网络配置或接管流量。卸载页说明先断开并移除系统接管,集中选择是否 删除线路、规则、场景与钥匙串密码,执行前二次确认。卸载进行中不能重复触发,也不绑定 Return。安装就绪后的“完成”为默认动作,Return 与 Escape 均关闭就绪窗口。
位置权限独立于平台 InstallationReport,不成为平台失败或手动连接门禁。存在非空
match_ssids 时,安装任务后显示“开启 Wi-Fi 自动切换”,说明 macOS 需要位置权限才能
提供 Wi-Fi 名称,XDial 只用它匹配场景;没有绑定则不显示该步骤。
未决定时,“继续”只在窗口可见、应用前台且用户点击后请求授权;拒绝或受限时打开定位服务 设置。平台成功但权限未就绪时,分别表达“平台安装完成”与“Wi-Fi 自动切换尚未开启”,用户 仍可完成安装并手动连接。权限恢复立即更新步骤与运行期匹配,不要求重启。
更新窗口独立于安装/卸载页签,顶部仅展示当前与候选的发布标签和一个状态图标,beta 候选 另带 Beta 标记;同号的 beta 与正式版靠标签区分,不显示成“v0.10.0 → v0.10.0”。更新说明可 滚动和选择,并与候选版本来自同一份有效清单。缺少说明的清单无效,不生成替代说明。
状态为检查中、已是最新、暂无可用更新、等待正式版、可下载、下载中、验证中、可以安装、 正在交接、失败。“等待正式版”只出现在已装 beta 且未开启 beta 时,此时只接收本线修复。界面只 消费更新器结构化状态:后台检查失败不弹窗,显式检查失败在窗口中显示。失败或限流不刷新最近 成功检查时间,也不冒充“已是最新”;候选构建号不高于当前时显示为失败。stable 已给出结论而 beta 清单读取失败时,只在状态下方作一行次要提示;已装 beta 而 stable 没有更高版本时,beta 清单失败即无法检查。已有候选可保留说明,但下载和安装前重新确认候选所在的清单。
“下载更新”只下载、解压与验证,当前连接继续运行;验证成功后才出现“安装并重新启动”, 它是唯一替换入口,并说明会短暂断开连接。更新开始时存在 committed Scenario,新 App 在 平台安装就绪后恢复它;原本断开则保持断开,不改动永久自动连接偏好。平台组件继续由既有 安装事务处理,更新窗口不复制 helper 或 System Extension 的任务列表。
下载仅使用一条进度;长度未知时使用不定进度,验证和交接不伪造百分比。失败保留当前安装 版本与重试入口,签名、版本、归档结构或替换失败完整展示,没有跳过验证或“仍然安装”。 菜单栏圆点、Popover 版本胶囊、上下文菜单与更新窗口消费同一个 candidate,清除或安装后 同步消失。
Popover 的方向键移动场景焦点,Space / Return 执行圆球当前动作,Escape 关闭,Command-, 打开设置,Tab 进入进度和详情。设置的 Tab / Shift-Tab 遍历控件,方向键切换页签或展开状态; Command-W 与 Escape 遵循窗口或 Sheet 语义,文本编辑的 Return 提交、Escape 取消未提交输入。
焦点顺序与视觉顺序一致,状态刷新、自动保存与排序不夺取焦点。场景圆球读出场景名、状态、 当前动作与连接进度;折叠卡片暴露展开状态;binding 把手读出规则名与位置。纯图标操作具有 名称,有状态的控件提供对应值;悬停不是唯一入口,也不触发场景或焦点变化。
滚动保持系统行为,命中区连续且不因悬停改变尺寸。动效仅解释状态变化,Reduce Motion 下 保留立即可读的结果;不以持续弹跳、发光或闪烁吸引注意。
线路组使用一个成员列表:首行“自动选择”,下面直接选择某条线路或子组;不再将手动组和 测速组作为两个创建入口。自动选择映射为 sing-box URLTest,固定成员映射为 Selector; 修改保存到 Profile,按既有配置事务应用,编辑期间不自动重启连接。
组头收纳名称、数量、折叠摘要和设置;展开后提供搜索、整组测速、多选添加、成员排序和 移除。名称及测速参数在设置中编辑,订阅组的来源成员保持只读;选线覆盖在刷新后保留, 若所选成员被源移除则拒绝更新并保留旧配置。自动选择暂不接纳含直连的组,沿用现有 DNS 所有权校验,不悄悄跳过成员。
线路列表、组成员、添加面板、场景/规则出口选择及菜单栏线路信息复用同一延迟组件。 显示毫秒、未测速、需连接、测速中或失败,悬停查看时间;单条测速放在延迟旁,批量测速放在列表工具栏。 行内刷新只测这一项当前使用的具体出口;组尚无原生优选结果时,通过“整组测速”获取初次结果, 不把行内刷新隐式展开成整组。组工具栏的“整组测速”始终覆盖全组成员,列表工具栏的“测当前列表” 只覆盖筛选结果;数量为成员去重后可测的线路数。每个按钮持有自己的任务,停止只取消本次请求; 共享探测若仍被另一任务使用则继续。共享成绩可以同步更新多个引用,但未发起测试的其他组不显示为测速中。 任务归属及开始时的数量保存在共享测速状态中,以 Profile 和稳定操作入口识别。切换 tab、折叠组或关闭再打开选择器不会丢失停止入口;切回后恢复原任务,期间完成或停止则显示可开始。筛选条件变化不扩大正在执行的范围,也不会恢复已经停止的任务。
菜单栏每条线路只占一行:名称、地址、毫秒数和刷新按钮;IP 不换行,长 IPv6 在行内省略中间部分, 点击地址查看完整值、切换地址族或复制。分流映射位于单独的折叠区域,展开后每条映射也只占一行。
自动组继续由 sing-box 原生测试与择优;手动测试只测量,不修改固定选择。
已连接的自动选线结果来自当前已提交事务;手动测速写入原生历史后立即由 sing-box 重新优选,失败清除旧成绩,固定选线不变。普通代理的显式手动测速不要求先连接场景,使用无系统
Ingress 的独立会话。VPN/Tailscale 仍只使用已连接能力。独立结果按 Profile 和完整线路配置
隔离,不持久化;改动凭据或删除资源会废弃旧结果。批量支持停止,排队、测速中、失败与超时
分别呈现;不存在结果时不显示 0 ms。未连接的自动组明确显示“连接后自动测速”,手动测完后以真实成绩交给无流量、无定时器的原生组计算“本次优选”;它不持久化、不等于“当前使用”。组内手动测速复用该自动组的 URL,留空及单独线路测速使用 https://www.gstatic.com/generate_204。
当前活动场景引用的出口缺少测速成绩时,后台补测一次;固定组只补测当前选中的成员, 已提交的自动组沿用 sing-box 原生周期。独立测量仍最多并发 3 条,不启动 VPN/Tailscale; 这些线路显示“需连接”,取得本次连接的线路能力后再补测。重复场景绑定复用同一成绩, 失败或停止后不循环自动重试;配置或连接事务变化后重新判断。单独浏览线路列表不会触发 整份配置测速,无关线路仍可手动测速。