diff options
| author | historia <historiavg@proton.me> | 2026-08-25 18:10:08 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-25 18:10:08 -0400 |
| commit | 4b49797b4d57c2d2cf63472636622a7a6280a38e (patch) | |
| tree | e3687c734de5d6159cdad288e025057ed6cd3a16 /app/ui | |
| parent | bcac6c42eaf9e004716d72960bddefb1db68a93c (diff) | |
| download | tts-audiobook-generator-4b49797b4d57c2d2cf63472636622a7a6280a38e.tar.gz | |
feat: no console drop when uninstalling backends
Diffstat (limited to 'app/ui')
| -rw-r--r-- | app/ui/hub.py | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/app/ui/hub.py b/app/ui/hub.py index f937b84..d20b28e 100644 --- a/app/ui/hub.py +++ b/app/ui/hub.py @@ -10,10 +10,10 @@ The entire hub runs in one curses session, driven by a single ``tui.Wizard`` stack of screens (the ``_Hub`` class below). Every menu/action is a screen that returns the next screen, ``Wizard.BACK`` (Esc/q) to pop one screen, or None to quit. Backend setup wizards and the conversion run view run as -opaque leaf screens on this same session (the wizards' long setup tails and -model downloads run inside the ``ui.taskview`` task view, and only the quick -uninstall/start/stop actions use ``tui.suspend``); a leaf screen finishes by -returning ``Wizard.BACK``, so +opaque leaf screens on this same session; every long step — setup tails, +model downloads, server start/stop, and uninstall — runs inside the +``ui.taskview`` task view, so the user is never dropped to the console. +A leaf screen finishes by returning ``Wizard.BACK``, so the stack lands back on the menu that launched it. Esc therefore steps back exactly one screen everywhere — on the main menu (an empty stack) it quits. 'q' mirrors Esc on every screen that has no typed text. @@ -253,11 +253,41 @@ class _Hub: return self.screen_setup(info) def screen_uninstall(self): + """Pick a backend, confirm, then uninstall it inside the task view. + + Esc on the picker or the confirm (or answering No) backs out + untouched. A confirmed uninstall runs as one task-view step on this + session — no console drop: the backend's ``uninstall`` stops its + servers, pip-uninstalls, and deletes its files, honoring cancel + between phases only. A flash summarizes the result and the stack + lands back on the Configure menu, whose status table re-detects the + removal. + """ info = self._pick_backend(installed_only=True) if info is None: return tui.Wizard.BACK - with tui.suspend(self.stdscr): - info.uninstall() + answer = tui.confirm( + self.stdscr, f"Uninstall {info.label}?", + body=[f"This permanently removes {info.label} from this " + "machine: managed servers are stopped and every installed " + "file — including downloaded models — is deleted."], + default=False, cancel_value=tui.Wizard.BACK) + if answer is not True: + return tui.Wizard.BACK + title = f"Uninstall {info.label}" + step = taskview.TaskStep( + title, + lambda emit, cancel: info.uninstall(emit=emit, cancel=cancel)) + rc = taskview.run_steps(self.stdscr, title, [step], + wait_on_finish=False) + # The uninstallers warn-and-continue (a failed pip step still + # returns 0), so rc == 0 means "finished"; anything else covers a + # failure or an Esc-cancelled run between phases. + if rc == 0: + tui.flash(self.stdscr, f"{info.label} uninstalled.", "ok") + else: + tui.flash(self.stdscr, + f"Could not fully uninstall {info.label}.", "err") return tui.Wizard.BACK def _pick_backend(self, installed_only: bool): |
