diff --git a/ShadowsocksX-NG2/App/Localizable.xcstrings b/ShadowsocksX-NG2/App/Localizable.xcstrings index 264a32ae..2923510d 100644 --- a/ShadowsocksX-NG2/App/Localizable.xcstrings +++ b/ShadowsocksX-NG2/App/Localizable.xcstrings @@ -275,50 +275,6 @@ } } } - }, - "在根目录新建服务器": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "New Server at Root" - } - } - } - }, - "在「%@」中新建服务器": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "New Server in “%@”" - } - } - } - }, - "在根目录新建分组": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "New Group at Root" - } - } - } - }, - "在「%@」中新建分组": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "New Group in “%@”" - } - } - } } }, "version": "1.0" diff --git a/ShadowsocksX-NG2/App/ServersView.swift b/ShadowsocksX-NG2/App/ServersView.swift index 1b7ab1ba..aad8e721 100644 --- a/ShadowsocksX-NG2/App/ServersView.swift +++ b/ShadowsocksX-NG2/App/ServersView.swift @@ -258,26 +258,16 @@ extension ServersView { @ToolbarContentBuilder private var toolbarContent: some ToolbarContent { ToolbarItem(placement: .primaryAction) { - Menu { - if let parent = workflow.importTargetParent(for: selection), - let path = workflow.tree.pathSummary(for: parent) - { - Button("在「\(path)」中新建服务器") { presentNewServer(in: parent) } - } - Button("在根目录新建服务器") { presentNewServer(in: nil) } + Button { + presentNewServer(in: workflow.importTargetParent(for: selection)) } label: { Label("新建服务器", systemImage: "plus") } .help("新建服务器") } ToolbarItem(placement: .primaryAction) { - Menu { - if let parent = workflow.importTargetParent(for: selection), - let path = workflow.tree.pathSummary(for: parent) - { - Button("在「\(path)」中新建分组") { presentNewGroup(in: parent) } - } - Button("在根目录新建分组") { presentNewGroup(in: nil) } + Button { + presentNewGroup(in: workflow.importTargetParent(for: selection)) } label: { Label("新建分组", systemImage: "folder.badge.plus") } diff --git a/docs/design/server-tree-selection-and-creation.md b/docs/design/server-tree-selection-and-creation.md index ed9dcbf6..b64ee928 100644 --- a/docs/design/server-tree-selection-and-creation.md +++ b/docs/design/server-tree-selection-and-creation.md @@ -8,13 +8,13 @@ ## 已确认决定 1. 仅调整服务器管理页面的树列表和手动新建服务器/分组入口。首页树、导入入口和移动节点流程维持现有交互。 -2. 两个新增按钮改为菜单,提供当前位置新增与根级新增。菜单明确显示当前位置的目标组;当前位置已经是根时只显示一个新增动作。 +2. 两个新增按钮单击直接按当前选择确定添加位置:手动组对应组内,服务器对应其手动父组,其余情况对应根。添加到根时可先清空选择。用户确认菜单增加了常用组内添加的操作成本,已要求移除菜单双路径方案。 3. 点击列表中没有节点的空白区域取消选择。再次点击已选中行仍保持选择。 4. 仅树列表有焦点时按 Esc 取消选择。文本编辑、表单与弹窗继续处理各自的 Esc。 5. 取消选择显示已有的“未选择节点”详情,不改变活动目标。 6. 取消选择沿用当前离开服务器详情的规则,直接丢弃未保存草稿,不自动保存、不增加确认弹窗。统一草稿保护不属于本次范围。 7. 打开新增窗口保留原选择及原服务器编辑草稿;取消新增返回原详情。 -8. 添加位置在点击菜单项时固定。目标组随后失效时,提交报错并保留输入,不自动改到根。 +8. 添加位置在点击新增按钮或右键新增动作时固定。目标组随后失效时,提交报错并保留输入,不自动改到根。 9. 新建服务器与新建分组成功后,统一选中新节点并展开其祖先组。离开原详情时遵循上述草稿丢弃规则。 10. 已启动的保存继续作用于原服务器,不因取消选择或打开新增而取消。完成后不恢复旧选择、不抢占当前详情,失败按现有方式呈现错误。 @@ -22,14 +22,7 @@ 工具栏按钮名称继续使用“新建服务器/新建分组”,英文沿用对应现有按钮名称。 -| 场景 | 中文 | English | -| --- | --- | --- | -| 根级新增服务器 | 在根目录新建服务器 | New Server at Root | -| 组内新增服务器 | 在「{组路径}」中新建服务器 | New Server in “{Group Path}” | -| 根级新增分组 | 在根目录新建分组 | New Group at Root | -| 组内新增分组 | 在「{组路径}」中新建分组 | New Group in “{Group Path}” | - -嵌套组使用完整路径,例如 `工作 / 香港`,用于区分同名组;当前位置为根时只显示对应根级动作。 +移除菜单双路径方案后,其专用的根级/组内新增中英文文案也一并移除。 ## 实现前代码事实 @@ -42,7 +35,7 @@ - 行为验证覆盖新增目标规则、打开时固定目标、目标失效拒绝、成功后的选择与祖先展开,以及晚保存完成不覆盖新详情。 - 编译与静态检查验证源代码和本地化资源。 -- 用户明确要求本次不使用 computer-use、不做视觉验证。空白点击、树焦点下 Esc、文本/弹窗 Esc 优先级、菜单与路径显示、打开并取消新增后原草稿保留,以及实际展开与选中效果保留为未验证的原生界面行为;代码测试与编译通过不代表这些交互已经通过人工验收。 +- 用户明确要求本次不使用 computer-use、不做视觉验证。空白点击、树焦点下 Esc、文本/弹窗 Esc 优先级、新增按钮交互、打开并取消新增后原草稿保留,以及实际展开与选中效果保留为未验证的原生界面行为;代码测试与编译通过不代表这些交互已经通过人工验收。 ## 文档边界