How to Trigger the Emergency Wipe Feature in BitChat
BitChat's emergency wipe (panic wipe) can be triggered either by triple-tapping the "bitchat/" logo in the app header or by tapping the panic wipe button in Settings, both of which invoke AppChromeModel.panicClearAllData() to permanently erase all local data, keys, and identity.
BitChat is a privacy-focused messaging application developed by the open-source permissionlesstech/bitchat repository. The emergency wipe feature provides an instantaneous method to destroy all local cryptographic material, conversation history, and identity metadata. This mechanism ensures users can purge sensitive data immediately when facing device compromise or seizure scenarios.
Two Ways to Trigger the Emergency Wipe
BitChat offers dual entry points to accommodate both stealth and explicit access patterns.
Triple-Tap the Logo (Hidden Gesture)
The primary stealth trigger resides in bitchat/Views/ContentHeaderView.swift (lines 53-55). The logo Text view registers a triple-tap gesture that immediately delegates to the panic wipe system.
// Inside ContentHeaderView.swift
Text(verbatim: "bitchat/")
.onTapGesture(count: 3) {
// Triple‑tap initiates the panic wipe
appChromeModel.panicClearAllData()
}
This hidden gesture allows users to initiate a wipe discreetly without navigating through menus, which is critical during high-risk scenarios where screen visibility may be compromised.
Panic Wipe Button in Settings
For users who prefer explicit controls, AppInfoView.swift exposes a destructive button labeled "panic wipe" within the Settings screen. This button invokes appChromeModel.panicClearAllData(), guaranteeing identical behavior to the triple-tap method while providing a discoverable, traditional UI element.
The Execution Chain: From UI to Data Destruction
When either trigger activates, the wipe request flows through a strict delegation hierarchy to ensure proper cleanup sequencing.
AppChromeModel Bridge Layer
In bitchat/App/AppChromeModel.swift (lines 14-18), the panicClearAllData() method serves as the bridge between UI actions and the underlying data layer. This method executes three critical steps:
- Optional pre-wipe preparation via a
prepareForPanicclosure set by the UI - UI-level hook execution through
onPanicWipe()to clear share-extension data - Delegation to the view-model via
chatViewModel.panicClearAllData()
ChatViewModel Implementation
The actual erasure logic lives in bitchat/ViewModels/ChatViewModel.swift (lines 48-55) within the panicClearAllData(restartServices: Bool = true) method. Marked with @MainActor and @discardableResult, this method performs surgical cleanup:
// Inside ChatViewModel.swift
@MainActor
@discardableResult
func panicClearAllData(restartServices: Bool = true) -> Bool {
panicRecoveryBlocked = true
isPanicResetting = true
defer { isPanicResetting = false }
// Stop services before any data is removed
panicNetworkLifecycle.stop()
// Begin a durable recovery intent
let recoveryIntent = panicRecoveryOperations.begin()
// Suspend mesh transport, reset media pipelines, etc.
if let panicTransport = meshService as? PanicResettingTransport {
panicTransport.suspendForPanicReset()
} else {
meshService.emergencyDisconnectAll()
}
// … (many cleanup steps – see full source for details) …
// Optionally restart services after the wipe
if restartServices {
panicNetworkLifecycle.restart()
}
return true
}
The method stops network and location services immediately, begins a durable recovery intent, suspends the mesh transport, cancels media preparation, clears conversation stores, deletes all Keychain data, removes identity-related UserDefaults, wipes location state, resets nicknames, clears peer-identity stores, and removes Nostr-related state.
Programmatic Triggering for Development
Developers can invoke the emergency wipe directly for testing purposes by accessing the AppChromeModel from any SwiftUI view:
import SwiftUI
struct DebugPanel: View {
@EnvironmentObject private var appChromeModel: AppChromeModel
var body: some View {
Button("🚨 Emergency wipe") {
// Explicitly trigger the wipe
appChromeModel.panicClearAllData()
}
.foregroundColor(.red)
}
}
This enables automated testing of recovery mechanisms and verification that the panicRecoveryBlocked and isPanicResetting flags properly prevent race conditions.
Critical Implementation Safeguards
The wipe process includes multiple safety mechanisms to ensure reliable execution. The panicRecoveryBlocked and isPanicResetting boolean flags guard against concurrent wipe attempts while the operation proceeds. A defer block guarantees that isPanicResetting returns to false even if an error occurs during the wipe sequence, preventing the application from entering a permanently locked state.
Key Source Files
bitchat/Views/ContentHeaderView.swift– Hosts the triple-tap gesture recognizer on the logobitchat/Views/AppInfoView.swift– Contains the explicit panic wipe button in Settingsbitchat/App/AppChromeModel.swift– Bridges UI actions to the view-model (lines 14-18)bitchat/ViewModels/ChatViewModel.swift– Implements the comprehensive data erasure logic (lines 48-55)
Summary
- Triple-tap the "bitchat/" logo to trigger a stealth emergency wipe via
ContentHeaderView.swift - Use the Settings button for explicit, discoverable activation through
AppInfoView.swift - AppChromeModel acts as the bridge, executing
prepareForPanicandonPanicWipehooks before delegating to the view-model - ChatViewModel.panicClearAllData() performs the actual destruction, stopping services first, then clearing all cryptographic identity and conversation data
- Race condition protection is enforced via
panicRecoveryBlockedandisPanicResettingflags within a@MainActorcontext
Frequently Asked Questions
What is the difference between the triple-tap and settings button triggers?
Both methods invoke identical wipe logic through appChromeModel.panicClearAllData(). The triple-tap gesture provides a stealth option for discreet activation during compromise scenarios, while the settings button offers a traditional, discoverable UI element. Both paths resolve to the same ChatViewModel.panicClearAllData() implementation.
Does the emergency wipe delete data from the network or just locally?
The emergency wipe operates exclusively on local device data. It clears conversation stores, deletes Keychain entries, removes identity-related UserDefaults, and wipes peer-identity caches, but cannot retract messages already delivered to other users. However, destroying the local cryptographic keys effectively severs the identity, preventing decryption of future messages.
Can developers trigger the emergency wipe programmatically for testing?
Yes, developers can invoke the wipe by calling appChromeModel.panicClearAllData() on any SwiftUI view that accesses the environment object. This enables testing of recovery flows and verification that the restartServices parameter properly controls whether network services restart after the wipe completes.
What mechanisms prevent accidental triggering of the emergency wipe?
The triple-tap gesture requires exactly three consecutive taps on the specific logo text, significantly reducing accidental activation. Internally, ChatViewModel protects the wipe routine with panicRecoveryBlocked and isPanicResetting flags that prevent concurrent execution and race conditions. A defer block ensures isPanicResetting resets to false even if the wipe encounters errors.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →