From e2f6a981f479d7a5a33628c14d84f6818516334b Mon Sep 17 00:00:00 2001 From: Ivan Ushakov Date: Tue, 25 Jan 2022 22:09:38 +0300 Subject: [PATCH 1/3] Crash when moving email to trash --- FlowCrypt.xcodeproj/project.pbxproj | 42 +++++++++++++------ .../Inbox/InboxViewController.swift | 16 ++++++- FlowCrypt/FlowCrypt-Bridging-Header.h | 5 +++ FlowCrypt/ObjC/ObjException.h | 19 +++++++++ FlowCrypt/ObjC/ObjException.m | 26 ++++++++++++ 5 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 FlowCrypt/FlowCrypt-Bridging-Header.h create mode 100644 FlowCrypt/ObjC/ObjException.h create mode 100644 FlowCrypt/ObjC/ObjException.m diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index d7c99be3c..e706679ab 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 2C141B2F274578C20038A3F8 /* Keypair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C141B2E274578C20038A3F8 /* Keypair.swift */; }; 2C2A3B4B2719EE6100B7F27B /* KeyServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2A3B4A2719EE6100B7F27B /* KeyServiceTests.swift */; }; 2C2A3B4D2719EF7300B7F27B /* PassPhraseServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2A3B4C2719EF7300B7F27B /* PassPhraseServiceMock.swift */; }; + 2C2B058927A07F7B00A406F0 /* ObjException.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C2B058827A07F7B00A406F0 /* ObjException.m */; }; 2C2D0B95275FDF6B0052771D /* Version6SchemaMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2D0B94275FDF6B0052771D /* Version6SchemaMigration.swift */; }; 2C4E60F72757D91A00DE5770 /* EncryptedStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4E60F62757D91A00DE5770 /* EncryptedStorageMock.swift */; }; 2C60AB0C272564D40040D7F2 /* InvalidStorageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */; }; @@ -460,6 +461,9 @@ 2C141B2E274578C20038A3F8 /* Keypair.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keypair.swift; sourceTree = ""; }; 2C2A3B4A2719EE6100B7F27B /* KeyServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyServiceTests.swift; sourceTree = ""; }; 2C2A3B4C2719EF7300B7F27B /* PassPhraseServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhraseServiceMock.swift; sourceTree = ""; }; + 2C2B058627A07F7A00A406F0 /* FlowCrypt-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FlowCrypt-Bridging-Header.h"; sourceTree = ""; }; + 2C2B058727A07F7B00A406F0 /* ObjException.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjException.h; sourceTree = ""; }; + 2C2B058827A07F7B00A406F0 /* ObjException.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjException.m; sourceTree = ""; }; 2C2D0B94275FDF6B0052771D /* Version6SchemaMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Version6SchemaMigration.swift; sourceTree = ""; }; 2C4E60F62757D91A00DE5770 /* EncryptedStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedStorageMock.swift; sourceTree = ""; }; 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvalidStorageViewController.swift; sourceTree = ""; }; @@ -996,6 +1000,15 @@ path = "Key Services"; sourceTree = ""; }; + 2C2B058A27A0809400A406F0 /* ObjC */ = { + isa = PBXGroup; + children = ( + 2C2B058727A07F7B00A406F0 /* ObjException.h */, + 2C2B058827A07F7B00A406F0 /* ObjException.m */, + ); + path = ObjC; + sourceTree = ""; + }; 2DC3601602226D74335E18F4 /* Pods */ = { isa = PBXGroup; children = ( @@ -1707,20 +1720,22 @@ C132B9B21EC2DBD800763715 /* FlowCrypt */ = { isa = PBXGroup; children = ( - 9F1C90ED26F236BE0046E7D7 /* FlowCryptEnterprise.entitlements */, - A3B7C31623E437370022D628 /* FlowCryptRelease.entitlements */, - A3B7C31523E436E10022D628 /* FlowCrypt.entitlements */, - 32DCA376D595968F13A3347A /* Core */, - C132B9C51EC2DCAB00763715 /* Controllers */, - 04B4728A1ECE29D200B8266F /* Models */, - 9FD22A1D230FEEC8005067A6 /* Common UI */, - C132B9C61EC2DCC000763715 /* Functionality */, - A3DAD60C22E469E400F2C4CD /* Resources */, 9F8220D32633661C004B2009 /* App */, C132B9B31EC2DBD800763715 /* AppDelegate.swift */, C132B9BA1EC2DBD800763715 /* Assets.xcassets */, 949ED9412303E3B400530579 /* Colors.xcassets */, + 9FD22A1D230FEEC8005067A6 /* Common UI */, + C132B9C51EC2DCAB00763715 /* Controllers */, + 32DCA376D595968F13A3347A /* Core */, + 2C2B058627A07F7A00A406F0 /* FlowCrypt-Bridging-Header.h */, + A3B7C31523E436E10022D628 /* FlowCrypt.entitlements */, + 9F1C90ED26F236BE0046E7D7 /* FlowCryptEnterprise.entitlements */, + A3B7C31623E437370022D628 /* FlowCryptRelease.entitlements */, + C132B9C61EC2DCC000763715 /* Functionality */, C132B9BF1EC2DBD800763715 /* Info.plist */, + 04B4728A1ECE29D200B8266F /* Models */, + 2C2B058A27A0809400A406F0 /* ObjC */, + A3DAD60C22E469E400F2C4CD /* Resources */, ); path = FlowCrypt; sourceTree = ""; @@ -2277,7 +2292,7 @@ }; C132B9AF1EC2DBD800763715 = { CreatedOnToolsVersion = 8.3.2; - LastSwiftMigration = 1020; + LastSwiftMigration = 1320; ProvisioningStyle = Automatic; }; D204DB9D23FB35700083B9D6 = { @@ -2598,6 +2613,7 @@ C192421F1EC48B6900C3D251 /* SetupBackupsViewController.swift in Sources */, 9F0C3C2623194E0A00299985 /* FolderViewModel.swift in Sources */, F8678DCC2722143300BB1710 /* GmailService+draft.swift in Sources */, + 2C2B058927A07F7B00A406F0 /* ObjException.m in Sources */, 21CE25E62650070300ADFF4B /* WkdUrlConstructor.swift in Sources */, 9FC411212595EA12001180A8 /* MessageSearchProvider.swift in Sources */, 9F778E7E27162038001D4B21 /* MessageThread.swift in Sources */, @@ -3054,7 +3070,7 @@ PRODUCT_NAME = FlowCrypt; PROVISIONING_PROFILE_SPECIFIER = ""; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "FlowCrypt/FlowCrypt-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; @@ -3439,7 +3455,7 @@ PRODUCT_NAME = FlowCrypt; PROVISIONING_PROFILE_SPECIFIER = ""; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "FlowCrypt/FlowCrypt-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; @@ -3498,7 +3514,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.flowcrypt.as.ios.consumer; PRODUCT_NAME = FlowCrypt; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "FlowCrypt/FlowCrypt-Bridging-Header.h"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index d91f53f6e..d3cb03268 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -452,10 +452,22 @@ extension InboxViewController: MsgListViewController { tableNode.reloadData() } else { state = .fetched(.byNumber(total: newTotalNumber)) - tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) + do { + try ObjException.catch { + self.tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) + } + } catch { + logger.logError("Failed to remove message at \(index) in fetched state") + } } default: - tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) + do { + try ObjException.catch { + self.tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) + } + } catch { + logger.logError("Failed to remove message at \(index) in default state") + } } } } diff --git a/FlowCrypt/FlowCrypt-Bridging-Header.h b/FlowCrypt/FlowCrypt-Bridging-Header.h new file mode 100644 index 000000000..6df9ada0c --- /dev/null +++ b/FlowCrypt/FlowCrypt-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "ObjException.h" diff --git a/FlowCrypt/ObjC/ObjException.h b/FlowCrypt/ObjC/ObjException.h new file mode 100644 index 000000000..b75b08fea --- /dev/null +++ b/FlowCrypt/ObjC/ObjException.h @@ -0,0 +1,19 @@ +// +// ObjException.h +// FlowCrypt +// +// Created by  Ivan Ushakov on 25.01.2022 +// Copyright © 2017-present FlowCrypt a. s. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ObjException : NSObject + ++ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/FlowCrypt/ObjC/ObjException.m b/FlowCrypt/ObjC/ObjException.m new file mode 100644 index 000000000..e1c8b6942 --- /dev/null +++ b/FlowCrypt/ObjC/ObjException.m @@ -0,0 +1,26 @@ +// +// ObjException.m +// FlowCrypt +// +// Created by  Ivan Ushakov on 25.01.2022 +// Copyright © 2017-present FlowCrypt a. s. All rights reserved. +// + +#import "ObjException.h" + +@implementation ObjException + ++ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error { + @try + { + tryBlock(); + return YES; + } + @catch (NSException *exception) + { + *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:exception.userInfo]; + return NO; + } +} + +@end From 627c1fcf6a95dd2c9261d710aefde40610656288 Mon Sep 17 00:00:00 2001 From: Ivan Ushakov Date: Wed, 26 Jan 2022 18:49:46 +0300 Subject: [PATCH 2/3] Code review fixes --- FlowCrypt.xcodeproj/project.pbxproj | 12 +++--- .../Inbox/InboxViewController.swift | 8 ++-- FlowCrypt/FlowCrypt-Bridging-Header.h | 2 +- FlowCrypt/ObjC/ObjException.m | 26 ------------ .../ObjC/{ObjException.h => ObjcException.h} | 4 +- FlowCrypt/ObjC/ObjcException.m | 40 +++++++++++++++++++ 6 files changed, 53 insertions(+), 39 deletions(-) delete mode 100644 FlowCrypt/ObjC/ObjException.m rename FlowCrypt/ObjC/{ObjException.h => ObjcException.h} (84%) create mode 100644 FlowCrypt/ObjC/ObjcException.m diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index e706679ab..9142cdf0f 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -37,7 +37,7 @@ 2C141B2F274578C20038A3F8 /* Keypair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C141B2E274578C20038A3F8 /* Keypair.swift */; }; 2C2A3B4B2719EE6100B7F27B /* KeyServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2A3B4A2719EE6100B7F27B /* KeyServiceTests.swift */; }; 2C2A3B4D2719EF7300B7F27B /* PassPhraseServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2A3B4C2719EF7300B7F27B /* PassPhraseServiceMock.swift */; }; - 2C2B058927A07F7B00A406F0 /* ObjException.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C2B058827A07F7B00A406F0 /* ObjException.m */; }; + 2C2B058927A07F7B00A406F0 /* ObjcException.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C2B058827A07F7B00A406F0 /* ObjcException.m */; }; 2C2D0B95275FDF6B0052771D /* Version6SchemaMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2D0B94275FDF6B0052771D /* Version6SchemaMigration.swift */; }; 2C4E60F72757D91A00DE5770 /* EncryptedStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4E60F62757D91A00DE5770 /* EncryptedStorageMock.swift */; }; 2C60AB0C272564D40040D7F2 /* InvalidStorageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */; }; @@ -462,8 +462,8 @@ 2C2A3B4A2719EE6100B7F27B /* KeyServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyServiceTests.swift; sourceTree = ""; }; 2C2A3B4C2719EF7300B7F27B /* PassPhraseServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhraseServiceMock.swift; sourceTree = ""; }; 2C2B058627A07F7A00A406F0 /* FlowCrypt-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FlowCrypt-Bridging-Header.h"; sourceTree = ""; }; - 2C2B058727A07F7B00A406F0 /* ObjException.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjException.h; sourceTree = ""; }; - 2C2B058827A07F7B00A406F0 /* ObjException.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjException.m; sourceTree = ""; }; + 2C2B058727A07F7B00A406F0 /* ObjcException.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjcException.h; sourceTree = ""; }; + 2C2B058827A07F7B00A406F0 /* ObjcException.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjcException.m; sourceTree = ""; }; 2C2D0B94275FDF6B0052771D /* Version6SchemaMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Version6SchemaMigration.swift; sourceTree = ""; }; 2C4E60F62757D91A00DE5770 /* EncryptedStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedStorageMock.swift; sourceTree = ""; }; 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvalidStorageViewController.swift; sourceTree = ""; }; @@ -1003,8 +1003,8 @@ 2C2B058A27A0809400A406F0 /* ObjC */ = { isa = PBXGroup; children = ( - 2C2B058727A07F7B00A406F0 /* ObjException.h */, - 2C2B058827A07F7B00A406F0 /* ObjException.m */, + 2C2B058727A07F7B00A406F0 /* ObjcException.h */, + 2C2B058827A07F7B00A406F0 /* ObjcException.m */, ); path = ObjC; sourceTree = ""; @@ -2613,7 +2613,7 @@ C192421F1EC48B6900C3D251 /* SetupBackupsViewController.swift in Sources */, 9F0C3C2623194E0A00299985 /* FolderViewModel.swift in Sources */, F8678DCC2722143300BB1710 /* GmailService+draft.swift in Sources */, - 2C2B058927A07F7B00A406F0 /* ObjException.m in Sources */, + 2C2B058927A07F7B00A406F0 /* ObjcException.m in Sources */, 21CE25E62650070300ADFF4B /* WkdUrlConstructor.swift in Sources */, 9FC411212595EA12001180A8 /* MessageSearchProvider.swift in Sources */, 9F778E7E27162038001D4B21 /* MessageThread.swift in Sources */, diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index d3cb03268..e5d59bc83 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -453,20 +453,20 @@ extension InboxViewController: MsgListViewController { } else { state = .fetched(.byNumber(total: newTotalNumber)) do { - try ObjException.catch { + try ObjcException.catch { self.tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) } } catch { - logger.logError("Failed to remove message at \(index) in fetched state") + logger.logError("Failed to remove message at \(index) in fetched state: \(error)") } } default: do { - try ObjException.catch { + try ObjcException.catch { self.tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) } } catch { - logger.logError("Failed to remove message at \(index) in default state") + logger.logError("Failed to remove message at \(index) in default state: \(error)") } } } diff --git a/FlowCrypt/FlowCrypt-Bridging-Header.h b/FlowCrypt/FlowCrypt-Bridging-Header.h index 6df9ada0c..ffb3e1d0b 100644 --- a/FlowCrypt/FlowCrypt-Bridging-Header.h +++ b/FlowCrypt/FlowCrypt-Bridging-Header.h @@ -2,4 +2,4 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // -#import "ObjException.h" +#import "ObjcException.h" diff --git a/FlowCrypt/ObjC/ObjException.m b/FlowCrypt/ObjC/ObjException.m deleted file mode 100644 index e1c8b6942..000000000 --- a/FlowCrypt/ObjC/ObjException.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// ObjException.m -// FlowCrypt -// -// Created by  Ivan Ushakov on 25.01.2022 -// Copyright © 2017-present FlowCrypt a. s. All rights reserved. -// - -#import "ObjException.h" - -@implementation ObjException - -+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error { - @try - { - tryBlock(); - return YES; - } - @catch (NSException *exception) - { - *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:exception.userInfo]; - return NO; - } -} - -@end diff --git a/FlowCrypt/ObjC/ObjException.h b/FlowCrypt/ObjC/ObjcException.h similarity index 84% rename from FlowCrypt/ObjC/ObjException.h rename to FlowCrypt/ObjC/ObjcException.h index b75b08fea..6b34dd152 100644 --- a/FlowCrypt/ObjC/ObjException.h +++ b/FlowCrypt/ObjC/ObjcException.h @@ -1,5 +1,5 @@ // -// ObjException.h +// ObjcException.h // FlowCrypt // // Created by  Ivan Ushakov on 25.01.2022 @@ -10,7 +10,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface ObjException : NSObject +@interface ObjcException : NSObject + (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error; diff --git a/FlowCrypt/ObjC/ObjcException.m b/FlowCrypt/ObjC/ObjcException.m new file mode 100644 index 000000000..70dc7f138 --- /dev/null +++ b/FlowCrypt/ObjC/ObjcException.m @@ -0,0 +1,40 @@ +// +// ObjcException.m +// FlowCrypt +// +// Created by  Ivan Ushakov on 25.01.2022 +// Copyright © 2017-present FlowCrypt a. s. All rights reserved. +// + +#import "ObjcException.h" + +@implementation ObjcException + ++ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error { + @try + { + tryBlock(); + return YES; + } + @catch (NSException *exception) + { + NSMutableDictionary *userInfo = [NSMutableDictionary new]; + if (exception.userInfo != NULL) + { + userInfo = [[NSMutableDictionary alloc] initWithDictionary:exception.userInfo]; + } + + if (exception.reason != nil) + { + if (![userInfo.allKeys containsObject:NSLocalizedFailureReasonErrorKey]) + { + [userInfo setObject:exception.reason forKey:NSLocalizedFailureReasonErrorKey]; + } + } + + *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:userInfo]; + return NO; + } +} + +@end From 0619dd0b702c975cfca1dab7c56cb27191515761 Mon Sep 17 00:00:00 2001 From: Ivan Ushakov Date: Thu, 27 Jan 2022 23:45:11 +0300 Subject: [PATCH 3/3] Change logger to alert --- FlowCrypt/Controllers/Inbox/InboxViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index e5d59bc83..a68b43fd9 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -457,7 +457,7 @@ extension InboxViewController: MsgListViewController { self.tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) } } catch { - logger.logError("Failed to remove message at \(index) in fetched state: \(error)") + showAlert(message: "Failed to remove message at \(index) in fetched state: \(error)") } } default: @@ -466,7 +466,7 @@ extension InboxViewController: MsgListViewController { self.tableNode.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left) } } catch { - logger.logError("Failed to remove message at \(index) in default state: \(error)") + showAlert(message: "Failed to remove message at \(index) in \(state): \(error)") } } }