Skip to content

Network name header, notifications, ping controls, and resource search - #2

Merged
urhend merged 15 commits into
mainfrom
production
Aug 1, 2026
Merged

urhend merged 15 commits into
mainfrom
production

Conversation

@urhend

@urhend urhend commented Jul 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Dropdown header: logo replaced with the account's network name (from twingate account list), bold when connected, next to the status dot
  • Native GNOME notifications on real connection state changes (connected/disconnected/error), with an on/off toggle in preferences — respects GNOME's own Do Not Disturb setting automatically
  • Status polling slows down while the dropdown is closed, refreshes immediately on open
  • Ping interval is now independent of the status poll interval, with its own toggle and interval setting
  • Resource list gets a magnifier-triggered search/filter (name + address), backed by a persisted ping-status map so filtering doesn't reset dots back to gray

Test plan

  • gnome-extensions disable/enable cycle after each change — Stan: ACTIVE, no journal errors
  • Preferences window opens cleanly with all new rows (notifications, ping enable/interval)
  • Search toggle shows/hides the entry, clears filter on close, auto-collapses when the dropdown menu closes
  • Icon colors (gear vs. magnifier) consistent via shared .twingate-header-icon class

urhend added 15 commits July 30, 2026 18:23
Reads the account's network name (e.g. "urhNET") from
`twingate account list`, which works even while disconnected. Fetched
once at startup and cached; the label stays hidden until resolved.
Logo now sits alone in its own row; the network name and connection
status dot share a second row underneath, side by side.
…eader

- Poll less frequently while the dropdown is closed, refresh immediately
  on open (BACKGROUND_POLL_MULTIPLIER).
- Ping interval is now independent of the status poll interval, with its
  own GSettings key and an on/off toggle (schema + prefs.js updated).
- Dropdown header: logo image replaced with the account's network name
  (from `twingate account list`), bold when connected, next to the
  status dot. The "Connected" switch label stays plain text.
- Add .gitignore (currently just TODO.md, a local-only brainstorm file).

The wordmark PNG asset is left in icons/ unused, in case the logo comes
back in a future revision.
Notifies on connected/disconnected/error transitions (Main.notify /
Main.notifyError), never on repeated polls of the same state and never
for the initial state discovered right after startup. Transitional
tokens (connecting/authenticating) are ignored but don't reset the
baseline, so a later real change is still caught. The status dot in
the header stays as the passive at-a-glance indicator.
- Resources header gets a magnifier button (edit-find-symbolic) that
  reveals a compact search entry, filtering by name+address. Persisted
  ping-status map means filtering no longer resets known dots to gray.
  Search auto-collapses and clears when the dropdown menu closes.
- New notifications-enabled GSettings key + prefs.js switch, gating the
  Main.notify/notifyError calls added earlier. GNOME's own Do Not
  Disturb setting (org.gnome.desktop.notifications show-banners) already
  suppresses banners shell-wide regardless of this toggle, so no extra
  DND-detection code was needed.
- Header and search-toggle icons share a new .twingate-header-icon class
  so their color stays consistent regardless of which menu item wraps
  them.
Runs on push/PR to main and production: node --check on extension.js
and prefs.js, JSON validation of metadata.json, and glib-compile-schemas
on the GSettings schema. Gives the CI monitoring panel real status to
show instead of 'unavailable' (the repo had no workflows configured
at all before this).
Add a live GitHub Actions status badge and list .github/workflows/ci.yml
in the project layout tree.
The diagram still showed the removed logo, a fixed 5s poll interval, and
had no mention of the resource search toggle or notifications. Updated
to reflect: network name replacing the logo, menu-aware polling with
backoff, the independent ping interval/toggle, and notification
behavior on real state changes.
- Real network name example replaced with generic 'network-name'
- 'under the logo' wording was stale (logo was replaced with the network
  name itself)
- Added rows for resource search and connection notifications, both
  missing from this table despite being shipped earlier
- Configuration table was missing 3 of 6 real GSettings keys
  (notifications-enabled, ping-enabled, ping-interval-seconds)
- 'opposite the Twingate logo' no longer applies — the logo was
  replaced with the network name in an earlier revision
- Project layout comment for twingate-wordmark.png still claimed it's
  shown in the dropdown header; it's actually unused, kept only in
  case the logo comes back later
…address

Addresses reviewer feedback on the v3 submission:
- Removed the sudo fallback entirely; privileged actions now always go
  through pkexec (EGO review guidelines disallow sudo outright)
- The binary path for start/stop is now a hardcoded constant
  (PRIVILEGED_TWINGATE_BIN), independent of the user-configurable
  twingate-binary setting — GSettings is user-writable, so it must never
  drive a privileged subprocess's argv
- _runPrivileged(action) split into separate _runStart()/_runStop()
  methods with fully literal argv at the call site, so nothing about the
  privileged command is built from a parameter
- Added VALID_ADDRESS_RE validation when parsing twingate resources
  output, before any address reaches the ping subprocess — closes a
  real argument-injection angle (a leading '-' could otherwise be read
  as a ping flag) and makes the data flow easy to trace
- Removed the now-pointless use-pkexec setting (schema + prefs.js UI)
  since pkexec is no longer optional
- Rewrote code comments in a more natural, human voice — shorter, less
  formal, dropped the ASCII-art section banners
- README updated to match: Configuration table, Known limitations
- Hardcode TWINGATE_BIN for all calls, not just the privileged ones.
  The setting only ever covered status/resources/account (read-only),
  while start/stop was already fixed — that asymmetry meant changing
  the path would silently break connect/disconnect while looking like
  it worked for everything else. Every official Twingate installer
  puts the binary at /usr/bin/twingate anyway, so the config knob
  bought little and confused more.
- Removed the setting from the schema and prefs.js UI accordingly.
- Dropped e.matches?.() and _onOpenPreferences?.() — both are
  guaranteed non-null at the call site, so the optional chaining was
  just noise (per EGO's extension best-practices guide, and matching
  the reviewer's literal '?.(' comment on the v3 submission). Left
  this._indicator?.destroy() in disable() alone — that one really can
  be null if enable() didn't complete.
- README updated to match (Configuration table, Known limitations).
If a subprocess call is still mid-flight when the extension gets
disabled, cancel() only stops what's actually in flight — a call whose
GTask already finished but hasn't been dispatched yet ignores it and
resumes anyway, right after destroy() has torn the actors down. Adds a
_destroyed flag set first thing in destroy(), checked after every
await/then that touches an actor, GSettings, or schedules a new timer.

Also makes runCommand() rethrow CANCELLED from proc.init() the same
way it already does from communicate_utf8_async() — previously a
cancelled spawn was reported back as a normal failure.

Couldn't reproduce the original rejection under repeated
disable/enable cycling (turns out disable/enable doesn't reload the
module in a live session, so those cycles were re-running old code
the whole time) — this is a hardening pass based on the actual
GTask/mainloop mechanics, not a confirmed-then-fixed repro.
Previously an empty resource list looked identical whether you were
disconnected or just had nothing authorized — the Resources section
and its header simply vanished either way. Now it stays up and shows
"No resources available" when _connected is true but the list is
empty, so a genuinely-empty account doesn't look indistinguishable
from being logged out.
Keeping only the license header. The reasoning they carried lives in
a local, gitignored WYJASNIENIE.md instead, so it's still around for
reference without shipping as inline commentary.
@urhend
urhend merged commit f6cae62 into main Aug 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant