You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.6 KiB
99 lines
3.6 KiB
"""Per-account notification tabs; signing identity = active tab's pubkey.""" |
|
|
|
from __future__ import annotations |
|
|
|
from PySide6.QtCore import Qt, Signal |
|
from PySide6.QtWidgets import QLabel, QListWidget, QListWidgetItem, QTabWidget, QVBoxLayout, QWidget |
|
|
|
from imwald.core.accounts_store import StoredAccount |
|
from imwald.core.database import Database |
|
from imwald.core.md_render import markdown_plain_summary |
|
|
|
|
|
class NotificationsPage(QWidget): |
|
"""v1: lists DB notifications per recipient; empty until ingest fills rows.""" |
|
|
|
open_event = Signal(str) |
|
signing_pubkey_changed = Signal(str) |
|
|
|
def __init__( |
|
self, db: Database, accounts: list[StoredAccount], parent: QWidget | None = None |
|
) -> None: |
|
super().__init__(parent) |
|
self._db = db |
|
self._accounts = accounts |
|
self._tabs = QTabWidget() |
|
self._tabs.currentChanged.connect(self._on_tab) |
|
self._lists: dict[str, QListWidget] = {} |
|
lay = QVBoxLayout(self) |
|
lay.addWidget(QLabel("Notifications per saved account (signing uses the active tab).")) |
|
lay.addWidget(self._tabs) |
|
self._rebuild_tabs() |
|
|
|
def set_accounts(self, accounts: list[StoredAccount]) -> None: |
|
self._accounts = accounts |
|
self._rebuild_tabs() |
|
|
|
def _rebuild_tabs(self) -> None: |
|
self._tabs.clear() |
|
self._lists.clear() |
|
if not self._accounts: |
|
holder = QWidget() |
|
hl = QVBoxLayout(holder) |
|
hl.addWidget(QLabel("No saved accounts.")) |
|
self._tabs.addTab(holder, "—") |
|
return |
|
for acc in self._accounts: |
|
lw = QListWidget() |
|
lw.itemActivated.connect(self._on_item) |
|
self._lists[acc.pubkey] = lw |
|
label = acc.label or acc.pubkey[:12] + "…" |
|
self._tabs.addTab(lw, label) |
|
self._refresh_list(acc.pubkey) |
|
self._on_tab(self._tabs.currentIndex()) |
|
|
|
def _refresh_list(self, pubkey: str) -> None: |
|
lw = self._lists.get(pubkey) |
|
if not lw: |
|
return |
|
lw.clear() |
|
cur = self._db.conn().execute( |
|
""" |
|
SELECT n.source_event_id, n.kind, n.read, n.created_at, e.content AS content |
|
FROM notifications n |
|
LEFT JOIN events e ON e.id = n.source_event_id AND e.deleted = 0 |
|
WHERE n.recipient_pubkey=? ORDER BY n.created_at DESC LIMIT 200 |
|
""", |
|
(pubkey,), |
|
) |
|
for row in cur: |
|
snippet = markdown_plain_summary(row["content"] or "", max_len=56) if row["content"] else "" |
|
tail = f" — {snippet}" if snippet else "" |
|
title = f"{row['kind']} {row['source_event_id'][:12]}… read={row['read']}{tail}" |
|
it = QListWidgetItem(title) |
|
it.setData(Qt.ItemDataRole.UserRole, row["source_event_id"]) |
|
lw.addItem(it) |
|
if lw.count() == 0: |
|
lw.addItem(QListWidgetItem("(no rows yet — wire mention/reply detection on ingest)")) |
|
|
|
def refresh_all(self) -> None: |
|
for pk in self._lists: |
|
self._refresh_list(pk) |
|
|
|
def _on_tab(self, index: int) -> None: |
|
if index < 0 or not self._accounts: |
|
return |
|
if index >= len(self._accounts): |
|
return |
|
self.signing_pubkey_changed.emit(self._accounts[index].pubkey) |
|
|
|
def _on_item(self, it: QListWidgetItem) -> None: |
|
eid = it.data(Qt.ItemDataRole.UserRole) |
|
if eid: |
|
self.open_event.emit(str(eid)) |
|
|
|
def active_signing_pubkey(self) -> str | None: |
|
idx = self._tabs.currentIndex() |
|
if 0 <= idx < len(self._accounts): |
|
return self._accounts[idx].pubkey |
|
return None
|
|
|