Commit Graph
20181 Commits
Author SHA1 Message Date
DenozordecandClaude Opus 5.5 66688031cd android: small cleanups - DB close in finally, single profile reload
- HomeViewModel closes the profile database in finally blocks and relies
  on the VPN_PROFILES_CHANGED broadcast instead of reloading twice
- READ_EXTERNAL_STORAGE only up to API 32; drop a dead settings flag

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:20:28 +07:00
DenozordecandClaude Opus 5.5 7abac87140 android: run DNS/route diagnostics on their own executor
They can block for 10-30 s on a degraded network and delayed any profile
load (connect, retry, profile switch) queued behind them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:20:28 +07:00
DenozordecandClaude Opus 5.5 1b4fdc83d8 android: tile/widget/log fixes
- tile: query the configured profile once per listening session instead
  of on every state notification
- widget: DISCONNECTING is shown as such, with a Disconnect button
- log viewer: bounded to 5000 lines, tails only while visible, picks up
  a log created or restarted after opening, and no longer yanks the user
  back to the bottom while they scroll up

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:19:33 +07:00
DenozordecandClaude Opus 5.5 ce80c36be1 android: routing - package scans off the main thread, no needless reconnects
- computeExcludedPackages() (full PackageManager scan) runs on Default,
  not Main.immediate, on config changes and package add/remove
- updateConfig() ignores no-op transforms and reconnects when routing is
  switched off too (direct apps kept bypassing the tunnel until then)
- config is volatile and read after its version, so an old config can no
  longer be cached under a new version
- Direct apps loads the app list once per entry, without GET_META_DATA

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:19:33 +07:00
DenozordecandClaude Opus 5.5 07fb02790c android: CharonVpnService - handover race, cheaper network/notification updates
- underlying-network bookkeeping is guarded by one lock and re-applied
  after establish(), so a handover racing with it no longer leaves the
  tunnel attributed to a lost network
- use the capabilities passed to onCapabilitiesChanged (no IPC per
  signal-strength update); mCurrentProfile is volatile
- countdown-only notification re-posts are limited to one per 5 s
- the connected chronometer keeps its start time across re-posts

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:17:36 +07:00
DenozordecandClaude Opus 5.5 b0f353af90 android: whitelist - working recheck backoff, fewer probe rounds
- scheduled rechecks are forced: the 15/30 s steps were below FRESH_MS,
  so the unforced recheck returned early and the backoff chain died
- signal-strength-only capability changes are no longer network events
  (each one reset the backoff and launched a check)
- tunnel state transitions force a new round at most every 15 s

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:17:36 +07:00
DenozordecandClaude Opus 5.5 514b15b1ca android: home/routing UI - poll only while visible, no idle animation
- traffic (1 s) and probe (10 s) loops run only while the Home screen is
  shown and the VPN is connected; no 1 s idle tick otherwise
- the refresh button no longer runs a second exit-IP trace
- the glow pulse is not composed at all while disconnected or with
  animations off (it redrew a transparent circle every frame)
- RTT sparkline appends each probe result once (it duplicated stale ones)
- Routing dead-host poll is lifecycle-aware

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:15:10 +07:00
DenozordecandClaude Opus 5.5 5f8b813eb4 android: updates - honour the charging constraint, real metered check
- drop the in-process 12 h loop: the VPN keeps the process alive, so it
  checked and pre-downloaded on battery, defeating the worker constraint
- the worker now waits for the check and a silent download it starts
- metered is judged by the physical network: the VPN reports itself
  unmetered, so pre-downloads ran over cellular while connected

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:15:10 +07:00
DenozordecandClaude Opus 5.5 6668dcfb56 android: health check - ping the server only when it can matter
- WITH_TUNNEL mode pings the server only once the external targets fail
  (no ping fork + DNS lookup outside the tunnel on every healthy cycle;
  an ICMP-blocking server no longer forces fast polls)
- initial battery-low state from the sticky ACTION_BATTERY_CHANGED
- non-state notifications no longer restart a pending cycle

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:12:22 +07:00
DenozordecandClaude Opus 5.5 1eb1dfe317 android: RU list - no reconnect for an unchanged list, failure backoff
- same SHA-256 as the applied list: only bump the timestamp, no parse,
  save or tunnel reconnect (it tore a healthy tunnel down daily)
