aboutsummaryrefslogtreecommitdiff
path: root/app/ui
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-26 18:39:33 -0400
committerhistoria <historiavg@proton.me>2026-08-26 18:39:33 -0400
commitdf95e7034df683c38fde67890430ab4c2abfa4ba (patch)
treef46d3eb393e605e82a4d058a2290061b77403649 /app/ui
parent544486a374cd5cae7acce1302648d8dad079db48 (diff)
downloadtts-audiobook-generator-df95e7034df683c38fde67890430ab4c2abfa4ba.tar.gz
feat: in-place toggle field, updated transcription tui to use new field
Diffstat (limited to 'app/ui')
-rw-r--r--app/ui/tui.py35
1 files changed, 28 insertions, 7 deletions
diff --git a/app/ui/tui.py b/app/ui/tui.py
index d91274b..e2118eb 100644
--- a/app/ui/tui.py
+++ b/app/ui/tui.py
@@ -883,6 +883,10 @@ def form(scr, title: str, fields: Sequence[dict],
"validate": lambda s: None if s.isdigit() else "digits only"}
{"key": "combine", "label": "Combine chapters",
"kind": "bool", "value": False}
+ {"key": "transcripts", "label": "Voice transcripts",
+ "kind": "toggle", "value": "missing",
+ "choices": [("Transcribe new voices", "missing"),
+ ("Re-transcribe all voices", "all")]}
{"key": "voices", "label": "Voices directory",
"kind": "dir", "value": Path("./voices")}
@@ -891,7 +895,9 @@ def form(scr, title: str, fields: Sequence[dict],
``choice`` opens a single choice menu (its ``choices`` may be a
callable of the field list, resolved when the menu opens); ``text``
opens a line editor (reusing its VALIDATE); ``bool`` shows Yes/No and
- toggles in place on Enter or Space; ``dir`` opens the DOS-style
+ toggles in place on Enter or Space; ``toggle`` shows the label whose
+ VALUE is selected and cycles through its ``(label, value)`` CHOICES
+ in place on Enter or Space; ``dir`` opens the DOS-style
directory browser (browse_directory) on Enter — its VALUE is a Path
(or str path, used as the browse start), an empty value starts at
the working directory, and backing out of the browser keeps the old
@@ -949,12 +955,28 @@ def form(scr, title: str, fields: Sequence[dict],
if callback is not None:
callback(fields)
+ def activate_inline(field: dict) -> None:
+ """Enter/Space on an in-place field: flip a bool, step a toggle."""
+ if field["kind"] == "bool":
+ field["value"] = not bool(field["value"])
+ else: # toggle: cycle through the choice values
+ values = [value for _label, value in field.get("choices") or []]
+ if values:
+ index = values.index(field["value"]) \
+ if field["value"] in values else -1
+ field["value"] = values[(index + 1) % len(values)]
+ run_on_change(field)
+
def display_value(field: dict) -> str:
if field.get("kind") == "bool":
return "Yes" if field["value"] else "No"
if field.get("kind") == "dir":
value = field["value"]
return str(value) if value is not None else ""
+ if field.get("kind") == "toggle":
+ for label, value in field.get("choices") or []:
+ if value == field["value"]:
+ return label
return str(field["value"])
while True:
@@ -1030,14 +1052,13 @@ def form(scr, title: str, fields: Sequence[dict],
curses.KEY_RIGHT, ord("h"), ord("l")):
on_buttons = True
btn_index = 0
- elif key == ord(" ") and shown[cursor].get("kind") == "bool":
- shown[cursor]["value"] = not bool(shown[cursor]["value"])
- run_on_change(shown[cursor])
+ elif key == ord(" ") and shown[cursor].get("kind") in \
+ ("bool", "toggle"):
+ activate_inline(shown[cursor])
elif key in (10, 13):
field = shown[cursor]
- if field.get("kind") == "bool":
- field["value"] = not bool(field["value"])
- run_on_change(field)
+ if field.get("kind") in ("bool", "toggle"):
+ activate_inline(field)
elif field.get("kind") == "choice":
choices = field.get("choices") or []
if callable(choices):