meeting-noter 1.3.0__py3-none-any.whl → 3.0.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.

Potentially problematic release.


This version of meeting-noter might be problematic. Click here for more details.

Files changed (40) hide show
  1. meeting_noter/__init__.py +1 -1
  2. meeting_noter/cli.py +103 -0
  3. meeting_noter/daemon.py +38 -0
  4. meeting_noter/gui/__init__.py +51 -0
  5. meeting_noter/gui/main_window.py +219 -0
  6. meeting_noter/gui/menubar.py +248 -0
  7. meeting_noter/gui/screens/__init__.py +17 -0
  8. meeting_noter/gui/screens/dashboard.py +262 -0
  9. meeting_noter/gui/screens/logs.py +184 -0
  10. meeting_noter/gui/screens/recordings.py +279 -0
  11. meeting_noter/gui/screens/search.py +229 -0
  12. meeting_noter/gui/screens/settings.py +232 -0
  13. meeting_noter/gui/screens/viewer.py +140 -0
  14. meeting_noter/gui/theme/__init__.py +5 -0
  15. meeting_noter/gui/theme/dark_theme.py +53 -0
  16. meeting_noter/gui/theme/styles.qss +504 -0
  17. meeting_noter/gui/utils/__init__.py +15 -0
  18. meeting_noter/gui/utils/signals.py +82 -0
  19. meeting_noter/gui/utils/workers.py +258 -0
  20. meeting_noter/gui/widgets/__init__.py +6 -0
  21. meeting_noter/gui/widgets/sidebar.py +210 -0
  22. meeting_noter/gui/widgets/status_indicator.py +108 -0
  23. meeting_noter/mic_monitor.py +29 -1
  24. meeting_noter/ui/__init__.py +5 -0
  25. meeting_noter/ui/app.py +68 -0
  26. meeting_noter/ui/screens/__init__.py +17 -0
  27. meeting_noter/ui/screens/logs.py +166 -0
  28. meeting_noter/ui/screens/main.py +346 -0
  29. meeting_noter/ui/screens/recordings.py +241 -0
  30. meeting_noter/ui/screens/search.py +191 -0
  31. meeting_noter/ui/screens/settings.py +184 -0
  32. meeting_noter/ui/screens/viewer.py +116 -0
  33. meeting_noter/ui/styles/app.tcss +257 -0
  34. meeting_noter/ui/widgets/__init__.py +1 -0
  35. {meeting_noter-1.3.0.dist-info → meeting_noter-3.0.0.dist-info}/METADATA +4 -1
  36. meeting_noter-3.0.0.dist-info/RECORD +65 -0
  37. meeting_noter-1.3.0.dist-info/RECORD +0 -35
  38. {meeting_noter-1.3.0.dist-info → meeting_noter-3.0.0.dist-info}/WHEEL +0 -0
  39. {meeting_noter-1.3.0.dist-info → meeting_noter-3.0.0.dist-info}/entry_points.txt +0 -0
  40. {meeting_noter-1.3.0.dist-info → meeting_noter-3.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,504 @@
1
+ /* Meeting Noter Dark Theme - Terminal Style */
2
+
3
+ /* ========== Global ========== */
4
+ * {
5
+ font-family: "Menlo", "Monaco", "Courier New", monospace;
6
+ font-size: 13px;
7
+ }
8
+
9
+ /* ========== Main Window ========== */
10
+ QMainWindow {
11
+ background-color: #1a1a1a;
12
+ }
13
+
14
+ QWidget {
15
+ background-color: #1a1a1a;
16
+ color: #d4d4d4;
17
+ }
18
+
19
+ /* ========== Sidebar ========== */
20
+ #sidebar {
21
+ background-color: #0d0d0d;
22
+ border-right: 1px solid #2a2a2a;
23
+ }
24
+
25
+ #sidebar-title-frame {
26
+ background-color: #0d0d0d;
27
+ border-bottom: none;
28
+ }
29
+
30
+ #sidebar-title {
31
+ color: #4ec9b0;
32
+ font-size: 18px;
33
+ font-weight: bold;
34
+ }
35
+
36
+ #sidebar QPushButton {
37
+ background-color: transparent;
38
+ border: none;
39
+ border-radius: 6px;
40
+ padding: 12px 15px;
41
+ text-align: left;
42
+ color: #808080;
43
+ font-size: 14px;
44
+ margin: 3px 10px;
45
+ }
46
+
47
+ #sidebar QPushButton:hover {
48
+ background-color: #1a1a1a;
49
+ color: #d4d4d4;
50
+ }
51
+
52
+ #sidebar QPushButton:checked {
53
+ background-color: #2a2a2a;
54
+ color: #4ec9b0;
55
+ border-left: 3px solid #4ec9b0;
56
+ border-radius: 0 6px 6px 0;
57
+ margin-left: 0;
58
+ padding-left: 22px;
59
+ }
60
+
61
+ #sidebar-status {
62
+ background-color: #0d0d0d;
63
+ }
64
+
65
+ /* ========== Content Area ========== */
66
+ #content-area {
67
+ background-color: #1a1a1a;
68
+ }
69
+
70
+ /* ========== Cards/Panels ========== */
71
+ .panel {
72
+ background-color: #0d0d0d;
73
+ border: 1px solid #2a2a2a;
74
+ border-radius: 8px;
75
+ padding: 15px;
76
+ }
77
+
78
+ /* ========== Labels ========== */
79
+ QLabel {
80
+ color: #d4d4d4;
81
+ background-color: transparent;
82
+ }
83
+
84
+ QLabel.heading {
85
+ font-size: 22px;
86
+ font-weight: 600;
87
+ color: #ffffff;
88
+ }
89
+
90
+ QLabel.subheading {
91
+ font-size: 14px;
92
+ color: #808080;
93
+ }
94
+
95
+ QLabel.section-title {
96
+ font-size: 11px;
97
+ font-weight: 600;
98
+ color: #808080;
99
+ text-transform: uppercase;
100
+ letter-spacing: 2px;
101
+ }
102
+
103
+ /* ========== Inputs ========== */
104
+ QLineEdit, QSpinBox {
105
+ background-color: #0d0d0d;
106
+ border: 1px solid #2a2a2a;
107
+ border-radius: 6px;
108
+ padding: 10px 14px;
109
+ color: #d4d4d4;
110
+ selection-background-color: #264f78;
111
+ font-size: 14px;
112
+ }
113
+
114
+ QLineEdit:focus, QSpinBox:focus {
115
+ border-color: #4ec9b0;
116
+ }
117
+
118
+ QLineEdit:disabled, QSpinBox:disabled {
119
+ background-color: #1a1a1a;
120
+ color: #5a5a5a;
121
+ }
122
+
123
+ QLineEdit::placeholder {
124
+ color: #5a5a5a;
125
+ }
126
+
127
+ /* ========== ComboBox ========== */
128
+ QComboBox {
129
+ background-color: #0d0d0d;
130
+ border: 1px solid #2a2a2a;
131
+ border-radius: 6px;
132
+ padding: 10px 14px;
133
+ color: #d4d4d4;
134
+ min-width: 150px;
135
+ font-size: 14px;
136
+ }
137
+
138
+ QComboBox:focus {
139
+ border-color: #4ec9b0;
140
+ }
141
+
142
+ QComboBox::drop-down {
143
+ border: none;
144
+ width: 24px;
145
+ }
146
+
147
+ QComboBox::down-arrow {
148
+ image: none;
149
+ border-left: 5px solid transparent;
150
+ border-right: 5px solid transparent;
151
+ border-top: 6px solid #808080;
152
+ margin-right: 10px;
153
+ }
154
+
155
+ QComboBox QAbstractItemView {
156
+ background-color: #0d0d0d;
157
+ border: 1px solid #2a2a2a;
158
+ border-radius: 6px;
159
+ selection-background-color: #264f78;
160
+ color: #d4d4d4;
161
+ padding: 5px;
162
+ }
163
+
164
+ /* ========== Buttons ========== */
165
+ QPushButton {
166
+ background-color: #4ec9b0;
167
+ border: none;
168
+ border-radius: 6px;
169
+ padding: 10px 20px;
170
+ color: #0d0d0d;
171
+ font-weight: 600;
172
+ font-size: 13px;
173
+ min-width: 90px;
174
+ }
175
+
176
+ QPushButton:hover {
177
+ background-color: #5fd9c0;
178
+ }
179
+
180
+ QPushButton:pressed {
181
+ background-color: #3eb9a0;
182
+ }
183
+
184
+ QPushButton:disabled {
185
+ background-color: #2a2a2a;
186
+ color: #5a5a5a;
187
+ }
188
+
189
+ QPushButton.secondary {
190
+ background-color: #2a2a2a;
191
+ color: #d4d4d4;
192
+ }
193
+
194
+ QPushButton.secondary:hover {
195
+ background-color: #3a3a3a;
196
+ }
197
+
198
+ QPushButton.success {
199
+ background-color: #4ec9b0;
200
+ }
201
+
202
+ QPushButton.success:hover {
203
+ background-color: #5fd9c0;
204
+ }
205
+
206
+ QPushButton.danger {
207
+ background-color: #f14c4c;
208
+ }
209
+
210
+ QPushButton.danger:hover {
211
+ background-color: #ff6b6b;
212
+ }
213
+
214
+ QPushButton.warning {
215
+ background-color: #dcdcaa;
216
+ color: #0d0d0d;
217
+ }
218
+
219
+ QPushButton.warning:hover {
220
+ background-color: #ececa0;
221
+ }
222
+
223
+ /* ========== Tables ========== */
224
+ QTableWidget, QTableView {
225
+ background-color: #0d0d0d;
226
+ alternate-background-color: #141414;
227
+ border: 1px solid #2a2a2a;
228
+ border-radius: 6px;
229
+ gridline-color: #2a2a2a;
230
+ color: #d4d4d4;
231
+ selection-background-color: #264f78;
232
+ font-size: 13px;
233
+ }
234
+
235
+ QTableWidget::item, QTableView::item {
236
+ padding: 10px;
237
+ }
238
+
239
+ QTableWidget::item:selected, QTableView::item:selected {
240
+ background-color: #264f78;
241
+ }
242
+
243
+ QHeaderView::section {
244
+ background-color: #1a1a1a;
245
+ border: none;
246
+ border-bottom: 1px solid #2a2a2a;
247
+ border-right: 1px solid #2a2a2a;
248
+ padding: 10px 14px;
249
+ color: #808080;
250
+ font-weight: 600;
251
+ font-size: 12px;
252
+ }
253
+
254
+ QHeaderView::section:last {
255
+ border-right: none;
256
+ }
257
+
258
+ /* ========== Text Areas ========== */
259
+ QTextEdit, QPlainTextEdit {
260
+ background-color: #0d0d0d;
261
+ border: 1px solid #2a2a2a;
262
+ border-radius: 6px;
263
+ color: #d4d4d4;
264
+ font-family: "Menlo", "Monaco", "Courier New", monospace;
265
+ font-size: 13px;
266
+ selection-background-color: #264f78;
267
+ padding: 12px;
268
+ line-height: 1.5;
269
+ }
270
+
271
+ QTextEdit:focus, QPlainTextEdit:focus {
272
+ border-color: #4ec9b0;
273
+ }
274
+
275
+ /* ========== Checkboxes ========== */
276
+ QCheckBox {
277
+ color: #d4d4d4;
278
+ spacing: 10px;
279
+ background-color: transparent;
280
+ font-size: 14px;
281
+ }
282
+
283
+ QCheckBox::indicator {
284
+ width: 20px;
285
+ height: 20px;
286
+ border-radius: 4px;
287
+ border: 2px solid #5a5a5a;
288
+ background-color: #0d0d0d;
289
+ }
290
+
291
+ QCheckBox::indicator:hover {
292
+ border-color: #4ec9b0;
293
+ }
294
+
295
+ QCheckBox::indicator:checked {
296
+ background-color: #4ec9b0;
297
+ border-color: #4ec9b0;
298
+ }
299
+
300
+ /* ========== ScrollBars ========== */
301
+ QScrollBar:vertical {
302
+ background-color: #0d0d0d;
303
+ width: 14px;
304
+ border-radius: 7px;
305
+ margin: 0;
306
+ }
307
+
308
+ QScrollBar::handle:vertical {
309
+ background-color: #3a3a3a;
310
+ border-radius: 7px;
311
+ min-height: 40px;
312
+ margin: 3px;
313
+ }
314
+
315
+ QScrollBar::handle:vertical:hover {
316
+ background-color: #4a4a4a;
317
+ }
318
+
319
+ QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
320
+ height: 0;
321
+ }
322
+
323
+ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
324
+ background: none;
325
+ }
326
+
327
+ QScrollBar:horizontal {
328
+ background-color: #0d0d0d;
329
+ height: 14px;
330
+ border-radius: 7px;
331
+ margin: 0;
332
+ }
333
+
334
+ QScrollBar::handle:horizontal {
335
+ background-color: #3a3a3a;
336
+ border-radius: 7px;
337
+ min-width: 40px;
338
+ margin: 3px;
339
+ }
340
+
341
+ QScrollBar::handle:horizontal:hover {
342
+ background-color: #4a4a4a;
343
+ }
344
+
345
+ QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
346
+ width: 0;
347
+ }
348
+
349
+ QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
350
+ background: none;
351
+ }
352
+
353
+ /* ========== List Views ========== */
354
+ QListWidget, QListView {
355
+ background-color: #0d0d0d;
356
+ border: 1px solid #2a2a2a;
357
+ border-radius: 6px;
358
+ color: #d4d4d4;
359
+ outline: none;
360
+ font-size: 13px;
361
+ }
362
+
363
+ QListWidget::item, QListView::item {
364
+ padding: 10px 14px;
365
+ border-radius: 4px;
366
+ margin: 2px 6px;
367
+ }
368
+
369
+ QListWidget::item:hover, QListView::item:hover {
370
+ background-color: #1a1a1a;
371
+ }
372
+
373
+ QListWidget::item:selected, QListView::item:selected {
374
+ background-color: #264f78;
375
+ }
376
+
377
+ /* ========== Group Box ========== */
378
+ QGroupBox {
379
+ font-weight: 600;
380
+ border: 1px solid #2a2a2a;
381
+ border-radius: 8px;
382
+ margin-top: 14px;
383
+ padding-top: 12px;
384
+ background-color: transparent;
385
+ font-size: 13px;
386
+ }
387
+
388
+ QGroupBox::title {
389
+ subcontrol-origin: margin;
390
+ left: 12px;
391
+ padding: 0 8px;
392
+ color: #808080;
393
+ }
394
+
395
+ /* ========== Splitter ========== */
396
+ QSplitter::handle {
397
+ background-color: #2a2a2a;
398
+ }
399
+
400
+ QSplitter::handle:horizontal {
401
+ width: 1px;
402
+ }
403
+
404
+ QSplitter::handle:vertical {
405
+ height: 1px;
406
+ }
407
+
408
+ /* ========== Status Indicator ========== */
409
+ #status-indicator {
410
+ background-color: #0d0d0d;
411
+ border: 1px solid #2a2a2a;
412
+ border-radius: 8px;
413
+ padding: 20px;
414
+ }
415
+
416
+ #status-dot {
417
+ font-size: 28px;
418
+ }
419
+
420
+ #status-text {
421
+ font-size: 16px;
422
+ font-weight: 500;
423
+ }
424
+
425
+ #status-details {
426
+ font-size: 13px;
427
+ color: #808080;
428
+ }
429
+
430
+ /* ========== Tooltips ========== */
431
+ QToolTip {
432
+ background-color: #0d0d0d;
433
+ border: 1px solid #2a2a2a;
434
+ border-radius: 6px;
435
+ color: #d4d4d4;
436
+ padding: 8px 12px;
437
+ font-size: 12px;
438
+ }
439
+
440
+ /* ========== Menu ========== */
441
+ QMenu {
442
+ background-color: #0d0d0d;
443
+ border: 1px solid #2a2a2a;
444
+ border-radius: 6px;
445
+ padding: 6px;
446
+ }
447
+
448
+ QMenu::item {
449
+ padding: 8px 24px;
450
+ border-radius: 4px;
451
+ }
452
+
453
+ QMenu::item:selected {
454
+ background-color: #264f78;
455
+ }
456
+
457
+ /* ========== Tab Widget ========== */
458
+ QTabWidget::pane {
459
+ border: 1px solid #2a2a2a;
460
+ border-radius: 6px;
461
+ background-color: #0d0d0d;
462
+ }
463
+
464
+ QTabBar::tab {
465
+ background-color: #1a1a1a;
466
+ border: 1px solid #2a2a2a;
467
+ border-bottom: none;
468
+ border-top-left-radius: 6px;
469
+ border-top-right-radius: 6px;
470
+ padding: 10px 20px;
471
+ color: #808080;
472
+ margin-right: 2px;
473
+ font-size: 13px;
474
+ }
475
+
476
+ QTabBar::tab:selected {
477
+ background-color: #0d0d0d;
478
+ color: #d4d4d4;
479
+ }
480
+
481
+ QTabBar::tab:hover:!selected {
482
+ background-color: #2a2a2a;
483
+ }
484
+
485
+ /* ========== Progress Bar ========== */
486
+ QProgressBar {
487
+ background-color: #2a2a2a;
488
+ border: none;
489
+ border-radius: 6px;
490
+ height: 10px;
491
+ text-align: center;
492
+ }
493
+
494
+ QProgressBar::chunk {
495
+ background-color: #4ec9b0;
496
+ border-radius: 6px;
497
+ }
498
+
499
+ /* ========== Frame Sections ========== */
500
+ QFrame.section {
501
+ background-color: #0d0d0d;
502
+ border: 1px solid #2a2a2a;
503
+ border-radius: 8px;
504
+ }
@@ -0,0 +1,15 @@
1
+ """Utility modules for Meeting Noter GUI."""
2
+
3
+ from meeting_noter.gui.utils.signals import AppState
4
+ from meeting_noter.gui.utils.workers import (
5
+ LiveTranscriptWatcher,
6
+ StatusPollingWorker,
7
+ TranscriptionWorker,
8
+ )
9
+
10
+ __all__ = [
11
+ "AppState",
12
+ "StatusPollingWorker",
13
+ "LiveTranscriptWatcher",
14
+ "TranscriptionWorker",
15
+ ]
@@ -0,0 +1,82 @@
1
+ """Application state and signals for Meeting Noter GUI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from PySide6.QtCore import QObject, Signal
6
+
7
+
8
+ class AppState(QObject):
9
+ """Central application state with Qt signals."""
10
+
11
+ # Recording state signals
12
+ recording_started = Signal(str) # meeting_name
13
+ recording_stopped = Signal(str) # filepath
14
+ recording_status_changed = Signal(bool, str) # is_recording, meeting_name
15
+
16
+ # Watcher state signals
17
+ watcher_status_changed = Signal(bool) # is_running
18
+
19
+ # Live transcription signals
20
+ live_transcript_updated = Signal(str) # new_text
21
+
22
+ # Config change signals
23
+ config_changed = Signal()
24
+
25
+ # Navigation signals
26
+ navigate_to = Signal(str) # screen_name
27
+ open_transcript = Signal(str) # filepath
28
+
29
+ # Notification signals
30
+ show_notification = Signal(str, str) # title, message
31
+
32
+ def __init__(self):
33
+ super().__init__()
34
+ self._is_recording = False
35
+ self._current_meeting = ""
36
+ self._watcher_running = False
37
+
38
+ @property
39
+ def is_recording(self) -> bool:
40
+ """Get current recording state."""
41
+ return self._is_recording
42
+
43
+ @is_recording.setter
44
+ def is_recording(self, value: bool) -> None:
45
+ """Set recording state and emit signal."""
46
+ if self._is_recording != value:
47
+ self._is_recording = value
48
+ self.recording_status_changed.emit(value, self._current_meeting)
49
+
50
+ @property
51
+ def current_meeting(self) -> str:
52
+ """Get current meeting name."""
53
+ return self._current_meeting
54
+
55
+ @current_meeting.setter
56
+ def current_meeting(self, value: str) -> None:
57
+ """Set current meeting name."""
58
+ self._current_meeting = value
59
+
60
+ @property
61
+ def watcher_running(self) -> bool:
62
+ """Get watcher state."""
63
+ return self._watcher_running
64
+
65
+ @watcher_running.setter
66
+ def watcher_running(self, value: bool) -> None:
67
+ """Set watcher state and emit signal."""
68
+ if self._watcher_running != value:
69
+ self._watcher_running = value
70
+ self.watcher_status_changed.emit(value)
71
+
72
+
73
+ # Global app state instance
74
+ _app_state: AppState | None = None
75
+
76
+
77
+ def get_app_state() -> AppState:
78
+ """Get the global app state instance."""
79
+ global _app_state
80
+ if _app_state is None:
81
+ _app_state = AppState()
82
+ return _app_state