- a failed download is not retried on every cold start (3 h backoff)
- the saved list is read and parsed off the main thread at startup
- switching the split off in system mode reconnects to drop the routes

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:12:22 +07:00
DenozordecandClaude Opus 5.5 cf89cec20e android: watchdog backs off whenever a live process owns recovery
Retrying, connecting or whitelist-blocked sessions kept the 60 s alarm and
the 10 min Doze wakeup for hours although a live process makes the alarm
useless. They now share the connected backoff (5 min / 60 min).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:12:22 +07:00
DenozordecandClaude Opus 5.5 24e536b9b9 android: updates - no stuck Downloading state, thread-safe singleton
After a silent pre-download the state stayed Downloading, so tapping the
"update ready" notification did nothing. It now returns to Available;
an install request without a known update (e.g. after a process restart)
re-checks and installs when found.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:09:40 +07:00
DenozordecandClaude Opus 5.5 e6c893219c android: DiagLog thread-safe timestamps; auto-connect survives stop/start
- SimpleDateFormat is now used under the lock; rotation counts bytes
- AutoConnectManager.stop() clears pendingEvaluate, whose reset runnable
  it removes, so later connects are not silently swallowed

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:09:40 +07:00
DenozordecandClaude Opus 5.5 01c398f2f7 android: tile/control activity - no bind leaks, no callbacks after destroy
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:09:40 +07:00
DenozordecandClaude Opus 5.5 f2e4ffe860 android: VpnStateService - single retry countdown, isolated listeners
- remove pending RETRY_MSG on reset/set: a Retry tap during a backoff
  started a second countdown chain (double-speed ticks, two reconnects)
- notify listeners over a copy with per-listener error handling
- disconnect() tolerates the VPN service not running

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:09:40 +07:00
DenozordecandClaude Opus 5.5 358dcb94b2 android: CharonVpnService - safer foreground and teardown handling
- DISCONNECT (plain startService) no longer promotes to the foreground,
  and startForeground() refusals on Android 12+ are logged, not fatal
- drop the placeholder notification when nothing was running, so the
  service does not stay in the foreground with a stale Disabled state
- onDestroy: shutdownNow/await the profile executor before closing the
  database; profile loads catch errors instead of killing the process
- unbind by bind result, not by mService (binding leaked if destroyed
  before onServiceConnected)
