diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 0950c5a243..9812dfee78 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -534,7 +534,6 @@ 45A1684D2A1C308800C2432D /* AudioPresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A1684C2A1C308800C2432D /* AudioPresentation.swift */; }; 45A2F005204473A3002E978A /* NewMessage.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45A2F004204473A3002E978A /* NewMessage.aifc */; }; 45A3579827DAAC6A0051CE8B /* UserProfileTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A3579727DAAC6A0051CE8B /* UserProfileTest.swift */; }; - 45B27B862037FFB400A539DF /* InternalFileBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45B27B852037FFB400A539DF /* InternalFileBrowserViewController.swift */; }; 45B3680B2A1D75DF0067D05A /* AudioAllMediaPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45B3680A2A1D75DF0067D05A /* AudioAllMediaPresenter.swift */; }; 45B74A742044AAB600CD42F8 /* aurora-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45B74A5B2044AAB300CD42F8 /* aurora-quiet.aifc */; }; 45B74A752044AAB600CD42F8 /* synth-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45B74A5C2044AAB300CD42F8 /* synth-quiet.aifc */; }; @@ -601,7 +600,6 @@ 4CA485BB2232339F004B9E7D /* PhotoCaptureViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA485BA2232339F004B9E7D /* PhotoCaptureViewController.swift */; }; 4CB5F26720F6E1E2004D1B42 /* MessageActionsToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF4C0920F55BBA005DA313 /* MessageActionsToolbar.swift */; }; 4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5F26820F7D060004D1B42 /* MessageActions.swift */; }; - 4CBBFE4A2306F5D300B37450 /* LogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBBFE492306F5D300B37450 /* LogViewController.swift */; }; 4CC1ECF9211A47CE00CC13BE /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC1ECF8211A47CD00CC13BE /* StoreKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 4CD675BE22E7BE35008010D2 /* MediaDismissAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD675BD22E7BE35008010D2 /* MediaDismissAnimationController.swift */; }; 4CD675C522E7CF22008010D2 /* ConversationViewController+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD675C422E7CF22008010D2 /* ConversationViewController+OWS.swift */; }; @@ -1287,6 +1285,7 @@ 66D31DAD2BC48E0100EAF735 /* OWSContactAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D31DAC2BC48E0100EAF735 /* OWSContactAddress.swift */; }; 66D31DAF2BC48E3A00EAF735 /* OWSContactName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D31DAE2BC48E3A00EAF735 /* OWSContactName.swift */; }; 66D31F972E5E685300A1C82D /* InternalListMediaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D31F962E5E684E00A1C82D /* InternalListMediaViewController.swift */; }; + 66D31FA02E5E685300A1C82D /* InternalBackupSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D31FA12E5E684E00A1C82D /* InternalBackupSettingsViewController.swift */; }; 66D709E928E3999400B5013A /* StoryContextAssociatedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D709E828E3999400B5013A /* StoryContextAssociatedData.swift */; }; 66D7B8FF2B9287F00005C98B /* AttachmentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D7B8FE2B9287F00005C98B /* AttachmentManager.swift */; }; 66D7B9012B92889E0005C98B /* AttachmentManagerImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D7B9002B92889E0005C98B /* AttachmentManagerImpl.swift */; }; @@ -4754,7 +4753,6 @@ 45A3579727DAAC6A0051CE8B /* UserProfileTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileTest.swift; sourceTree = ""; }; 45A663C41F92EC760027B59E /* GroupTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupTableViewCell.swift; sourceTree = ""; }; 45A6DAD51EBBF85500893231 /* ReminderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReminderView.swift; sourceTree = ""; }; - 45B27B852037FFB400A539DF /* InternalFileBrowserViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalFileBrowserViewController.swift; sourceTree = ""; }; 45B3680A2A1D75DF0067D05A /* AudioAllMediaPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioAllMediaPresenter.swift; sourceTree = ""; }; 45B74A5B2044AAB300CD42F8 /* aurora-quiet.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; path = "aurora-quiet.aifc"; sourceTree = ""; }; 45B74A5C2044AAB300CD42F8 /* synth-quiet.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; path = "synth-quiet.aifc"; sourceTree = ""; }; @@ -4837,7 +4835,6 @@ 4CA485BA2232339F004B9E7D /* PhotoCaptureViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoCaptureViewController.swift; sourceTree = ""; }; 4CB5F26820F7D060004D1B42 /* MessageActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActions.swift; sourceTree = ""; }; 4CB93DC12180FF07004B9764 /* ProximityMonitoringManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProximityMonitoringManager.swift; sourceTree = ""; }; - 4CBBFE492306F5D300B37450 /* LogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewController.swift; sourceTree = ""; }; 4CC1ECF8211A47CD00CC13BE /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; 4CD675BD22E7BE35008010D2 /* MediaDismissAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaDismissAnimationController.swift; sourceTree = ""; }; 4CD675C422E7CF22008010D2 /* ConversationViewController+OWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConversationViewController+OWS.swift"; sourceTree = ""; }; @@ -5567,6 +5564,7 @@ 66D31DAC2BC48E0100EAF735 /* OWSContactAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSContactAddress.swift; sourceTree = ""; }; 66D31DAE2BC48E3A00EAF735 /* OWSContactName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSContactName.swift; sourceTree = ""; }; 66D31F962E5E684E00A1C82D /* InternalListMediaViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalListMediaViewController.swift; sourceTree = ""; }; + 66D31FA12E5E684E00A1C82D /* InternalBackupSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalBackupSettingsViewController.swift; sourceTree = ""; }; 66D709E828E3999400B5013A /* StoryContextAssociatedData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryContextAssociatedData.swift; sourceTree = ""; }; 66D7B8FE2B9287F00005C98B /* AttachmentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentManager.swift; sourceTree = ""; }; 66D7B9002B92889E0005C98B /* AttachmentManagerImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentManagerImpl.swift; sourceTree = ""; }; @@ -11441,12 +11439,11 @@ isa = PBXGroup; children = ( 344A761024B366F4009D69A5 /* FlagsViewController.swift */, + 66D31FA12E5E684E00A1C82D /* InternalBackupSettingsViewController.swift */, 665229882E218D53002C14A0 /* InternalDiskUsageViewController.swift */, - 45B27B852037FFB400A539DF /* InternalFileBrowserViewController.swift */, 66D31F962E5E684E00A1C82D /* InternalListMediaViewController.swift */, 8862A55825F090C5005D65DB /* InternalSettingsViewController.swift */, 663883562D4C034F008EA898 /* InternalSQLClientViewController.swift */, - 4CBBFE492306F5D300B37450 /* LogViewController.swift */, 344A761224B36C8C009D69A5 /* TestingViewController.swift */, ); path = Internal; @@ -18508,8 +18505,8 @@ D9E43C072CC194140001536E /* IndividualCallViewController.swift in Sources */, D97046062E81D4240034C05D /* InfoMessageGroupUpdateMigrator.swift in Sources */, 88BCCC8123837B7D00CE5FE6 /* InteractionReactionState.swift in Sources */, + 66D31FA02E5E685300A1C82D /* InternalBackupSettingsViewController.swift in Sources */, 665229892E218D5F002C14A0 /* InternalDiskUsageViewController.swift in Sources */, - 45B27B862037FFB400A539DF /* InternalFileBrowserViewController.swift in Sources */, 66D31F972E5E685300A1C82D /* InternalListMediaViewController.swift in Sources */, 8862A55925F090C5005D65DB /* InternalSettingsViewController.swift in Sources */, 663883572D4C0360008EA898 /* InternalSQLClientViewController.swift in Sources */, @@ -18533,7 +18530,6 @@ 4C25768A23AD510800E0398D /* LoadMoreMessagesView.swift in Sources */, D9E43C082CC194140001536E /* LocalVideoView.swift in Sources */, 88A9729422FB4D02004B4FBF /* LocationPicker.swift in Sources */, - 4CBBFE4A2306F5D300B37450 /* LogViewController.swift in Sources */, 3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */, 88A941992409A391000E9700 /* LottieToggleButton.swift in Sources */, 5033D46929D7951F007FEADA /* MainAppContext.swift in Sources */, diff --git a/Signal/AppLaunch/AppDelegate.swift b/Signal/AppLaunch/AppDelegate.swift index 0baab806a5..d8df275646 100644 --- a/Signal/AppLaunch/AppDelegate.swift +++ b/Signal/AppLaunch/AppDelegate.swift @@ -148,9 +148,6 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { debugLogger.enableFileLogging(appContext: mainAppContext, canLaunchInBackground: true) DebugLogger.configureSwiftLogging() - if DebugFlags.audibleErrorLogging { - debugLogger.enableErrorReporting() - } Logger.warn("Launching…") defer { Logger.info("Launched.") } diff --git a/Signal/src/ViewControllers/AppSettings/Internal/InternalBackupSettingsViewController.swift b/Signal/src/ViewControllers/AppSettings/Internal/InternalBackupSettingsViewController.swift new file mode 100644 index 0000000000..0e06c0fd33 --- /dev/null +++ b/Signal/src/ViewControllers/AppSettings/Internal/InternalBackupSettingsViewController.swift @@ -0,0 +1,82 @@ +// +// Copyright 2026 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +import SignalServiceKit +import SignalUI + +class InternalBackupSettingsViewController: OWSTableViewController2 { + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Backups" + + updateTableContents() + } + + func updateTableContents() { + let contents = OWSTableContents() + + let section = OWSTableSection() + + let backupSettingsStore = BackupSettingsStore() + let db = DependenciesBridge.shared.db + let lastBackupDetails = db.read { tx in + return backupSettingsStore.lastBackupDetails(tx: tx) + } + + section.add(.copyableItem( + label: "Last Backup chats/messages file size", + value: lastBackupDetails.flatMap { ByteCountFormatter().string(for: $0.backupFileSizeBytes) }, + )) + section.add(.actionItem(withText: "Enable Backups onboarding flow") { [weak self] in + let backupSettingsStore = BackupSettingsStore() + let db = DependenciesBridge.shared.db + + db.write { tx in + backupSettingsStore.setShouldOverrideShowBackupsOnboarding(true, tx: tx) + } + + self?.presentToast(text: "Backups onboarding enabled!") + }) + section.add(.actionItem(withText: #"Show "Backup Key Reminder" flow"#) { [weak self] in + guard let self else { return } + + let accountKeyStore = DependenciesBridge.shared.accountKeyStore + let db = DependenciesBridge.shared.db + + guard let aep = db.read(block: { accountKeyStore.getAccountEntropyPool(tx: $0) }) else { + presentToast(text: "Missing AEP?!") + return + } + + BackupRecoveryKeyReminderCoordinator( + aep: aep, + fromViewController: self, + onSuccess: { + self.presentToast(text: "Success!") + }, + ).presentVerifyFlow() + }) + section.add(.actionItem(withText: "Backup media integrity check") { [weak self] in + let vc = InternalListMediaViewController() + self?.navigationController?.pushViewController(vc, animated: true) + }) + if RemoteConfig.current.isOptimizeStorageEnabled { + section.add(.switch( + withText: "Aggressive optimize media", + subtitle: "Don't keep recent attachments when optimize media is enabled", + isOn: { Attachment.offloadingThresholdOverride }, + actionBlock: { _ in + Attachment.offloadingThresholdOverride = !Attachment.offloadingThresholdOverride + }, + )) + } + + contents.add(section) + + self.contents = contents + } +} diff --git a/Signal/src/ViewControllers/AppSettings/Internal/InternalFileBrowserViewController.swift b/Signal/src/ViewControllers/AppSettings/Internal/InternalFileBrowserViewController.swift deleted file mode 100644 index 1b1a5b9e68..0000000000 --- a/Signal/src/ViewControllers/AppSettings/Internal/InternalFileBrowserViewController.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright 2018 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only -// - -import SignalServiceKit -import SignalUI - -class InternalFileBrowserViewController: OWSTableViewController2 { - private let fileManager: FileManager - private let fileURL: URL - - init(fileURL: URL) { - self.fileManager = .default - self.fileURL = fileURL - - super.init() - - self.contents = buildContents() - } - - private func buildContents() -> OWSTableContents { - var isDirectory: ObjCBool = false - guard fileManager.fileExists(atPath: fileURL.path, isDirectory: &isDirectory) else { - return OWSTableContents(title: "File not found: \(fileURL)") - } - - var sections = [OWSTableSection]() - - // Put the URL somewhere it'll wrap and is copyable. - sections.append(OWSTableSection(items: [ - .copyableItem( - label: "Current File URL", - value: fileURL.absoluteString, - ), - ])) - - if isDirectory.boolValue { - let directoryContents: [URL] - do { - directoryContents = try fileManager.contentsOfDirectory( - at: fileURL, - includingPropertiesForKeys: [.isDirectoryKey], - ) - } catch { - owsFailDebug("Failed to get contents of \(fileURL)! \(error)") - directoryContents = [] - } - - let fileItems: [OWSTableItem] = directoryContents.map { contentsUrl in - let fileIsDirectory: Bool - do { - fileIsDirectory = try contentsUrl.resourceValues(forKeys: [.isDirectoryKey]).isDirectory! - } catch { - owsFailDebug("Failed to get isDirectory resource value! \(error)") - fileIsDirectory = false - } - - let icon = fileIsDirectory ? "📁" : "📄" - - return .disclosureItem( - withText: "\(icon): \(contentsUrl.lastPathComponent)", - actionBlock: { [weak self] in - guard let self else { return } - navigationController?.pushViewController( - InternalFileBrowserViewController(fileURL: contentsUrl), - animated: true, - ) - }, - ) - } - - sections.append(OWSTableSection( - title: "Contents", - items: fileItems, - )) - } - - do { - let attributes: [FileAttributeKey: Any] = try fileManager.attributesOfItem(atPath: fileURL.path) - - let attributeItems: [OWSTableItem] = attributes - .sorted(by: { $0.key.rawValue < $1.key.rawValue }) - .map { fileAttribute, value in - return .copyableItem( - label: fileAttribute.rawValue.replacingOccurrences(of: "NSFile", with: ""), - value: "\(value)", - ) - } - - sections.append(OWSTableSection( - title: "Attributes", - items: attributeItems, - )) - } catch { - owsFailDebug("Failed to get attributes for \(fileURL)! \(error)") - } - - return OWSTableContents(sections: sections) - } -} diff --git a/Signal/src/ViewControllers/AppSettings/Internal/InternalSettingsViewController.swift b/Signal/src/ViewControllers/AppSettings/Internal/InternalSettingsViewController.swift index cfebae5dab..c3ad383b34 100644 --- a/Signal/src/ViewControllers/AppSettings/Internal/InternalSettingsViewController.swift +++ b/Signal/src/ViewControllers/AppSettings/Internal/InternalSettingsViewController.swift @@ -4,8 +4,6 @@ // import AVFoundation -import GRDB -import LibSignalClient import SignalServiceKit import SignalUI @@ -51,17 +49,6 @@ class InternalSettingsViewController: OWSTableViewController2 { )) #endif - if DebugFlags.audibleErrorLogging { - debugSection.add(.disclosureItem( - withText: OWSLocalizedString("SETTINGS_ADVANCED_VIEW_ERROR_LOG", comment: ""), - actionBlock: { [weak self] in - Logger.flush() - let vc = LogPickerViewController(logDirUrl: DebugLogger.errorLogsDir) - self?.navigationController?.pushViewController(vc, animated: true) - }, - )) - } - debugSection.add(.disclosureItem( withText: "Remote Configs", actionBlock: { [weak self] in @@ -92,42 +79,11 @@ class InternalSettingsViewController: OWSTableViewController2 { self?.navigationController?.pushViewController(vc, animated: true) }, )) - debugSection.add(.actionItem( - withText: "Run Database Integrity Checks", + debugSection.add(.disclosureItem( + withText: "Backups", actionBlock: { [weak self] in - guard let self else { return } - - ModalActivityIndicatorViewController.present( - fromViewController: self, - ) { modal in - let databaseStorage = SSKEnvironment.shared.databaseStorageRef - let integrityCheckResult = GRDBDatabaseStorageAdapter.checkIntegrity( - databaseStorage: databaseStorage, - ) - - modal.dismiss { - switch integrityCheckResult { - case .ok: - self.presentToast(text: "Integrity check: ok! More detail in logs.") - case .notOk: - self.presentToast(text: "Integrity check: not ok! More detail in logs.") - } - } - } - }, - )) - debugSection.add(.actionItem( - withText: "Clean Orphaned Data", - actionBlock: { [weak self] in - guard let self else { return } - ModalActivityIndicatorViewController.present( - fromViewController: self, - canCancel: false, - asyncBlock: { modalActivityIndicator in - try? await OWSOrphanDataCleaner.cleanUp(shouldRemoveOrphanedData: true) - modalActivityIndicator.dismiss() - }, - ) + let vc = InternalBackupSettingsViewController() + self?.navigationController?.pushViewController(vc, animated: true) }, )) @@ -139,98 +95,6 @@ class InternalSettingsViewController: OWSTableViewController2 { contents.add(debugSection) - let backupsSection = OWSTableSection(title: "Backups") - - let backupSettingsStore = BackupSettingsStore() - let db = DependenciesBridge.shared.db - let lastBackupDetails = db.read { tx in - return backupSettingsStore.lastBackupDetails(tx: tx) - } - - backupsSection.add(.actionItem(withText: "Export + Validate Message Backup proto") { [self] in - Task { - await exportMessageBackupProto() - } - }) - if SSKEnvironment.shared.remoteConfigManagerRef.currentConfig().isOptimizeStorageEnabled { - backupsSection.add(.switch( - withText: "Offload all attachments", - subtitle: "If on and \"Optimize Storage\" enabled, offload all attachments instead of only those >30d old", - isOn: { Attachment.offloadingThresholdOverride }, - actionBlock: { _ in - Attachment.offloadingThresholdOverride = !Attachment.offloadingThresholdOverride - }, - )) - } - backupsSection.add(.actionItem(withText: "Enable Backups onboarding flow") { [weak self] in - let backupSettingsStore = BackupSettingsStore() - let db = DependenciesBridge.shared.db - - db.write { tx in - backupSettingsStore.setShouldOverrideShowBackupsOnboarding(true, tx: tx) - } - - self?.presentToast(text: "Backups onboarding enabled!") - }) - backupsSection.add(.copyableItem( - label: "Last Backup chats/messages file size", - value: lastBackupDetails.flatMap { ByteCountFormatter().string(for: $0.backupFileSizeBytes) }, - )) - backupsSection.add(.actionItem(withText: #"Show "Backup Key Reminder" flow"#) { [weak self] in - guard let self else { return } - - let accountKeyStore = DependenciesBridge.shared.accountKeyStore - let db = DependenciesBridge.shared.db - - guard let aep = db.read(block: { accountKeyStore.getAccountEntropyPool(tx: $0) }) else { - presentToast(text: "Missing AEP?!") - return - } - - BackupRecoveryKeyReminderCoordinator( - aep: aep, - fromViewController: self, - onSuccess: { - self.presentToast(text: "Success!") - }, - ).presentVerifyFlow() - }) - backupsSection.add(.actionItem(withText: "Backup media integrity check") { [weak self] in - let vc = InternalListMediaViewController() - self?.navigationController?.pushViewController(vc, animated: true) - }) - contents.add(backupsSection) - - do { - func makeFileBrowsingActionItem(_ title: String, _ fileUrl: URL) -> OWSTableItem { - return .actionItem( - withText: title, - actionBlock: { [weak self] in - guard let self else { return } - navigationController?.pushViewController( - InternalFileBrowserViewController(fileURL: fileUrl), - animated: true, - ) - }, - ) - } - - let fileBrowsingSection = OWSTableSection(title: "Browse App Files") - fileBrowsingSection.add(makeFileBrowsingActionItem( - "App Container: Library", - URL(string: OWSFileSystem.appLibraryDirectoryPath())!.deletingLastPathComponent(), - )) - fileBrowsingSection.add(makeFileBrowsingActionItem( - "App Container: Documents", - URL(string: OWSFileSystem.appDocumentDirectoryPath())!.deletingLastPathComponent(), - )) - fileBrowsingSection.add(makeFileBrowsingActionItem( - "Shared App Container", - URL(string: OWSFileSystem.appSharedDataDirectoryPath())!.deletingLastPathComponent(), - )) - contents.add(fileBrowsingSection) - } - let ( contactThreadCount, groupThreadCount, @@ -412,66 +276,4 @@ private extension InternalSettingsViewController { } InMemorySettings.spinningCheckmarks = !wasSpinning } - - func exportMessageBackupProto() async { - let accountKeyStore = DependenciesBridge.shared.accountKeyStore - let backupArchiveManager = DependenciesBridge.shared.backupArchiveManager - let db = DependenciesBridge.shared.db - let tsAccountManager = DependenciesBridge.shared.tsAccountManager - - let backupKey: MessageBackupKey - let exportMetadata: Upload.EncryptedBackupUploadMetadata - do { - (backupKey, exportMetadata) = try await ModalActivityIndicatorViewController.presentAndPropagateResult( - from: self, - title: "Exporting...", - ) { - let (messageBackupKey, localIdentifiers) = try db.read { tx in - let localIdentifiers = try tsAccountManager.registeredState(tx: tx).localIdentifiers - return ( - try accountKeyStore.getMessageRootBackupKey(aci: localIdentifiers.aci, tx: tx)!, - localIdentifiers, - ) - } - - let backupKey = try MessageBackupKey( - backupKey: messageBackupKey.backupKey, - backupId: messageBackupKey.backupId, - ) - - let exportMetadata = try await backupArchiveManager.exportEncryptedBackup( - localIdentifiers: localIdentifiers, - backupPurpose: .remoteExport(key: messageBackupKey, chatAuth: .implicit()), - progress: nil, - logger: PrefixedLogger(prefix: "[Backups]"), - ) - - return (backupKey, exportMetadata) - } - } catch { - let message = "Failed to export Backup proto! \(error)" - Logger.error(message) - presentToast(text: message) - return - } - - let keyString = "AES key: \(backupKey.aesKey.base64EncodedString())" - + "\nHMAC key: \(backupKey.hmacKey.base64EncodedString())" - - let activityVC = UIActivityViewController( - activityItems: [exportMetadata.fileUrl], - applicationActivities: nil, - ) - activityVC.popoverPresentationController?.sourceView = view - activityVC.completionWithItemsHandler = { [self] _, _, _, _ in - UIPasteboard.general.setItems( - [[UIPasteboard.typeAutomatic: keyString]], - options: [.expirationDate: Date().addingTimeInterval(120)], - ) - - presentToast(text: "Success! Encryption key copied.") - } - - present(activityVC, animated: true) - } } diff --git a/Signal/src/ViewControllers/AppSettings/Internal/LogViewController.swift b/Signal/src/ViewControllers/AppSettings/Internal/LogViewController.swift deleted file mode 100644 index 2c39045926..0000000000 --- a/Signal/src/ViewControllers/AppSettings/Internal/LogViewController.swift +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only -// - -import SignalServiceKit -public import SignalUI - -public class LogPickerViewController: OWSTableViewController2 { - let logDirUrl: URL - - public init(logDirUrl: URL) { - self.logDirUrl = logDirUrl - super.init() - } - - override public func viewDidLoad() { - super.viewDidLoad() - updateTableContents() - } - - public func updateTableContents() { - let contents = OWSTableContents() - contents.add(buildPreferenceSection()) - contents.add(buildActionsSection()) - contents.add(buildLogsSection()) - self.contents = contents - } - - private func buildPreferenceSection() -> OWSTableSection { - let chooChoo = OWSTableItem.switch( - withText: "🚂 Play Sound When Errors Occur", - isOn: { Preferences.isAudibleErrorLoggingEnabled }, - target: self, - selector: #selector(didToggleAudiblePreference(_:)), - ) - let failDebug = OWSTableItem.switch( - withText: "💥 Crash When owsFailDebugs Occur", - isOn: { Preferences.isFailDebugEnabled }, - target: self, - selector: #selector(didToggleFailDebug(_:)), - ) - return OWSTableSection(title: "Preferences", items: [chooChoo, failDebug]) - } - - private func buildActionsSection() -> OWSTableSection { - let exportItem = OWSTableItem(title: "Export Logs") { - Logger.flush() - DebugLogs.exportLogs() - } - return OWSTableSection(title: "Actions", items: [exportItem]) - } - - private func buildLogsSection() -> OWSTableSection { - guard let directoryEnumerator = FileManager.default.enumerator(at: logDirUrl, includingPropertiesForKeys: nil) else { - owsFailDebug("logUrls was unexpectedly nil") - return OWSTableSection(title: "No Log URLs", items: []) - } - - let logUrls: [URL] = directoryEnumerator.compactMap { $0 as? URL } - let sortedUrls = logUrls.sorted { a, b -> Bool in - return a.lastPathComponent > b.lastPathComponent - } - - let logItems: [OWSTableItem] = sortedUrls.map { logUrl in - return OWSTableItem( - customCellBlock: { () -> UITableViewCell in - let cell = OWSTableItem.newCell() - guard let textLabel = cell.textLabel else { - owsFailDebug("textLabel was unexpectedly nil") - return cell - } - textLabel.lineBreakMode = .byTruncatingHead - textLabel.text = logUrl.lastPathComponent - - return cell - }, - actionBlock: { [weak self] in - guard let self else { return } - let logVC = LogViewController(logUrl: logUrl) - - guard let navigationController = self.navigationController else { - owsFailDebug("navigationController was unexpectedly nil") - return - } - - navigationController.pushViewController(logVC, animated: true) - }, - ) - } - - return OWSTableSection(title: "View Logs", items: logItems) - } - - @objc - private func didToggleAudiblePreference(_ sender: UISwitch) { - Preferences.setIsAudibleErrorLoggingEnabled(sender.isOn) - if sender.isOn { - ErrorLogger.playAlertSound() - } - } - - @objc - private func didToggleFailDebug(_ sender: UISwitch) { - Preferences.setIsFailDebugEnabled(sender.isOn) - } -} - -public class LogViewController: UIViewController { - - let logUrl: URL - - public init(logUrl: URL) { - self.logUrl = logUrl - super.init(nibName: nil, bundle: nil) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - let textView = UITextView() - - override public func loadView() { - self.view = textView - loadLogText() - } - - override public func viewDidLoad() { - super.viewDidLoad() - navigationItem.rightBarButtonItems = [ - UIBarButtonItem(image: Theme.iconImage(.buttonShare), style: .plain, target: self, action: #selector(didTapShare(_:))), - UIBarButtonItem(image: Theme.iconImage(.buttonDelete), style: .plain, target: self, action: #selector(didTapTrash(_:))), - ] - } - - func loadLogText() { - do { - // This is super crude, but: - // 1. generally we should haven't a ton of logged errors - // 2. this is a dev tool - let logData = try Data(contentsOf: logUrl) - - // TODO most recent lines on top? - textView.text = String(data: logData, encoding: .utf8) - } catch { - textView.text = "Failed to load log data: \(error)" - } - } - - @objc - private func didTapTrash(_ sender: UIBarButtonItem) { - // truncate logUrl - do { - try NSData().write(to: logUrl) - loadLogText() - } catch { - owsFailDebug("error: \(error)") - } - } - - @objc - private func didTapShare(_ sender: UIBarButtonItem) { - let logText = textView.text ?? "Empty Log" - let vc = UIActivityViewController(activityItems: [logText], applicationActivities: []) - present(vc, animated: true) - } -} diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index fef656ae02..9156d8fb51 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -8308,9 +8308,6 @@ /* No comment provided by engineer. */ "SETTINGS_ADVANCED_SUBMIT_DEBUGLOG" = "Submit Debug Log"; -/* No comment provided by engineer. */ -"SETTINGS_ADVANCED_VIEW_ERROR_LOG" = "Error Logs"; - /* Information on sheet about changing the app icon - first line */ "SETTINGS_APP_ICON_EDUCATION_APP_NAME" = "The app name “Signal” will be visible on the Home Screen, in notifications and in the App Library."; diff --git a/SignalServiceKit/Debugging/DebugLogger.swift b/SignalServiceKit/Debugging/DebugLogger.swift index 8b0272aadd..bbe6b04260 100644 --- a/SignalServiceKit/Debugging/DebugLogger.swift +++ b/SignalServiceKit/Debugging/DebugLogger.swift @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-only // -import AudioToolbox import CocoaLumberjack import LibSignalClient import SignalRingRTC @@ -59,19 +58,6 @@ private final class DebugLogFileManager: DDLogFileManagerDefault { } } -public final class ErrorLogger: DDFileLogger { - public static func playAlertSound() { - AudioServicesPlayAlertSound(SystemSoundID(1023)) - } - - override public func log(message logMessage: DDLogMessage) { - super.log(message: logMessage) - if Preferences.isAudibleErrorLoggingEnabled { - Self.playAlertSound() - } - } -} - public final class DebugLogger { private init() {} @@ -105,8 +91,6 @@ public final class DebugLogger { DebugLogger.nseDebugLogsDirPath, ] - public static let errorLogsDir = URL(fileURLWithPath: OWSFileSystem.cachesDirectoryPath().appendingPathComponent("ErrorLogs")) - public var fileLogger: DDFileLogger? public var allLogFilePaths: Set { let fileManager = FileManager.default @@ -129,12 +113,6 @@ public final class DebugLogger { return logPathSet } - public func enableErrorReporting() { - let errorLogger = ErrorLogger(logFileManager: DDLogFileManagerDefault(logsDirectory: Self.errorLogsDir.path)) - errorLogger.logFormatter = ScrubbingLogFormatter() - DDLog.add(errorLogger, with: .error) - } - // MARK: Enable/Disable public func enableFileLogging(appContext: AppContext, canLaunchInBackground: Bool) { diff --git a/SignalServiceKit/Environment/BuildFlags.swift b/SignalServiceKit/Environment/BuildFlags.swift index a19ff07525..43433c0f31 100644 --- a/SignalServiceKit/Environment/BuildFlags.swift +++ b/SignalServiceKit/Environment/BuildFlags.swift @@ -25,8 +25,6 @@ private let build = FeatureBuild.current /// it's easier to review which feature flags are in play. public enum BuildFlags { - public static let choochoo = build <= .internal - public static let failDebug = build <= .internal public static let linkedPhones = build <= .internal @@ -151,8 +149,6 @@ public enum DebugFlags { public static let testPopulationErrorAlerts = build <= .beta - public static let audibleErrorLogging = build <= .internal - public static let internalSettings = build <= .internal public static let internalMegaphoneEligible = build <= .internal diff --git a/SignalServiceKit/Util/Preferences.swift b/SignalServiceKit/Util/Preferences.swift index 88738587d9..f4adb46b79 100644 --- a/SignalServiceKit/Util/Preferences.swift +++ b/SignalServiceKit/Util/Preferences.swift @@ -49,7 +49,6 @@ public class Preferences { private enum UserDefaultsKeys { static let deviceScale = "OWSPreferencesKeyDeviceScale" - static let isAudibleErrorLoggingEnabled = "IsAudibleErrorLoggingEnabled" static let isFailDebugEnabled = "IsFailDebugEnabled" } @@ -147,14 +146,6 @@ public class Preferences { CurrentAppContext().appUserDefaults().set(value, forKey: UserDefaultsKeys.isFailDebugEnabled) } - public static var isAudibleErrorLoggingEnabled: Bool { - CurrentAppContext().appUserDefaults().bool(forKey: UserDefaultsKeys.isAudibleErrorLoggingEnabled) && BuildFlags.choochoo - } - - public static func setIsAudibleErrorLoggingEnabled(_ value: Bool) { - CurrentAppContext().appUserDefaults().set(value, forKey: UserDefaultsKeys.isAudibleErrorLoggingEnabled) - } - // MARK: Specific Preferences public var isScreenSecurityEnabled: Bool {