wrkmon 1.0.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wrkmon/__init__.py +1 -1
- wrkmon/app.py +323 -5
- wrkmon/cli.py +100 -0
- wrkmon/core/media_keys.py +377 -0
- wrkmon/core/queue.py +55 -0
- wrkmon/core/youtube.py +102 -0
- wrkmon/data/database.py +120 -0
- wrkmon/data/migrations.py +26 -0
- wrkmon/ui/screens/help.py +80 -0
- wrkmon/ui/theme.py +332 -75
- wrkmon/ui/views/search.py +283 -19
- wrkmon/ui/widgets/header.py +31 -1
- wrkmon/ui/widgets/player_bar.py +52 -5
- wrkmon/ui/widgets/thumbnail.py +230 -0
- wrkmon/utils/ascii_art.py +408 -0
- wrkmon/utils/config.py +85 -4
- wrkmon/utils/updater.py +311 -0
- {wrkmon-1.0.0.dist-info → wrkmon-1.2.0.dist-info}/METADATA +170 -193
- {wrkmon-1.0.0.dist-info → wrkmon-1.2.0.dist-info}/RECORD +23 -18
- {wrkmon-1.0.0.dist-info → wrkmon-1.2.0.dist-info}/WHEEL +1 -1
- {wrkmon-1.0.0.dist-info → wrkmon-1.2.0.dist-info}/entry_points.txt +0 -0
- {wrkmon-1.0.0.dist-info → wrkmon-1.2.0.dist-info}/top_level.txt +0 -0
- /wrkmon-1.0.0.dist-info/licenses/LICENSE.txt → /wrkmon-1.2.0.dist-info/licenses/LICENSE +0 -0
wrkmon/data/migrations.py
CHANGED
|
@@ -64,6 +64,32 @@ MIGRATIONS: list[tuple[int, str, str]] = [
|
|
|
64
64
|
);
|
|
65
65
|
""",
|
|
66
66
|
),
|
|
67
|
+
(
|
|
68
|
+
2,
|
|
69
|
+
"Add queue persistence",
|
|
70
|
+
"""
|
|
71
|
+
-- Queue table for persistent queue
|
|
72
|
+
CREATE TABLE IF NOT EXISTS queue (
|
|
73
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
74
|
+
track_id INTEGER NOT NULL,
|
|
75
|
+
position INTEGER NOT NULL,
|
|
76
|
+
playback_position INTEGER DEFAULT 0,
|
|
77
|
+
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
78
|
+
FOREIGN KEY (track_id) REFERENCES tracks(id) ON DELETE CASCADE
|
|
79
|
+
);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_queue_position ON queue(position);
|
|
81
|
+
|
|
82
|
+
-- Queue state table (single row for current state)
|
|
83
|
+
CREATE TABLE IF NOT EXISTS queue_state (
|
|
84
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
85
|
+
current_index INTEGER DEFAULT -1,
|
|
86
|
+
shuffle_mode INTEGER DEFAULT 0,
|
|
87
|
+
repeat_mode TEXT DEFAULT 'none',
|
|
88
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
89
|
+
);
|
|
90
|
+
INSERT OR IGNORE INTO queue_state (id) VALUES (1);
|
|
91
|
+
""",
|
|
92
|
+
),
|
|
67
93
|
]
|
|
68
94
|
|
|
69
95
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Help overlay screen for wrkmon."""
|
|
2
|
+
|
|
3
|
+
from textual.app import ComposeResult
|
|
4
|
+
from textual.containers import Container, Vertical, VerticalScroll
|
|
5
|
+
from textual.screen import ModalScreen
|
|
6
|
+
from textual.widgets import Static
|
|
7
|
+
from textual.binding import Binding
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
HELP_TEXT = """
|
|
11
|
+
[bold cyan]━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[/]
|
|
12
|
+
[bold cyan] WRKMON KEYBOARD SHORTCUTS[/]
|
|
13
|
+
[bold cyan]━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[/]
|
|
14
|
+
|
|
15
|
+
[bold orange1]NAVIGATION[/]
|
|
16
|
+
[bold purple]F1[/] Switch to Search view
|
|
17
|
+
[bold purple]F2[/] Switch to Queue view
|
|
18
|
+
[bold purple]F3[/] Switch to History view
|
|
19
|
+
[bold purple]F4[/] Switch to Playlists view
|
|
20
|
+
[bold purple]j / ↓[/] Move down in list
|
|
21
|
+
[bold purple]k / ↑[/] Move up in list
|
|
22
|
+
[bold purple]g / Home[/] Jump to top of list
|
|
23
|
+
[bold purple]G / End[/] Jump to bottom of list
|
|
24
|
+
[bold purple]Tab[/] Next focusable element
|
|
25
|
+
[bold purple]Shift+Tab[/] Previous focusable element
|
|
26
|
+
|
|
27
|
+
[bold orange1]PLAYBACK[/]
|
|
28
|
+
[bold purple]F5 / Space[/] Play / Pause
|
|
29
|
+
[bold purple]F6 / -[/] Volume down
|
|
30
|
+
[bold purple]F7 / + =[/] Volume up
|
|
31
|
+
[bold purple]F8 / n[/] Next track
|
|
32
|
+
[bold purple]p[/] Previous track
|
|
33
|
+
[bold purple]F9 / s[/] Stop playback
|
|
34
|
+
[bold purple]r[/] Cycle repeat mode (Off → One → All)
|
|
35
|
+
[bold purple]m[/] Mute / Unmute
|
|
36
|
+
|
|
37
|
+
[bold orange1]SEARCH & QUEUE[/]
|
|
38
|
+
[bold purple]/[/] Focus search input
|
|
39
|
+
[bold purple]Enter[/] Play selected track
|
|
40
|
+
[bold purple]a[/] Add selected to queue
|
|
41
|
+
[bold purple]F10[/] Add highlighted to queue
|
|
42
|
+
[bold purple]d / Del[/] Remove from queue
|
|
43
|
+
[bold purple]c[/] Clear queue
|
|
44
|
+
|
|
45
|
+
[bold orange1]VIEW OPTIONS[/]
|
|
46
|
+
[bold purple]t[/] Toggle thumbnail preview
|
|
47
|
+
[bold purple]?[/] Show this help
|
|
48
|
+
[bold purple]Escape[/] Close overlay / Go back
|
|
49
|
+
|
|
50
|
+
[bold orange1]APPLICATION[/]
|
|
51
|
+
[bold purple]Ctrl+Q[/] Quit application
|
|
52
|
+
[bold purple]Ctrl+C[/] Quit application
|
|
53
|
+
|
|
54
|
+
[bold cyan]━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[/]
|
|
55
|
+
[dim]Press [bold]Escape[/bold] or [bold]?[/bold] to close this help[/]
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class HelpScreen(ModalScreen):
|
|
60
|
+
"""Modal help screen showing keyboard shortcuts."""
|
|
61
|
+
|
|
62
|
+
BINDINGS = [
|
|
63
|
+
Binding("escape", "close", "Close", show=False),
|
|
64
|
+
Binding("?", "close", "Close", show=False),
|
|
65
|
+
Binding("q", "close", "Close", show=False),
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
def compose(self) -> ComposeResult:
|
|
69
|
+
with Container(id="help-container"):
|
|
70
|
+
yield Static("[bold cyan]⌨ KEYBOARD SHORTCUTS[/]", id="help-title")
|
|
71
|
+
with VerticalScroll(id="help-scroll"):
|
|
72
|
+
yield Static(HELP_TEXT, id="help-content", markup=True)
|
|
73
|
+
|
|
74
|
+
def action_close(self) -> None:
|
|
75
|
+
"""Close the help screen."""
|
|
76
|
+
self.dismiss()
|
|
77
|
+
|
|
78
|
+
def on_click(self) -> None:
|
|
79
|
+
"""Close on click outside."""
|
|
80
|
+
self.dismiss()
|