Ensure /clear and panic triple-tap delete media files

Fix: /clear command and panicClearAllData() now properly delete media files

1. /clear (triple-tap on chat):
   - Deletes outgoing media (voice notes, images, files)
   - Conservative: only our sent media, preserves received media
   - Runs in background to avoid UI freeze

2. panicClearAllData() (triple-tap on bitchat/ header):
   - Deletes ALL media files (incoming + outgoing)
   - Removes entire files directory and recreates structure
   - Ensures complete data wipe for emergency scenarios

Both operations run async on .utility queue to prevent blocking UI.
This commit is contained in:
jack
2025-10-14 22:29:38 +02:00
parent 2040e94b83
commit 326ff628f7
+53 -1
View File
@@ -3691,9 +3691,34 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
nostrRelayManager?.connect()
}
// Delete ALL media files (incoming and outgoing) in background
Task.detached(priority: .utility) {
do {
let base = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let filesDir = base.appendingPathComponent("files", isDirectory: true)
// Delete the entire files directory and recreate it
if FileManager.default.fileExists(atPath: filesDir.path) {
try FileManager.default.removeItem(at: filesDir)
SecureLogger.info("🗑️ Deleted all media files during panic clear", category: .session)
}
// Recreate empty directory structure
try FileManager.default.createDirectory(at: filesDir, withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: filesDir.appendingPathComponent("voicenotes/incoming", isDirectory: true), withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: filesDir.appendingPathComponent("voicenotes/outgoing", isDirectory: true), withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: filesDir.appendingPathComponent("images/incoming", isDirectory: true), withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: filesDir.appendingPathComponent("images/outgoing", isDirectory: true), withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: filesDir.appendingPathComponent("files/incoming", isDirectory: true), withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: filesDir.appendingPathComponent("files/outgoing", isDirectory: true), withIntermediateDirectories: true, attributes: nil)
} catch {
SecureLogger.error("Failed to clear media files during panic: \(error)", category: .session)
}
}
// Force immediate UI update for panic mode
// UI updates immediately - no flushing needed
}
// MARK: - Autocomplete
@@ -4695,6 +4720,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// Clear the current public channel's timeline (visible + persistent buffer)
@MainActor
func clearCurrentPublicTimeline() {
// Clear messages from current timeline
switch activeChannel {
case .mesh:
messages.removeAll()
@@ -4703,6 +4729,32 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
messages.removeAll()
geoTimelines[ch.geohash] = []
}
// Delete associated media files (images, voice notes, files) in background
// Only delete from current chat to avoid removing private chat media
Task.detached(priority: .utility) {
do {
let base = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let filesDir = base.appendingPathComponent("files", isDirectory: true)
// Only clear public media (mesh channel only - geohash media is separate)
// Note: This is conservative - only clears outgoing since we authored those
let outgoingDirs = [
filesDir.appendingPathComponent("voicenotes/outgoing", isDirectory: true),
filesDir.appendingPathComponent("images/outgoing", isDirectory: true),
filesDir.appendingPathComponent("files/outgoing", isDirectory: true)
]
for dir in outgoingDirs {
if FileManager.default.fileExists(atPath: dir.path) {
try? FileManager.default.removeItem(at: dir)
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil)
}
}
} catch {
SecureLogger.error("Failed to clear media files: \(error)", category: .session)
}
}
}
// MARK: - Message Management