From c65361c009e4c8d4adf3f1ce0278bac9a8cab4c3 Mon Sep 17 00:00:00 2001 From: Donald Date: Thu, 3 Sep 2026 13:54:06 +0000 Subject: [PATCH] Fix delete shortcut handling in session manager --- README.md | 6 +++--- herdr_hub/selector.py | 12 +++++++----- tests/test_selector.py | 6 ++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 46e639c..bb06c9d 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ window,同时在后台并行查询所有已登记远端;每台机器的结 | `▶` 当前 / `●` 已打开 | 跳转到已有 window | | `×` 已断线 | 自动重连并跳转 | | `○` 远端运行 | 新建 attach window 并跳转 | -| `■` 远端已停止 | Enter/单击启动;按 `d` 可删除历史 Session | +| `■` 远端已停止 | Enter/单击启动;按 `d` 或 `D` 可删除历史 Session | | `↻` Windows 旧窗口 | 原地切换为 SSH TTY 模式并重连 | 弹窗靠前位置提供“关闭当前 Tab”;它只结束该 Tab 中的 Hub client,底层 Herdr @@ -131,8 +131,8 @@ Session”;二次确认后会在后台停止远端 Herdr Session、中断其 记忆记录,不关闭已有 window,也不停止远端 Herdr server。手机端单击条目即可执行, 键盘支持上下键、Enter、输入搜索、Backspace、`Ctrl+R` 刷新和 Esc 返回/关闭。 -选中标记为 `■ 已停止` 且没有对应 Hub Tab 的远端 Session 后,按小写 `d` 会进入 -二次确认;可点击“确认删除”、按 Enter,或再按一次 `d`。确认后在后台通过 SSH 执行 +选中标记为 `■ 已停止` 且没有对应 Hub Tab 的远端 Session 后,按 `d` 或 `D` 会进入 +二次确认;可点击“确认删除”、按 Enter,或再按一次 `d`/`D`。确认后在后台通过 SSH 执行 `herdr session delete`,永久删除该 Session 的工作现场 和历史数据,并留在弹窗中继续管理。运行中的 Session 和仍有 Tab 的 Session 不允许删除。 diff --git a/herdr_hub/selector.py b/herdr_hub/selector.py index b90f6ed..7960fb6 100644 --- a/herdr_hub/selector.py +++ b/herdr_hub/selector.py @@ -352,13 +352,13 @@ def build_main_rows( detail = ( "Windows · SSH 模式 · 单击打开" if running - else "Windows · 已停止 · Enter 启动 · d 删除" + else "Windows · 已停止 · Enter 启动 · d/D 删除" ) else: detail = ( "远端运行 · 单击打开" if running - else "已停止 · Enter 启动 · d 删除" + else "已停止 · Enter 启动 · d/D 删除" ) rows.append( PickerRow( @@ -724,17 +724,19 @@ class SessionSelector: return None if key in {curses.KEY_ENTER, "\n", "\r"}: return self._activate(self._selected_row(rows)) - if key == "d" and self.view == "confirm-delete-session": + if key in {"d", "D"} and self.view == "confirm-delete-session": row = next( (item for item in rows if item.kind == "delete-session-yes"), None, ) return self._activate(row) - if key == "d" and self.view == "main": + if key in {"d", "D"} and self.view == "main": row = self._selected_row(rows) if row is not None and row.deletable: self._show_delete_session_confirmation(row) return None + self.message = "只能删除已停止且没有对应 Tab 的远端 Session" + return None if key == "\x12" and self.view == "main": self.results.clear() self.pool.enqueue_many(self.entries.values()) @@ -1191,7 +1193,7 @@ class SessionSelector: line = f" {main} {detail}" self._safe_add(screen, y, 0, line, attribute) - footer = "Enter 打开 · d 删除停止项 · Ctrl+R 刷新 · Esc 关闭" + footer = "Enter 打开 · d/D 删除停止项 · Ctrl+R 刷新 · Esc 关闭" if self.view in {"working-delete-session", "working-stop-session"}: footer = "远端操作进行中,请稍候" elif self.view != "main": diff --git a/tests/test_selector.py b/tests/test_selector.py index 0257f4d..1720ccc 100644 --- a/tests/test_selector.py +++ b/tests/test_selector.py @@ -91,7 +91,7 @@ class SelectorCatalogTests(unittest.TestCase): self.assertIn("remote:orangepi:default", by_key) self.assertIn("remote:orangepi:old", by_key) self.assertTrue(by_key["remote:orangepi:old"].deletable) - self.assertIn("d 删除", by_key["remote:orangepi:old"].detail) + self.assertIn("d/D 删除", by_key["remote:orangepi:old"].detail) self.assertFalse(by_key["remote:orangepi:default"].deletable) self.assertIn("new:orangepi", by_key) self.assertEqual(by_key["local:draft"].main, "○ draft") @@ -340,11 +340,13 @@ class SelectorActionTests(unittest.TestCase): selector._handle_key("d", rows) # type: ignore[attr-defined] self.assertEqual(selector.view, "main") self.assertEqual(deleted, []) + self.assertEqual(selector.query, "") + self.assertIn("只能删除", selector.message) selector.query = "" old = next(row for row in rows if row.key == "remote:orangepi:old") selector.selected_key = old.key - selector._handle_key("d", rows) # type: ignore[attr-defined] + selector._handle_key("D", rows) # type: ignore[attr-defined] self.assertEqual(selector.view, "confirm-delete-session") confirm = next( row