linux observer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Cross-DE tray polish: plain-text tooltips, GNOME install docs, menu tweak

- Strip HTML from tooltips — use plain text for KDE/GNOME compatibility
- INSTALL.md: add GNOME AppIndicator extension instructions (step 6)
with distro-specific install commands and verification steps
- Move "open journal" to top level above settings/about submenus
- Update activity detection note (works on KDE too now)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+35 -15
+23 -3
INSTALL.md
··· 71 71 solstone-linux install-service 72 72 ``` 73 73 74 - the system tray indicator appears automatically when the observer starts on a graphical session with a StatusNotifierWatcher (KDE Plasma, GNOME with AppIndicator extension). no separate install step needed. 74 + the system tray icon appears automatically when the observer starts in a graphical session. on KDE Plasma this works out of the box. on GNOME, the AppIndicator extension is required — see step 6. 75 + 76 + 6. **GNOME only:** install the AppIndicator extension for tray icon support. KDE users can skip this. 77 + 78 + GNOME removed native system tray support. the AppIndicator extension restores it via the same StatusNotifierItem protocol KDE uses. without it, the observer runs fine but has no tray icon. 79 + 80 + **ubuntu:** already installed and enabled by default — skip this step. 75 81 76 - 6. verify it's running and connected: 82 + **fedora:** 83 + ``` 84 + sudo dnf install gnome-shell-extension-appindicator 85 + ``` 86 + then log out and back in, or restart GNOME Shell (Alt+F2, type `r`, enter). enable the extension in GNOME Extensions app if not auto-enabled. 87 + 88 + **arch:** 89 + ``` 90 + sudo pacman -S gnome-shell-extension-appindicator 91 + ``` 92 + 93 + to check if it's working: `gnome-extensions list | grep appindicator` should show it. if the tray icon still doesn't appear, verify it's enabled: `gnome-extensions enable appindicatorsupport@rgcjonas.gmail.com` 94 + 95 + 7. verify it's running and connected: 77 96 ``` 78 97 systemctl --user status solstone-linux 79 98 sol remote list ··· 81 100 82 101 ## notes 83 102 84 - - activity detection (idle timeout, screen lock, power save) requires a GNOME desktop. other desktops capture screen and audio fine but won't get activity-based segment boundaries. 103 + - activity detection (idle timeout, screen lock, power save) works on both GNOME and KDE. other desktops capture screen and audio fine but may not get activity-based segment boundaries. 85 104 - if pipx is not installed: `pip install --user pipx` or install via your package manager. 105 + - the tray icon uses the StatusNotifierItem (SNI) D-Bus protocol. it works on KDE natively and GNOME with the AppIndicator extension. if no SNI host is available, the observer runs normally without a tray icon.
+1 -1
src/solstone_linux/dbusmenu.py
··· 188 188 189 189 @method() 190 190 def AboutToShow(self, item_id: "i") -> "b": 191 - return False # no layout update needed 191 + return True # tell host to re-read layout (fresh labels on open) 192 192 193 193 @method() 194 194 def AboutToShowGroup(self, ids: "ai") -> "aiai":
+9 -9
src/solstone_linux/tray.py
··· 268 268 children_display="submenu", 269 269 ) 270 270 settings_submenu.children = [ 271 - open_journal, 272 271 settings_open_config, 273 272 settings_copy_agent, 274 273 ] ··· 322 321 self._pause_submenu, 323 322 self._resume_item, 324 323 separator(), 324 + open_journal, 325 325 settings_submenu, 326 326 about_submenu, 327 327 separator(), ··· 439 439 self._resume_item.label = new_resume 440 440 441 441 def _build_tooltip(self) -> str: 442 - """Build rich tooltip body (HTML on KDE).""" 442 + """Build plain-text tooltip body (cross-DE compatible).""" 443 443 parts = [] 444 444 445 - status_html = { 446 - "recording": "<b>observing</b>", 447 - "paused": "<b>paused</b>", 445 + status_labels = { 446 + "recording": "observing", 447 + "paused": "paused", 448 448 "idle": "idle (screen inactive)", 449 - "stopped": "<font color='#cc3333'>not running</font>", 449 + "stopped": "not running", 450 450 } 451 - parts.append(status_html.get(self.status, self.status)) 451 + parts.append(status_labels.get(self.status, self.status)) 452 452 453 453 if self.sync_status == "synced": 454 454 parts.append("all segments synced") ··· 458 458 parts.append(f"sync: {self.sync_status}") 459 459 460 460 if self.error: 461 - parts.append(f"<font color='#cc3333'>{self.error}</font>") 461 + parts.append(self.error) 462 462 463 - return "<br>".join(parts) 463 + return "\n".join(parts) 464 464 465 465 # ── Menu callbacks ── 466 466
+2 -2
tests/test_tray.py
··· 55 55 assert len(app._pause_submenu.children) == 4 56 56 assert app._resume_item.visible is False 57 57 assert app.menu._root.children[1].item_type == separator().item_type 58 - assert len(app.menu._root.children) == 9 58 + assert len(app.menu._root.children) == 10 59 59 60 60 61 61 class TestUpdateStatus: ··· 169 169 170 170 tooltip = app._build_tooltip() 171 171 172 - assert "<b>observing</b>" in tooltip 172 + assert "observing" in tooltip 173 173 assert "all segments synced" in tooltip 174 174 175 175 def test_build_tooltip_stopped(self):