From 321adebfe60c7dee56e34393118dfcc563b56013 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 26 May 2026 17:54:04 +0000 Subject: [PATCH] fix(tor): clear remembered-approval window on user TorType toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once the user picked "Use regular connection" after a 60s stuck-Connecting prompt, `lastBypassApprovalMs` was persisted to DataStore for an hour. Inside that window the connection-failure flow silently flipped `sessionBypass = true` on every later Connecting span instead of re-prompting, which caused the status flow to call `service.stop()` and emit `Off` regardless of the user's `TorType`. The DataStore-backed approval survived force-stop, and toggling Tor off/on only cleared the in-memory `sessionBypass` half — so the next bootstrap attempt re-triggered the silent bypass after 60s and the user was trapped until wiping app data. Any user-initiated `TorType` change now wipes both halves: the in-memory `sessionBypass` flag and the persisted approval. The next stuck-Connecting span will surface the dialog again so the user has a real choice instead of a silent fall-back to direct. --- .../vitorpamplona/amethyst/ui/tor/TorManager.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt index ade8fa2213..1b32e28241 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt @@ -74,12 +74,19 @@ class TorManager( lastBypassApprovalMs = torPrefs.loadLastBypassApprovalMs() } - // Any user-initiated change to torType clears the in-memory bypass so the - // explicit user action wins over the implicit override. + // Any user-initiated change to torType clears the in-memory bypass AND the + // remembered-approval window. Otherwise a single past "Use regular connection" + // traps the user in a silent-bypass loop: every Connecting span >60s + // auto-flips sessionBypass without showing the dialog, force-stop preserves + // the DataStore-backed approval, and toggling Tor off/on only clears the + // in-memory half — so wiping app data becomes the only recovery path. torPrefs.value.torType .drop(1) - .onEach { sessionBypass.value = false } - .launchIn(scope) + .onEach { + sessionBypass.value = false + lastBypassApprovalMs = 0L + torPrefs.saveLastBypassApprovalMs(0L) + }.launchIn(scope) } @OptIn(ExperimentalCoroutinesApi::class)