diff --git a/app/icons/bip110.svg b/app/icons/bip110.svg new file mode 100644 index 0000000..4534ad7 --- /dev/null +++ b/app/icons/bip110.svg @@ -0,0 +1 @@ +BIP110 diff --git a/app/icons/bitcoin-core.svg b/app/icons/bitcoin-core.svg new file mode 100644 index 0000000..4296a25 --- /dev/null +++ b/app/icons/bitcoin-core.svg @@ -0,0 +1 @@ + diff --git a/app/sovran_systemsos_hub/application.py b/app/sovran_systemsos_hub/application.py index 4f52e87..e72a840 100644 --- a/app/sovran_systemsos_hub/application.py +++ b/app/sovran_systemsos_hub/application.py @@ -22,7 +22,8 @@ Adw.init() # Category display order and labels CATEGORY_ORDER = [ ("infrastructure", "Infrastructure"), - ("bitcoin", "Bitcoin"), + ("bitcoin-base", "Bitcoin Base"), + ("bitcoin-apps", "Bitcoin Apps"), ("communication", "Communication"), ("apps", "Self-Hosted Apps"), ("nostr", "Nostr"), @@ -57,17 +58,7 @@ class SovranHubWindow(Adw.ApplicationWindow): ) header = Adw.HeaderBar() - - # Show active role in header - role = config.get("role", "server_plus_desktop") - role_label = ROLE_LABELS.get(role, role) - role_tag = Gtk.Label( - label=role_label, - css_classes=["caption", "role-badge"], - ) - header.set_title_widget( - self._build_title_box(role_label) - ) + header.set_title_widget(self._build_title_box()) refresh_btn = Gtk.Button( icon_name="view-refresh-symbolic", @@ -76,7 +67,6 @@ class SovranHubWindow(Adw.ApplicationWindow): refresh_btn.connect("clicked", lambda _b: self._refresh_all()) header.pack_end(refresh_btn) - # Main vertical layout self._main_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=0, @@ -100,7 +90,9 @@ class SovranHubWindow(Adw.ApplicationWindow): if interval and interval > 0: GLib.timeout_add_seconds(interval, self._auto_refresh) - def _build_title_box(self, role_label): + def _build_title_box(self): + role = self._config.get("role", "server_plus_desktop") + role_label = ROLE_LABELS.get(role, role) box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, halign=Gtk.Align.CENTER, @@ -141,7 +133,6 @@ class SovranHubWindow(Adw.ApplicationWindow): ) self._main_box.append(section_label) - # Separator sep = Gtk.Separator( orientation=Gtk.Orientation.HORIZONTAL, margin_start=24, @@ -150,7 +141,6 @@ class SovranHubWindow(Adw.ApplicationWindow): ) self._main_box.append(sep) - # FlowBox for this category flowbox = Gtk.FlowBox( max_children_per_line=4, min_children_per_line=2, @@ -180,7 +170,6 @@ class SovranHubWindow(Adw.ApplicationWindow): self._main_box.append(flowbox) - # Defer first status poll so the window renders immediately GLib.idle_add(self._refresh_all) def _refresh_all(self): diff --git a/modules/core/sovran-hub.nix b/modules/core/sovran-hub.nix index 2980a2e..8902e30 100644 --- a/modules/core/sovran-hub.nix +++ b/modules/core/sovran-hub.nix @@ -3,31 +3,30 @@ let cfg = config.sovran_systemsOS; - # ── Determine Bitcoin implementation label ─────────────────── - bitcoinImplName = - if cfg.features.bitcoin-core then "Bitcoin Core" - else if cfg.features.bip110 then "Bitcoin Knots + BIP110" - else "Bitcoin Knots"; - monitoredServices = # ── Infrastructure (always present) ──────────────────────── [ - { name = "Caddy"; unit = "caddy.service"; type = "system"; icon = "caddy"; enabled = true; category = "infrastructure"; } - { name = "Tor"; unit = "tor.service"; type = "system"; icon = "tor"; enabled = true; category = "infrastructure"; } + { name = "Caddy"; unit = "caddy.service"; type = "system"; icon = "caddy"; enabled = true; category = "infrastructure"; } + { name = "Tor"; unit = "tor.service"; type = "system"; icon = "tor"; enabled = true; category = "infrastructure"; } ] - # ── Bitcoin Ecosystem ────────────────────────────────────── + # ── Bitcoin Base (node implementations) ──────────────────── ++ [ - { name = bitcoinImplName; unit = "bitcoind.service"; type = "system"; icon = "bitcoind"; enabled = cfg.services.bitcoin; category = "bitcoin"; } - { name = "Electrs"; unit = "electrs.service"; type = "system"; icon = "electrs"; enabled = cfg.services.bitcoin; category = "bitcoin"; } - { name = "LND"; unit = "lnd.service"; type = "system"; icon = "lnd"; enabled = cfg.services.bitcoin; category = "bitcoin"; } - { name = "Ride The Lightning"; unit = "rtl.service"; type = "system"; icon = "rtl"; enabled = cfg.services.bitcoin; category = "bitcoin"; } - { name = "BTCPayserver"; unit = "btcpayserver.service"; type = "system"; icon = "btcpayserver"; enabled = cfg.services.bitcoin; category = "bitcoin"; } - { name = "Mempool"; unit = "mempool.service"; type = "system"; icon = "mempool"; enabled = cfg.features.mempool; category = "bitcoin"; } + { name = "Bitcoin Knots"; unit = "bitcoind.service"; type = "system"; icon = "bitcoind"; enabled = cfg.services.bitcoin && !cfg.features.bitcoin-core && !cfg.features.bip110; category = "bitcoin-base"; } + { name = "Bitcoin Core"; unit = "bitcoind.service"; type = "system"; icon = "bitcoin-core"; enabled = cfg.features.bitcoin-core; category = "bitcoin-base"; } + { name = "Bitcoin Knots + BIP110"; unit = "bitcoind.service"; type = "system"; icon = "bip110"; enabled = cfg.features.bip110; category = "bitcoin-base"; } + ] + # ── Bitcoin Apps (services on top of the node) ───────────── + ++ [ + { name = "Electrs"; unit = "electrs.service"; type = "system"; icon = "electrs"; enabled = cfg.services.bitcoin; category = "bitcoin-apps"; } + { name = "LND"; unit = "lnd.service"; type = "system"; icon = "lnd"; enabled = cfg.services.bitcoin; category = "bitcoin-apps"; } + { name = "Ride The Lightning"; unit = "rtl.service"; type = "system"; icon = "rtl"; enabled = cfg.services.bitcoin; category = "bitcoin-apps"; } + { name = "BTCPayserver"; unit = "btcpayserver.service"; type = "system"; icon = "btcpayserver"; enabled = cfg.services.bitcoin; category = "bitcoin-apps"; } + { name = "Mempool"; unit = "mempool.service"; type = "system"; icon = "mempool"; enabled = cfg.features.mempool; category = "bitcoin-apps"; } ] # ── Communication ────────────────────────────────────────── ++ [ - { name = "Matrix-Synapse"; unit = "matrix-synapse.service"; type = "system"; icon = "synapse"; enabled = cfg.services.synapse; category = "communication"; } - { name = "Element-Call"; unit = "livekit.service"; type = "system"; icon = "livekit"; enabled = cfg.features.element-calling; category = "communication"; } + { name = "Matrix-Synapse"; unit = "matrix-synapse.service"; type = "system"; icon = "synapse"; enabled = cfg.services.synapse; category = "communication"; } + { name = "Element-Call"; unit = "livekit.service"; type = "system"; icon = "livekit"; enabled = cfg.features.element-calling; category = "communication"; } ] # ── Self-Hosted Apps ─────────────────────────────────────── ++ [ @@ -40,7 +39,6 @@ let { name = "Haven Relay"; unit = "haven-relay.service"; type = "system"; icon = "haven"; enabled = cfg.features.haven; category = "nostr"; } ]; - # ── Determine active role name ─────────────────────────────── activeRole = if cfg.roles.desktop then "desktop" else if cfg.roles.node then "node"