- the connection thread's crash guard can no longer throw itself

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:09:39 +07:00
DenozordecandClaude Opus 5.5 2b40eebf5b android: close TCP probe sockets right after connecting
tcpPing never closed its socket: every health/whitelist/home probe leaked
an fd until GC and the peer's later FIN/RST woke the radio again.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:09:39 +07:00
DenozordecandClaude Opus 5.5 793ca1b410 android: native - hold charon_mutex while reading routing engine stats
getRoutingStats/getDeadDirectTargets are polled from the UI once a second;
a concurrent disconnect frees the engine under charon_mutex, so reading it
without the lock was a use-after-free.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:05:09 +07:00
DenozordecandClaude Opus 5.5 5e38fc2f76 android: keep the BETA badge on one line on narrow mode cards
Android / pre-check (push) Failing after 5s
Android / android (push) Skipped
CIFuzz / pre-check (push) Failing after 4s
CIFuzz / fuzzing (address) (push) Skipped
CIFuzz / fuzzing (undefined) (push) Skipped
CodeQL / pre-check (push) Failing after 4s
CodeQL / analyze (python) (push) Skipped
CodeQL / analyze (ruby) (push) Skipped
CodeQL / analyze-cpp (push) Skipped
FreeBSD / pre-check (push) Failing after 3s
FreeBSD / freebsd (14.4) (push) Skipped
FreeBSD / freebsd (15.0) (push) Skipped
Linux / pre-check (push) Failing after 4s
Linux / latest (apidoc) (push) Skipped
Linux / latest (clang, no, all) (push) Skipped
Linux / latest (clang, no, default) (push) Skipped
Linux / latest (clang, no, printf-builtin) (push) Skipped
Linux / latest (clang, no-dbg) (push) Skipped
Linux / latest (clang, no-testable-ke) (push) Skipped
Linux / latest (clang, yes, all) (push) Skipped
Linux / latest (clang, yes, default) (push) Skipped
Linux / latest (clang, yes, fuzzing) (push) Skipped
Linux / latest (coverage) (push) Skipped
Linux / latest (dist) (push) Skipped
Linux / latest (gcc, no, all) (push) Skipped
Linux / latest (gcc, no, default) (push) Skipped
Linux / latest (gcc, no, printf-builtin) (push) Skipped
Linux / latest (gcc, yes, all) (push) Skipped
Linux / latest (gcc, yes, default) (push) Skipped
Linux / latest (nm) (push) Skipped
Linux / latest (no-dbg) (push) Skipped
Linux / latest (no-testable-ke) (push) Skipped
Linux / latest (yes, ld) (push) Skipped
Linux / crypto (ubuntu-22.04, openssl-sys) (push) Skipped
Linux / crypto (ubuntu-latest, botan) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-3) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-4) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-awslc) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-sys) (push) Skipped
Linux / crypto (ubuntu-latest, wolfssl) (push) Skipped
Linux / older (clang, ubuntu-22.04, all) (push) Skipped
Linux / older (gcc, ubuntu-22.04, all) (push) Skipped
Linux / older (gcc, ubuntu-22.04, nm) (push) Skipped
Linux / alpine (push) Skipped
macOS / pre-check (push) Failing after 4s
macOS / macos (macos-14) (push) Skipped
macOS / macos (macos-latest) (push) Skipped
SonarCloud / pre-check (push) Failing after 3s
SonarCloud / sonarcloud (push) Skipped
TKM / pre-check (push) Failing after 4s
TKM / tkm (push) Skipped
Windows / pre-check (push) Failing after 3s
Windows / cross-compile (win32) (push) Skipped
Windows / cross-compile (win64) (push) Skipped
Windows / native (i686, mingw32, win32) (push) Skipped
Windows / native (x86_64, mingw64, win64) (push) Skipped
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:55:19 +07:00
DenozordecandClaude Opus 5.5 c23d4dad8b android: 2.16.0 - Routing 2.0: one direct-apps list, inline RU mode, no per-profile app picker
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:48:33 +07:00
DenozordecandClaude Opus 5.5 e2ce8420a7 android: remove per-profile app picker, rule-set UI and SelectedApplicationsActivity
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:48:00 +07:00
DenozordecandClaude Opus 5.5 488c0aa210 android: Routing tab redesign - RU sites card, direct apps screen, advanced pages
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:47:59 +07:00
DenozordecandClaude Opus 5.5 48f1ed7fb8 android: routing 2.0 strings (en/ru/de), drop obsolete rule-set strings
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:47:59 +07:00
DenozordecandClaude Opus 5.5 389712bba3 android: global direct-apps routing model, migration, single-source CharonVpnService excludes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 01:47:58 +07:00
DenozordecandClaude Opus 5.5 584004a25c android: 2.15.1 - fix startup crash: R8 stripped WorkDatabase_Impl constructor
Android / pre-check (push) Failing after 4s
Android / android (push) Skipped
CIFuzz / pre-check (push) Failing after 3s
CIFuzz / fuzzing (address) (push) Skipped
CIFuzz / fuzzing (undefined) (push) Skipped
CodeQL / pre-check (push) Failing after 4s
CodeQL / analyze (python) (push) Skipped
CodeQL / analyze (ruby) (push) Skipped
CodeQL / analyze-cpp (push) Skipped
FreeBSD / pre-check (push) Failing after 3s
FreeBSD / freebsd (14.4) (push) Skipped
FreeBSD / freebsd (15.0) (push) Skipped
Linux / pre-check (push) Failing after 4s
Linux / latest (apidoc) (push) Skipped
Linux / latest (clang, no, all) (push) Skipped
Linux / latest (clang, no, default) (push) Skipped
Linux / latest (clang, no, printf-builtin) (push) Skipped
Linux / latest (clang, no-dbg) (push) Skipped
Linux / latest (clang, no-testable-ke) (push) Skipped
Linux / latest (clang, yes, all) (push) Skipped
Linux / latest (clang, yes, default) (push) Skipped
Linux / latest (clang, yes, fuzzing) (push) Skipped
Linux / latest (coverage) (push) Skipped
Linux / latest (dist) (push) Skipped
Linux / latest (gcc, no, all) (push) Skipped
Linux / latest (gcc, no, default) (push) Skipped
Linux / latest (gcc, no, printf-builtin) (push) Skipped
Linux / latest (gcc, yes, all) (push) Skipped
Linux / latest (gcc, yes, default) (push) Skipped
Linux / latest (nm) (push) Skipped
Linux / latest (no-dbg) (push) Skipped
Linux / latest (no-testable-ke) (push) Skipped
Linux / latest (yes, ld) (push) Skipped
Linux / crypto (ubuntu-22.04, openssl-sys) (push) Skipped
Linux / crypto (ubuntu-latest, botan) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-3) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-4) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-awslc) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-sys) (push) Skipped
Linux / crypto (ubuntu-latest, wolfssl) (push) Skipped
Linux / older (clang, ubuntu-22.04, all) (push) Skipped
Linux / older (gcc, ubuntu-22.04, all) (push) Skipped
Linux / older (gcc, ubuntu-22.04, nm) (push) Skipped
Linux / alpine (push) Skipped
macOS / pre-check (push) Failing after 3s
macOS / macos (macos-14) (push) Skipped
macOS / macos (macos-latest) (push) Skipped
SonarCloud / pre-check (push) Failing after 4s
SonarCloud / sonarcloud (push) Skipped
TKM / pre-check (push) Failing after 3s
TKM / tkm (push) Skipped
Windows / pre-check (push) Failing after 4s
Windows / cross-compile (win32) (push) Skipped
Windows / cross-compile (win64) (push) Skipped
Windows / native (i686, mingw32, win32) (push) Skipped
Windows / native (x86_64, mingw64, win64) (push) Skipped
AGP 9 strict full-mode keep rules no longer keep no-arg constructors of
-keep'd classes, so WorkManager's reflectively created Room database
lost its constructor and the app crashed in InitializationProvider.
Restore AGP 8 keep-rule semantics and keep RoomDatabase constructors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 00:50:59 +07:00
DenozordecandClaude Opus 5.5 6a8528fc98 android: 2.15.0 - Material 3 Expressive redesign
Android / pre-check (push) Failing after 6s
Android / android (push) Skipped
CIFuzz / pre-check (push) Failing after 4s
CIFuzz / fuzzing (address) (push) Skipped
CIFuzz / fuzzing (undefined) (push) Skipped
CodeQL / pre-check (push) Failing after 3s
CodeQL / analyze (python) (push) Skipped
CodeQL / analyze (ruby) (push) Skipped
CodeQL / analyze-cpp (push) Skipped
FreeBSD / pre-check (push) Failing after 4s
FreeBSD / freebsd (14.4) (push) Skipped
FreeBSD / freebsd (15.0) (push) Skipped
Linux / pre-check (push) Failing after 3s
Linux / latest (apidoc) (push) Skipped
Linux / latest (clang, no, all) (push) Skipped
Linux / latest (clang, no, default) (push) Skipped
Linux / latest (clang, no, printf-builtin) (push) Skipped
Linux / latest (clang, no-dbg) (push) Skipped
Linux / latest (clang, no-testable-ke) (push) Skipped
Linux / latest (clang, yes, all) (push) Skipped
Linux / latest (clang, yes, default) (push) Skipped
Linux / latest (clang, yes, fuzzing) (push) Skipped
Linux / latest (coverage) (push) Skipped
Linux / latest (dist) (push) Skipped
Linux / latest (gcc, no, all) (push) Skipped
Linux / latest (gcc, no, default) (push) Skipped
Linux / latest (gcc, no, printf-builtin) (push) Skipped
Linux / latest (gcc, yes, all) (push) Skipped
Linux / latest (gcc, yes, default) (push) Skipped
Linux / latest (nm) (push) Skipped
Linux / latest (no-dbg) (push) Skipped
Linux / latest (no-testable-ke) (push) Skipped
Linux / latest (yes, ld) (push) Skipped
Linux / crypto (ubuntu-22.04, openssl-sys) (push) Skipped
Linux / crypto (ubuntu-latest, botan) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-3) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-4) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-awslc) (push) Skipped
Linux / crypto (ubuntu-latest, openssl-sys) (push) Skipped
Linux / crypto (ubuntu-latest, wolfssl) (push) Skipped
Linux / older (clang, ubuntu-22.04, all) (push) Skipped
Linux / older (gcc, ubuntu-22.04, all) (push) Skipped
Linux / older (gcc, ubuntu-22.04, nm) (push) Skipped
Linux / alpine (push) Skipped
macOS / pre-check (push) Failing after 4s
macOS / macos (macos-14) (push) Skipped
macOS / macos (macos-latest) (push) Skipped
SonarCloud / pre-check (push) Failing after 3s
SonarCloud / sonarcloud (push) Skipped
TKM / pre-check (push) Failing after 3s
TKM / tkm (push) Skipped
Windows / pre-check (push) Failing after 3s
Windows / cross-compile (win32) (push) Skipped
Windows / cross-compile (win64) (push) Skipped
Windows / native (i686, mingw32, win32) (push) Skipped
Windows / native (x86_64, mingw64, win64) (push) Skipped
Toolchain AGP 9.1 / Gradle 9.3 / Kotlin 2.2 / compileSdk 37, minSdk 24,
material3 1.5.0-beta01. Expressive theme and motion, redesigned Connect,
Profiles, Routing and Settings screens, adaptive layouts, home-screen
widget, Live Update download progress, predictive back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 00:38:00 +07:00
Denozordec 8ef7c0a53b docs: ui plan status - deferred items completed 2026-10-10 00:33:20 +07:00
Denozordec dc6e1e32fb android: predictive back scale for settings pages and remediation detail 2026-10-10 00:33:20 +07:00
Denozordec 2681233449 android: route check results as cards with status pills 2026-10-10 00:32:24 +07:00
Denozordec 7a7673119e android: profile import as an Expressive bottom sheet in a transparent host 2026-10-10 00:32:00 +07:00
Denozordec 8deafeae8e android: trusted networks - inline location explainer card 2026-10-10 00:31:32 +07:00
Denozordec 59a31d6a1d android: app picker - hide system apps by default with a toggle 2026-10-10 00:30:41 +07:00
Denozordec 8bedf432e2 android: log screen - level filter chips, snackbar instead of toast 2026-10-10 00:30:27 +07:00
Denozordec 42cd361c58 android: QS tile - connectivity category, toggleable 2026-10-10 00:29:39 +07:00
Denozordec 87c3d73fbc android: update download progress notification (ProgressStyle / Live Update on API 36+) 2026-10-10 00:29:30 +07:00
Denozordec 564b8aaa8d android: profiles list-detail on expanded width with in-pane profile form 2026-10-10 00:28:47 +07:00
Denozordec 7cc6343ba1 android: build.gradle comment cleanup 2026-10-10 00:27:29 +07:00
Denozordec c9048143cc android: minSdk 24 (material3 1.5 requirement), drop overrideLibrary workaround 2026-10-10 00:27:24 +07:00
Denozordec 203a67ee86 android: a11y (headings, switch role), form snackbar, German strings, smoke tests, docs 2026-10-10 00:21:31 +07:00
Denozordec 3c7c121c7d android: expanded width - two-column Connect, 640dp settings 2026-10-10 00:13:51 +07:00
Denozordec 0e5e28b4da android: spacing tokens - migrate padding/spacing literals and ScreenPadding to ShxSpacing 2026-10-10 00:13:08 +07:00
Denozordec 22e4082825 android: home screen widget (Glance), tile subtitle with profile name 2026-10-10 00:13:07 +07:00
Denozordec 0c3ea75cac android: settings as grouped pages (appearance, automation, security, updates, support), theme mode, snackbars instead of toasts 2026-10-10 00:09:45 +07:00
Denozordec a451386e0a android: split RoutingScreen into routing/{RoutingHero,RuleSetList,AdvancedRouting} 2026-10-10 00:09:44 +07:00
Denozordec 8bd65d535e android: routing - advanced block (RU details, GeoIP, force prefixes), kill switch vs excluded apps note 2026-10-10 00:07:12 +07:00
Denozordec c5585df135 android: profiles - swipe to delete with undo, search only for long lists 2026-10-10 00:06:05 +07:00
DenozordecandClaude Opus 5.5 385819caf0 android: redesigned Connect screen - morphing hero, profile chip + picker sheet, traffic tiles, one banner slot, collapsed availability
Split HomeScreen into home/{HeroConnect,TrafficTiles,AvailabilityCard,HomeBanners}.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 00:05:34 +07:00
DenozordecandClaude Opus 5.5 3f7bd94a69 android: expressive motion - fade-through tabs, back to Connect, LoadingIndicator, wavy progress, snackbar messages
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 00:01:17 +07:00
DenozordecandClaude Opus 5.5 6fd03f37f7 android: toolchain AGP 9.1.1 / Gradle 9.3.1 / Kotlin 2.2.21 / compileSdk 37, BOM 2026.09.00 + material3 1.5.0-beta01
Built-in Kotlin (kotlin-android removed), Java 11 compile options (compose 1.12),
proguard-android-optimize.txt (the non-optimize file is rejected by AGP 9),
ExposedDropdownMenu import, minSdk 23 kept via tools:overrideLibrary for
material3 1.5 libs that declare minSdk 24. -PshortNdkCommands for deep worktree paths.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 23:59:09 +07:00
DenozordecandClaude Opus 5.5 65989b3a5a android: shared ui components (SectionCard, ListRow, StatusPill, SnackbarHost)
Replace the duplicate FormSection, ActiveBadge and SnackbarHost call sites.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 23:39:35 +07:00