fix(tor): clear remembered-approval window on user TorType toggle

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.
This commit is contained in:
Claude
2026-05-26 17:54:04 +00:00
parent b258028b54
commit 321adebfe6
@@ -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)