Compare commits
6 Commits
080c731fd7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4741080284 | |||
| 737147b457 | |||
| 123d35068f | |||
| 258aabe10f | |||
| bc070c4162 | |||
| cbf6bff779 |
@@ -6,9 +6,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
from textual import work
|
from textual import work
|
||||||
from textual.app import App, ComposeResult
|
from textual.app import App, ComposeResult
|
||||||
from textual.containers import Container
|
|
||||||
from textual.events import Key
|
from textual.events import Key
|
||||||
from textual.screen import ModalScreen
|
|
||||||
from textual.widgets import DataTable, Footer, Header, ProgressBar, Static
|
from textual.widgets import DataTable, Footer, Header, ProgressBar, Static
|
||||||
from textual.worker import get_current_worker
|
from textual.worker import get_current_worker
|
||||||
|
|
||||||
@@ -22,41 +20,12 @@ from .table_utils import (
|
|||||||
filter_unfinished_items,
|
filter_unfinished_items,
|
||||||
format_item_as_row,
|
format_item_as_row,
|
||||||
)
|
)
|
||||||
|
from .ui import HelpScreen
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from textual.widgets._data_table import ColumnKey
|
from textual.widgets._data_table import ColumnKey
|
||||||
|
|
||||||
|
|
||||||
class HelpScreen(ModalScreen):
|
|
||||||
"""Help screen displaying all available keybindings."""
|
|
||||||
|
|
||||||
BINDINGS = [("escape", "dismiss", "Close"), ("?", "dismiss", "Close")]
|
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
|
||||||
with Container(id="help_container"):
|
|
||||||
yield Static("Help - Key Bindings", id="help_title")
|
|
||||||
help_table = DataTable(id="help_table")
|
|
||||||
help_table.add_columns("Key", "Action")
|
|
||||||
help_table.show_header = True
|
|
||||||
help_table.zebra_stripes = False
|
|
||||||
help_table.cursor_type = "none"
|
|
||||||
bindings = self.app.BINDINGS
|
|
||||||
for binding in bindings:
|
|
||||||
if isinstance(binding, tuple):
|
|
||||||
key, action, description = binding
|
|
||||||
else:
|
|
||||||
key = binding.key
|
|
||||||
description = binding.description
|
|
||||||
key_display = key.replace(
|
|
||||||
"ctrl+", "^").replace("left", "←").replace("right", "→").replace("space", "Space")
|
|
||||||
help_table.add_row(f"[bold]{key_display}[/]", description)
|
|
||||||
yield help_table
|
|
||||||
yield Static("Press ? or Escape to close", id="help_footer")
|
|
||||||
|
|
||||||
def action_dismiss(self) -> None:
|
|
||||||
self.dismiss()
|
|
||||||
|
|
||||||
|
|
||||||
class Auditui(App):
|
class Auditui(App):
|
||||||
"""Main application class for the Audible TUI app."""
|
"""Main application class for the Audible TUI app."""
|
||||||
|
|
||||||
|
|||||||
@@ -140,71 +140,97 @@ ProgressBar#progress_bar > .progress-bar--track {
|
|||||||
|
|
||||||
ProgressBar#progress_bar > .progress-bar--bar {
|
ProgressBar#progress_bar > .progress-bar--bar {
|
||||||
background: #a6e3a1;
|
background: #a6e3a1;
|
||||||
width: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HelpScreen {
|
HelpScreen {
|
||||||
align: center middle;
|
align: center middle;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_container {
|
#help_container {
|
||||||
width: 60;
|
width: 70;
|
||||||
height: auto;
|
height: auto;
|
||||||
max-height: 80%;
|
max-height: 85%;
|
||||||
|
min-height: 20;
|
||||||
background: #1e1e2e;
|
background: #1e1e2e;
|
||||||
border: solid #585b70;
|
border: thick #89b4fa;
|
||||||
padding: 1;
|
padding: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_title {
|
#help_title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-style: bold;
|
text-style: bold;
|
||||||
color: #cdd6f4;
|
color: #89b4fa;
|
||||||
margin-bottom: 1;
|
margin-bottom: 2;
|
||||||
padding-bottom: 1;
|
padding-bottom: 1;
|
||||||
border-bottom: solid #585b70;
|
border-bottom: solid #585b70;
|
||||||
|
height: 3;
|
||||||
|
align: center middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_content {
|
#help_content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: 1fr;
|
||||||
padding: 1;
|
padding: 1 0;
|
||||||
}
|
|
||||||
|
|
||||||
#help_table {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
background: #1e1e2e;
|
|
||||||
border: none;
|
|
||||||
margin: 1 0;
|
margin: 1 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-size: 0 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_table > .datatable--header {
|
#help_content > .scrollbar--vertical {
|
||||||
|
background: #313244;
|
||||||
|
}
|
||||||
|
|
||||||
|
#help_content > .scrollbar--vertical > .scrollbar--track {
|
||||||
|
background: #181825;
|
||||||
|
}
|
||||||
|
|
||||||
|
#help_content > .scrollbar--vertical > .scrollbar--handle {
|
||||||
|
background: #585b70;
|
||||||
|
}
|
||||||
|
|
||||||
|
#help_content > .scrollbar--vertical > .scrollbar--handle:hover {
|
||||||
background: #45475a;
|
background: #45475a;
|
||||||
color: #bac2de;
|
|
||||||
text-style: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_table > .datatable--cursor {
|
.help_row {
|
||||||
background: transparent;
|
height: 3;
|
||||||
}
|
margin: 0 0 1 0;
|
||||||
|
|
||||||
#help_table > .datatable--odd-row,
|
|
||||||
#help_table > .datatable--even-row {
|
|
||||||
background: #1e1e2e;
|
|
||||||
}
|
|
||||||
|
|
||||||
#help_binding {
|
|
||||||
padding: 0 1;
|
padding: 0 1;
|
||||||
margin: 0;
|
background: #181825;
|
||||||
|
border: solid #313244;
|
||||||
|
align: left middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help_row:hover {
|
||||||
|
background: #313244;
|
||||||
|
border: solid #45475a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help_key {
|
||||||
|
width: 20;
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 2 0 0;
|
||||||
|
color: #f9e2af;
|
||||||
|
text-style: bold;
|
||||||
|
align: right middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help_action {
|
||||||
|
width: 1fr;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0 0 0 2;
|
||||||
color: #cdd6f4;
|
color: #cdd6f4;
|
||||||
|
align: left middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_footer {
|
#help_footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #bac2de;
|
color: #bac2de;
|
||||||
margin-top: 1;
|
margin-top: 2;
|
||||||
padding-top: 1;
|
padding-top: 1;
|
||||||
border-top: solid #585b70;
|
border-top: solid #585b70;
|
||||||
|
height: 3;
|
||||||
|
align: center middle;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|||||||
33
auditui/ui.py
Normal file
33
auditui/ui.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
"""UI components for the Auditui application."""
|
||||||
|
|
||||||
|
from textual.app import ComposeResult
|
||||||
|
from textual.containers import Container, Horizontal, ScrollableContainer
|
||||||
|
from textual.screen import ModalScreen
|
||||||
|
from textual.widgets import Static
|
||||||
|
|
||||||
|
|
||||||
|
class HelpScreen(ModalScreen):
|
||||||
|
"""Help screen displaying all available keybindings."""
|
||||||
|
|
||||||
|
BINDINGS = [("escape", "dismiss", "Close"), ("?", "dismiss", "Close")]
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
with Container(id="help_container"):
|
||||||
|
yield Static("Key Bindings", id="help_title")
|
||||||
|
with ScrollableContainer(id="help_content"):
|
||||||
|
bindings = self.app.BINDINGS
|
||||||
|
for binding in bindings:
|
||||||
|
if isinstance(binding, tuple):
|
||||||
|
key, action, description = binding
|
||||||
|
else:
|
||||||
|
key = binding.key
|
||||||
|
description = binding.description
|
||||||
|
key_display = key.replace(
|
||||||
|
"ctrl+", "^").replace("left", "←").replace("right", "→").replace("space", "Space").replace("enter", "Enter")
|
||||||
|
with Horizontal(classes="help_row"):
|
||||||
|
yield Static(f"[bold #f9e2af]{key_display}[/]", classes="help_key")
|
||||||
|
yield Static(description, classes="help_action")
|
||||||
|
yield Static("Press [bold #f9e2af]?[/] or [bold #f9e2af]Escape[/] to close", id="help_footer")
|
||||||
|
|
||||||
|
def action_dismiss(self) -> None:
|
||||||
|
self.dismiss()
|
||||||
7
main.py
7
main.py
@@ -2,7 +2,6 @@
|
|||||||
"""Auditui entrypoint."""
|
"""Auditui entrypoint."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from auditui.app import Auditui
|
from auditui.app import Auditui
|
||||||
from auditui.auth import authenticate
|
from auditui.auth import authenticate
|
||||||
@@ -24,7 +23,7 @@ def main() -> None:
|
|||||||
config_dir = AUTH_PATH.parent
|
config_dir = AUTH_PATH.parent
|
||||||
|
|
||||||
if not config_dir.exists():
|
if not config_dir.exists():
|
||||||
print("No configuration yet, please run 'auditui configure' to create it")
|
print("No configuration yet, please run 'auditui configure'.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -32,9 +31,9 @@ def main() -> None:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(f"Authentication error: {exc}")
|
print(f"Authentication error: {exc}")
|
||||||
if not AUTH_PATH.exists():
|
if not AUTH_PATH.exists():
|
||||||
print("No configuration yet, please run 'auditui configure' to create it")
|
print("No configuration yet, please run 'auditui configure'.")
|
||||||
else:
|
else:
|
||||||
print("Please re-authenticate by running 'auditui configure'")
|
print("Please re-authenticate by running 'auditui configure'.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
app = Auditui(auth=auth, client=client)
|
app = Auditui(auth=auth, client=client)
|
||||||
|
|||||||
Reference in New Issue
Block a user