diff --git a/Swiftgram/SGDBReset/Sources/File.swift b/Swiftgram/SGDBReset/Sources/File.swift
index 1029c5e152..89c7369e88 100644
--- a/Swiftgram/SGDBReset/Sources/File.swift
+++ b/Swiftgram/SGDBReset/Sources/File.swift
@@ -3,6 +3,7 @@ import Foundation
import SGLogging
private let dbResetKey = "sg_db_reset"
+private let dbHardResetKey = "sg_db_hard_reset"
public func sgDBResetIfNeeded(databasePath: String, present: ((UIViewController) -> ())?) {
guard UserDefaults.standard.bool(forKey: dbResetKey) else {
@@ -45,3 +46,117 @@ public func sgDBResetIfNeeded(databasePath: String, present: ((UIViewController)
// let semaphore = DispatchSemaphore(value: 0)
// semaphore.wait()
}
+
+public func sgHardReset(dataPath: String, present: ((UIViewController) -> ())?) {
+ let startAlert = UIAlertController(
+ title: "ATTENTION",
+ message: "Confirm HARD RESET?",
+ preferredStyle: .alert
+ )
+
+ startAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
+ exit(0)
+ })
+ startAlert.addAction(UIAlertAction(title: "RESET", style: .destructive) { _ in
+ let ensureAlert = UIAlertController(
+ title: "⚠️ ATTENTION ⚠️",
+ message: "ARE YOU SURE you want to make a HARD RESET?",
+ preferredStyle: .alert
+ )
+
+ ensureAlert.addAction(UIAlertAction(title: "Cancel", style: .default) { _ in
+ exit(0)
+ })
+ ensureAlert.addAction(UIAlertAction(title: "RESET NOW", style: .destructive) { _ in
+ NSLog("[SG.DBReset] Hard reset with system settings")
+ let alert = UIAlertController(
+ title: "Hard reset.\nPlease wait...",
+ message: nil,
+ preferredStyle: .alert
+ )
+ ensureAlert.dismiss(animated: false) {
+ present?(alert)
+ }
+
+ do {
+ let fileManager = FileManager.default
+ let contents = try fileManager.contentsOfDirectory(atPath: dataPath)
+
+ // Filter directories that match our criteria
+ let accountDirectories = contents.compactMap { filename in
+ let fullPath = (dataPath as NSString).appendingPathComponent(filename)
+
+ var isDirectory: ObjCBool = false
+ if fileManager.fileExists(atPath: fullPath, isDirectory: &isDirectory), isDirectory.boolValue {
+ if filename.hasPrefix("account-") || filename == "accounts-metadata" {
+ return fullPath
+ }
+ }
+ return nil
+ }
+
+ NSLog("[SG.DBReset] Found \(accountDirectories.count) account dirs...")
+ var deletedPostboxCount = 0
+ for accountDir in accountDirectories {
+ let accountName = (accountDir as NSString).lastPathComponent
+ let postboxPath = (accountDir as NSString).appendingPathComponent("postbox")
+
+ var isPostboxDir: ObjCBool = false
+ if fileManager.fileExists(atPath: postboxPath, isDirectory: &isPostboxDir), isPostboxDir.boolValue {
+ // Delete postbox/db
+ let dbPath = (postboxPath as NSString).appendingPathComponent("db")
+ var isDbDir: ObjCBool = false
+ if fileManager.fileExists(atPath: dbPath, isDirectory: &isDbDir), isDbDir.boolValue {
+ NSLog("[SG.DBReset] Trying to delete postbox/db in: \(accountName)")
+ try fileManager.removeItem(atPath: dbPath)
+ NSLog("[SG.DBReset] OK. Deleted postbox/db directory in: \(accountName)")
+ }
+
+ // Delete postbox/media
+ let mediaPath = (postboxPath as NSString).appendingPathComponent("media")
+ var isMediaDir: ObjCBool = false
+ if fileManager.fileExists(atPath: mediaPath, isDirectory: &isMediaDir), isMediaDir.boolValue {
+ NSLog("[SG.DBReset] Trying to delete postbox/media in: \(accountName)")
+ try fileManager.removeItem(atPath: mediaPath)
+ NSLog("[SG.DBReset] OK. Deleted postbox/media directory in: \(accountName)")
+ }
+
+ deletedPostboxCount += 1
+ }
+ }
+
+
+ NSLog("[SG.DBReset] Done. Hard Reset completed")
+ let successAlert = UIAlertController(
+ title: "Hard reset completed",
+ message: nil,
+ preferredStyle: .alert
+ )
+ successAlert.addAction(UIAlertAction(title: "Restart App", style: .cancel) { _ in
+ exit(0)
+ })
+ alert.dismiss(animated: false) {
+ present?(successAlert)
+ }
+ } catch {
+ NSLog("[SG.DBReset] ERROR. Hard reset failed: \(error)")
+ let failAlert = UIAlertController(
+ title: "ERROR. Hard reset failed",
+ message: "\(error)",
+ preferredStyle: .alert
+ )
+ alert.dismiss(animated: false) {
+ present?(failAlert)
+ }
+ }
+ })
+ ensureAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
+ exit(0)
+ })
+
+ present?(ensureAlert)
+ })
+
+ present?(startAlert)
+ UserDefaults.standard.set(false, forKey: dbHardResetKey)
+}
diff --git a/Swiftgram/SGSettingsBundle/Settings.bundle/Root.plist b/Swiftgram/SGSettingsBundle/Settings.bundle/Root.plist
index 92c85b662d..148a22836f 100644
--- a/Swiftgram/SGSettingsBundle/Settings.bundle/Root.plist
+++ b/Swiftgram/SGSettingsBundle/Settings.bundle/Root.plist
@@ -24,6 +24,24 @@
DefaultValue
+
+ Type
+ PSGroupSpecifier
+ FooterText
+ HardReset.Notice
+ Title
+ HardReset.Title
+
+
+ Type
+ PSToggleSwitchSpecifier
+ Title
+ HardReset.Toggle
+ Key
+ sg_db_hard_reset
+ DefaultValue
+
+
diff --git a/Swiftgram/SGSettingsBundle/Settings.bundle/en.lproj/Root.strings b/Swiftgram/SGSettingsBundle/Settings.bundle/en.lproj/Root.strings
index 6986865c88..fb7c4fe63d 100644
--- a/Swiftgram/SGSettingsBundle/Settings.bundle/en.lproj/Root.strings
+++ b/Swiftgram/SGSettingsBundle/Settings.bundle/en.lproj/Root.strings
@@ -1,5 +1,8 @@
/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
"Reset.Title" = "TROUBLESHOOTING";
-"Reset.Toggle" = "Reset caches on next launch";
+"Reset.Toggle" = "Reset metadata";
"Reset.Notice" = "Use in case you're stuck and can't open the app. This WILL NOT logout your accounts, but all secret chats will be lost.";
+"HardReset.Title" = "";
+"HardReset.Toggle" = "Reset all";
+"HardReset.Notice" = "Clears metadata, cached messages and media for all accounts. This should not logout your accounts, but proceed at YOUR OWN RISK. All secret chats will be lost.";
\ No newline at end of file
diff --git a/Swiftgram/SGSettingsBundle/Settings.bundle/ru.lproj/Root.strings b/Swiftgram/SGSettingsBundle/Settings.bundle/ru.lproj/Root.strings
index 42015a1b91..4da4548194 100644
--- a/Swiftgram/SGSettingsBundle/Settings.bundle/ru.lproj/Root.strings
+++ b/Swiftgram/SGSettingsBundle/Settings.bundle/ru.lproj/Root.strings
@@ -1,3 +1,6 @@
"Reset.Title" = "РЕШЕНИЕ ПРОБЛЕМ";
-"Reset.Toggle" = "Сбросить кэш при следующем запуске";
+"Reset.Toggle" = "Сбросить метаданные";
"Reset.Notice" = "Используйте, если приложение вылетает или не загружается. Эта опция НЕ СБРАСЫВАЕТ ваши аккаунты, но удалит все секретные чаты.";
+"HardReset.Title" = "";
+"HardReset.Toggle" = "Сбросить всё";
+"HardReset.Notice" = "Сбрасывает метаданные, кэшированные сообщения и медиа для всех аккаунтов. Эта опция не должна разлогинить ваши аккаунты, но используйте её на СВОЙ СТРАХ И РИСК. Все секретные чаты удалятся.";
\ No newline at end of file
diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift
index 49ddba2646..e96d91b200 100644
--- a/submodules/TelegramUI/Sources/AppDelegate.swift
+++ b/submodules/TelegramUI/Sources/AppDelegate.swift
@@ -605,6 +605,12 @@ private func extractAccountManagerState(records: AccountRecordsView