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/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()