Updated the alerts to use the custom styled ones
Removed some more unused code Moved around some files to make them more reusable
This commit is contained in:
parent
40109e0bea
commit
37124c2185
|
@ -155,7 +155,6 @@
|
|||
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707F127290ACB002817AD /* SessionCallManager.swift */; };
|
||||
7BCD116C27016062006330F1 /* WebRTCSession+DataChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */; };
|
||||
7BD477A827EC39F5004E2822 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD477A727EC39F5004E2822 /* Atomic.swift */; };
|
||||
7BD477B027F526FF004E2822 /* BlockListUIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD477AF27F526FF004E2822 /* BlockListUIUtils.swift */; };
|
||||
7BDCFC08242186E700641C39 /* NotificationServiceExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */; };
|
||||
7BDCFC0B2421EB7600641C39 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6F509951AA53F760068F56A /* Localizable.strings */; };
|
||||
7BFA8AE32831D0D4001876F3 /* ContextMenuVC+EmojiReactsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFA8AE22831D0D4001876F3 /* ContextMenuVC+EmojiReactsView.swift */; };
|
||||
|
@ -205,7 +204,6 @@
|
|||
B85357C323A1BD1200AAF6CD /* SeedVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B85357C223A1BD1200AAF6CD /* SeedVC.swift */; };
|
||||
B8569AC325CB5D2900DBA3DB /* ConversationVC+Interaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8569AC225CB5D2900DBA3DB /* ConversationVC+Interaction.swift */; };
|
||||
B8569AE325CBB19A00DBA3DB /* DocumentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8569AE225CBB19A00DBA3DB /* DocumentView.swift */; };
|
||||
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; };
|
||||
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08523399CEF000F5AE3 /* SeedModal.swift */; };
|
||||
B877E24226CA12910007970A /* CallVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B877E24126CA12910007970A /* CallVC.swift */; };
|
||||
B877E24626CA13BA0007970A /* CallVC+Camera.swift in Sources */ = {isa = PBXBuildFile; fileRef = B877E24526CA13BA0007970A /* CallVC+Camera.swift */; };
|
||||
|
@ -216,7 +214,6 @@
|
|||
B8856D08256F10F1001CE70E /* DeviceSleepManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38EF309255B6DBE007E1867 /* DeviceSleepManager.swift */; };
|
||||
B8856D11256F112A001CE70E /* OWSAudioSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38EF281255B6D84007E1867 /* OWSAudioSession.swift */; };
|
||||
B8856D23256F116B001CE70E /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38EF2EF255B6DBB007E1867 /* Weak.swift */; };
|
||||
B8856D60256F129B001CE70E /* OWSAlerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8856D5F256F129B001CE70E /* OWSAlerts.swift */; };
|
||||
B8856D72256F1421001CE70E /* OWSWindowManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF2FB255B6DBD007E1867 /* OWSWindowManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF23E255B6D66007E1867 /* UIView+OWS.m */; };
|
||||
B8856D8D256F1502001CE70E /* UIView+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF23D255B6D66007E1867 /* UIView+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -513,7 +510,6 @@
|
|||
D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D24B5BD4169F568C00681372 /* AudioToolbox.framework */; };
|
||||
D2AEACDC16C426DA00C364C0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; };
|
||||
DA2AE22FA77136442EF669E9 /* Pods_GlobalDependencies_Session_SessionTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4C92F6ADBECCD47A6B6008E /* Pods_GlobalDependencies_Session_SessionTests.framework */; };
|
||||
EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */ = {isa = PBXBuildFile; fileRef = EF764C341DB67CC5000D9A87 /* UIViewController+Permissions.m */; };
|
||||
FC3BD9881A30A790005B96BB /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC3BD9871A30A790005B96BB /* Social.framework */; };
|
||||
FCB11D8C1A129A76002F93FB /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB11D8B1A129A76002F93FB /* CoreMedia.framework */; };
|
||||
FD078E4827E02561000769AF /* CommonMockedExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E4727E02561000769AF /* CommonMockedExtensions.swift */; };
|
||||
|
@ -651,7 +647,6 @@
|
|||
FD52090128AF61BA006098F6 /* OWSBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB38255A580B00E217F9 /* OWSBackgroundTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
FD52090328B4680F006098F6 /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090228B4680F006098F6 /* RadioButton.swift */; };
|
||||
FD52090528B4915F006098F6 /* PrivacySettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090428B4915F006098F6 /* PrivacySettingsViewModel.swift */; };
|
||||
FD52090728B49738006098F6 /* ConfirmationModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090628B49738006098F6 /* ConfirmationModal.swift */; };
|
||||
FD52090928B59411006098F6 /* ScreenLockUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090828B59411006098F6 /* ScreenLockUI.swift */; };
|
||||
FD52090B28B59BB4006098F6 /* ScreenLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090A28B59BB4006098F6 /* ScreenLockViewController.swift */; };
|
||||
FD5C72F7284F0E560029977D /* MessageReceiver+ReadReceipts.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5C72F6284F0E560029977D /* MessageReceiver+ReadReceipts.swift */; };
|
||||
|
@ -705,6 +700,8 @@
|
|||
FD71164E28E3F8CC00B47552 /* SessionCell+Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71164D28E3F8CC00B47552 /* SessionCell+Info.swift */; };
|
||||
FD71165028E3F9FA00B47552 /* SessionTableViewModel+NavItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71164F28E3F9FA00B47552 /* SessionTableViewModel+NavItem.swift */; };
|
||||
FD71165228E410BE00B47552 /* SessionTableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71165128E410BE00B47552 /* SessionTableSection.swift */; };
|
||||
FD71165828E436E800B47552 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; };
|
||||
FD71165928E436E800B47552 /* ConfirmationModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090628B49738006098F6 /* ConfirmationModal.swift */; };
|
||||
FD7162DB281B6C440060647B /* TypedTableAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD7162DA281B6C440060647B /* TypedTableAlias.swift */; };
|
||||
FD716E6428502DDD00C96BF4 /* CallManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD716E6328502DDD00C96BF4 /* CallManagerProtocol.swift */; };
|
||||
FD716E6628502EE200C96BF4 /* CurrentCallProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD716E6528502EE200C96BF4 /* CurrentCallProtocol.swift */; };
|
||||
|
@ -1217,7 +1214,6 @@
|
|||
7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebRTCSession+DataChannel.swift"; sourceTree = "<group>"; };
|
||||
7BD477A727EC39F5004E2822 /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
|
||||
7BD477A927F15F24004E2822 /* OpenGroupServerIdLookup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenGroupServerIdLookup.swift; sourceTree = "<group>"; };
|
||||
7BD477AF27F526FF004E2822 /* BlockListUIUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockListUIUtils.swift; sourceTree = "<group>"; };
|
||||
7BDCFC0424206E7300641C39 /* SessionNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SessionNotificationServiceExtension.entitlements; sourceTree = "<group>"; };
|
||||
7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtensionContext.swift; sourceTree = "<group>"; };
|
||||
7BFA8AE22831D0D4001876F3 /* ContextMenuVC+EmojiReactsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContextMenuVC+EmojiReactsView.swift"; sourceTree = "<group>"; };
|
||||
|
@ -1290,7 +1286,6 @@
|
|||
B879D44A247E1D9200DB3608 /* PathStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathStatusView.swift; sourceTree = "<group>"; };
|
||||
B87EF17026367CF800124B3C /* FileServerAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileServerAPI.swift; sourceTree = "<group>"; };
|
||||
B87EF18026377A1D00124B3C /* Features.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Features.swift; sourceTree = "<group>"; };
|
||||
B8856D5F256F129B001CE70E /* OWSAlerts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAlerts.swift; sourceTree = "<group>"; };
|
||||
B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraints.swift"; sourceTree = "<group>"; };
|
||||
B886B4A62398B23E00211ABE /* QRCodeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeVC.swift; sourceTree = "<group>"; };
|
||||
B886B4A82398BA1500211ABE /* QRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCode.swift; sourceTree = "<group>"; };
|
||||
|
@ -1623,8 +1618,6 @@
|
|||
E1A0AD8B16E13FDD0071E604 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
E23C1E6B7E0C12BF4ACD9CBE /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionSnodeKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionSnodeKit.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionSnodeKit/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionSnodeKit.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
EC5C23F9D234F558BE5E41DE /* Pods-SessionUIKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SessionUIKit.debug.xcconfig"; path = "Target Support Files/Pods-SessionUIKit/Pods-SessionUIKit.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
EF764C331DB67CC5000D9A87 /* UIViewController+Permissions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Permissions.h"; sourceTree = "<group>"; };
|
||||
EF764C341DB67CC5000D9A87 /* UIViewController+Permissions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Permissions.m"; sourceTree = "<group>"; };
|
||||
F705826F79C4A591AB35D68F /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
FC3BD9871A30A790005B96BB /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; };
|
||||
FCB11D8B1A129A76002F93FB /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
|
||||
|
@ -1692,7 +1685,6 @@
|
|||
FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUKLegacy.swift; sourceTree = "<group>"; };
|
||||
FD1C98E3282E3C5B00B76F9E /* UINavigationBar+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationBar+Utilities.swift"; sourceTree = "<group>"; };
|
||||
FD245C612850664300B966DD /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
|
||||
FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListUIUtils.swift; sourceTree = "<group>"; };
|
||||
FD28A4F527EAD44C00FF65E7 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = "<group>"; };
|
||||
FD37E9C228A1C6F3003AE748 /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
|
||||
FD37E9C528A1D4EC003AE748 /* Theme+ClassicDark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Theme+ClassicDark.swift"; sourceTree = "<group>"; };
|
||||
|
@ -2196,8 +2188,6 @@
|
|||
FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */,
|
||||
45C0DC1A1E68FE9000E04C47 /* UIApplication+OWS.swift */,
|
||||
45C0DC1D1E69011F00E04C47 /* UIStoryboard+OWS.swift */,
|
||||
EF764C331DB67CC5000D9A87 /* UIViewController+Permissions.h */,
|
||||
EF764C341DB67CC5000D9A87 /* UIViewController+Permissions.m */,
|
||||
45B5360D206DD8BB00D61655 /* UIResponder+OWS.swift */,
|
||||
4C586924224FAB83003FD070 /* AVAudioSession+OWS.h */,
|
||||
4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */,
|
||||
|
@ -2828,6 +2818,8 @@
|
|||
7BBBDC43286EAD2D00747E59 /* TappableLabel.swift */,
|
||||
FD09B7E228865FDA00ED0B66 /* HighlightMentionBackgroundView.swift */,
|
||||
C38EF3EE255B6DF6007E1867 /* GradientView.swift */,
|
||||
B86BD08323399ACF000F5AE3 /* Modal.swift */,
|
||||
FD52090628B49738006098F6 /* ConfirmationModal.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2837,7 +2829,6 @@
|
|||
children = (
|
||||
C33FD9B7255A54A300E217F9 /* Meta */,
|
||||
C36096ED25AD20FD008B62B2 /* Media Viewing & Editing */,
|
||||
C38BBA0D255E321C0041B9A3 /* Messaging */,
|
||||
C36096EF25AD2268008B62B2 /* Profile Pictures */,
|
||||
C36096EE25AD21BC008B62B2 /* Screen Lock */,
|
||||
C3851CD225624B060061EEB0 /* Shared Views */,
|
||||
|
@ -2944,15 +2935,6 @@
|
|||
path = "Closed Groups";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C36096AF25AD1932008B62B2 /* Sheets & Modals */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B86BD08323399ACF000F5AE3 /* Modal.swift */,
|
||||
FD52090628B49738006098F6 /* ConfirmationModal.swift */,
|
||||
);
|
||||
path = "Sheets & Modals";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C36096B925AD1ACF008B62B2 /* GIFs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3106,15 +3088,6 @@
|
|||
path = "Shared Views";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C38BBA0D255E321C0041B9A3 /* Messaging */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */,
|
||||
7BD477AF27F526FF004E2822 /* BlockListUIUtils.swift */,
|
||||
);
|
||||
path = Messaging;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C3A721332558BDDF0043A11F /* Open Groups */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3328,7 +3301,6 @@
|
|||
C38EF3E4255B6DF4007E1867 /* CommonStrings.swift */,
|
||||
C38EF304255B6DBE007E1867 /* ImageCache.swift */,
|
||||
C38EF2F2255B6DBC007E1867 /* Searcher.swift */,
|
||||
B8856D5F256F129B001CE70E /* OWSAlerts.swift */,
|
||||
C3F0A52F255C80BC007BE2A3 /* NoopNotificationsManager.swift */,
|
||||
C33FDA8B255A57FD00E217F9 /* AppVersion.m */,
|
||||
C33FDB69255A580F00E217F9 /* FeatureFlags.swift */,
|
||||
|
@ -3506,7 +3478,6 @@
|
|||
C360969A25AD17E3008B62B2 /* Path */,
|
||||
C360969125AD1765008B62B2 /* Settings */,
|
||||
B8CCF63B239757C10091D419 /* Shared */,
|
||||
C36096AF25AD1932008B62B2 /* Sheets & Modals */,
|
||||
76EB03C118170B33006006FC /* Utilities */,
|
||||
);
|
||||
path = Session;
|
||||
|
@ -5142,7 +5113,9 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C331FF972558FA6B00070591 /* Fonts.swift in Sources */,
|
||||
FD71165828E436E800B47552 /* Modal.swift in Sources */,
|
||||
FD37E9D328A1FCDB003AE748 /* Theme+OceanDark.swift in Sources */,
|
||||
FD71165928E436E800B47552 /* ConfirmationModal.swift in Sources */,
|
||||
7BBBDC44286EAD2D00747E59 /* TappableLabel.swift in Sources */,
|
||||
FD09B7E328865FDA00ED0B66 /* HighlightMentionBackgroundView.swift in Sources */,
|
||||
C331FFB82558FA8D00070591 /* DeviceUtilities.swift in Sources */,
|
||||
|
@ -5237,7 +5210,6 @@
|
|||
C38EF3C0255B6DE7007E1867 /* ImageEditorCropViewController.swift in Sources */,
|
||||
FD52090B28B59BB4006098F6 /* ScreenLockViewController.swift in Sources */,
|
||||
C38EF401255B6DF7007E1867 /* VideoPlayerView.swift in Sources */,
|
||||
B8856D60256F129B001CE70E /* OWSAlerts.swift in Sources */,
|
||||
C38EF3BD255B6DE7007E1867 /* ImageEditorTransform.swift in Sources */,
|
||||
C38EF24F255B6D67007E1867 /* UIColor+OWS.m in Sources */,
|
||||
C33FDC9A255A582000E217F9 /* ByteParser.m in Sources */,
|
||||
|
@ -5245,7 +5217,6 @@
|
|||
C33FDC78255A582000E217F9 /* TSConstants.m in Sources */,
|
||||
C38EF324255B6DBF007E1867 /* Bench.swift in Sources */,
|
||||
FDCDB8DE2810F73B00352A0C /* Differentiable+Utilities.swift in Sources */,
|
||||
7BD477B027F526FF004E2822 /* BlockListUIUtils.swift in Sources */,
|
||||
C38EF3F9255B6DF7007E1867 /* OWSLayerView.swift in Sources */,
|
||||
C33FDD03255A582000E217F9 /* WeakTimer.swift in Sources */,
|
||||
C38EF3B9255B6DE7007E1867 /* ImageEditorPinchGestureRecognizer.swift in Sources */,
|
||||
|
@ -5621,7 +5592,6 @@
|
|||
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */,
|
||||
B82B408A2399EC0600A248E7 /* FakeChatView.swift in Sources */,
|
||||
B82B40882399EB0E00A248E7 /* LandingVC.swift in Sources */,
|
||||
EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */,
|
||||
45CD81EF1DC030E7004C9430 /* SyncPushTokensJob.swift in Sources */,
|
||||
B83524A525C3BA4B0089A44F /* InfoMessageCell.swift in Sources */,
|
||||
7B9F71D82853100A006DFE7B /* EmojiWithSkinTones.swift in Sources */,
|
||||
|
@ -5672,7 +5642,6 @@
|
|||
7B46AAAF28766DF4001AF2DC /* AllMediaViewController.swift in Sources */,
|
||||
FD71162228D983ED00B47552 /* QRCodeScanningViewController.swift in Sources */,
|
||||
C331FFFE2558FF3B00070591 /* FullConversationCell.swift in Sources */,
|
||||
FD52090728B49738006098F6 /* ConfirmationModal.swift in Sources */,
|
||||
B8D84EA325DF745A005A043E /* LinkPreviewState.swift in Sources */,
|
||||
45C0DC1E1E69011F00E04C47 /* UIStoryboard+OWS.swift in Sources */,
|
||||
B82B408E239DC00D00A248E7 /* DisplayNameVC.swift in Sources */,
|
||||
|
@ -5783,7 +5752,6 @@
|
|||
C328251F25CA3A900062D0A7 /* QuoteView.swift in Sources */,
|
||||
FD37E9CC28A1E578003AE748 /* AppearanceViewController.swift in Sources */,
|
||||
B8EB20F02640F7F000773E52 /* OpenGroupInvitationView.swift in Sources */,
|
||||
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */,
|
||||
C328254025CA55880062D0A7 /* ContextMenuVC.swift in Sources */,
|
||||
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */,
|
||||
B8269D2925C7A4B400488AB4 /* InputView.swift in Sources */,
|
||||
|
|
|
@ -454,8 +454,15 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
|
|||
// MARK: - Convenience
|
||||
|
||||
private func showError(title: String, message: String = "") {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: title,
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -296,7 +296,7 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
|
|||
title: title,
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
present(modal, animated: true)
|
||||
|
@ -334,11 +334,16 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
|
|||
.catch(on: DispatchQueue.main) { [weak self] _ in
|
||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||
|
||||
let title = "Couldn't Create Group"
|
||||
let message = "Please check your internet connection and try again."
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
self?.presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Couldn't Create Group",
|
||||
explanation: "Please check your internet connection and try again.",
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
.retainUntilComplete()
|
||||
}
|
||||
|
|
|
@ -262,29 +262,49 @@ extension ConversationVC:
|
|||
}
|
||||
catch {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
let alert = UIAlertController(title: "Session", message: "An error occurred.", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
||||
|
||||
self?.present(alert, animated: true, completion: nil)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Session",
|
||||
explanation: "An error occurred.",
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let type = urlResourceValues.typeIdentifier ?? (kUTTypeData as String)
|
||||
guard urlResourceValues.isDirectory != true else {
|
||||
DispatchQueue.main.async {
|
||||
OWSAlerts.showAlert(
|
||||
title: "ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE".localized(),
|
||||
message: "ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY".localized()
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE".localized(),
|
||||
explanation: "ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let fileName = urlResourceValues.name ?? NSLocalizedString("ATTACHMENT_DEFAULT_FILENAME", comment: "")
|
||||
guard let dataSource = DataSourcePath.dataSource(with: url, shouldDeleteOnDeallocation: false) else {
|
||||
DispatchQueue.main.async {
|
||||
OWSAlerts.showAlert(title: "ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE".localized())
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -364,7 +384,7 @@ extension ConversationVC:
|
|||
explanation: "modal_send_seed_explanation".localized(),
|
||||
confirmTitle: "modal_send_seed_send_button_title".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
onConfirm: { [weak self] _ in self?.sendMessage(hasPermissionToSendSeed: true) }
|
||||
)
|
||||
)
|
||||
|
@ -487,7 +507,7 @@ extension ConversationVC:
|
|||
explanation: "modal_send_seed_explanation".localized(),
|
||||
confirmTitle: "modal_send_seed_send_button_title".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
onConfirm: { [weak self] _ in
|
||||
self?.sendAttachments(attachments, with: text, hasPermissionToSendSeed: true, onComplete: onComplete)
|
||||
}
|
||||
|
@ -1000,24 +1020,25 @@ extension ConversationVC:
|
|||
guard let url: URL = URL(string: urlString) else { return }
|
||||
|
||||
// URLs can be unsafe, so always ask the user whether they want to open one
|
||||
let alertVC = UIAlertController(
|
||||
let actionSheet: UIAlertController = UIAlertController(
|
||||
title: "modal_open_url_title".localized(),
|
||||
message: String(format: "modal_open_url_explanation".localized(), url.absoluteString),
|
||||
preferredStyle: .actionSheet
|
||||
)
|
||||
alertVC.addAction(UIAlertAction(title: "modal_open_url_button_title".localized(), style: .default) { [weak self] _ in
|
||||
actionSheet.addAction(UIAlertAction(title: "modal_open_url_button_title".localized(), style: .default) { [weak self] _ in
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
self?.showInputAccessoryView()
|
||||
})
|
||||
alertVC.addAction(UIAlertAction(title: "modal_copy_url_button_title".localized(), style: .default) { [weak self] _ in
|
||||
actionSheet.addAction(UIAlertAction(title: "modal_copy_url_button_title".localized(), style: .default) { [weak self] _ in
|
||||
UIPasteboard.general.string = url.absoluteString
|
||||
self?.showInputAccessoryView()
|
||||
})
|
||||
alertVC.addAction(UIAlertAction(title: "cancel".localized(), style: .cancel) { [weak self] _ in
|
||||
actionSheet.addAction(UIAlertAction(title: "cancel".localized(), style: .cancel) { [weak self] _ in
|
||||
self?.showInputAccessoryView()
|
||||
})
|
||||
|
||||
self.presentAlert(alertVC)
|
||||
Modal.setupForIPadIfNeeded(actionSheet, targetView: self.view)
|
||||
self.present(actionSheet, animated: true)
|
||||
}
|
||||
|
||||
func handleReplyButtonTapped(for cellViewModel: MessageViewModel) {
|
||||
|
@ -1474,7 +1495,7 @@ extension ConversationVC:
|
|||
info: ConfirmationModal.Info(
|
||||
title: "Couldn't Join",
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -1502,7 +1523,7 @@ extension ConversationVC:
|
|||
title: "Couldn't Join",
|
||||
explanation: error.localizedDescription,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -1746,8 +1767,8 @@ extension ConversationVC:
|
|||
return
|
||||
}
|
||||
|
||||
let alertVC = UIAlertController.init(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
alertVC.addAction(UIAlertAction(title: "delete_message_for_me".localized(), style: .destructive) { [weak self] _ in
|
||||
let actionSheet: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
actionSheet.addAction(UIAlertAction(title: "delete_message_for_me".localized(), style: .destructive) { [weak self] _ in
|
||||
Storage.shared.writeAsync { db in
|
||||
_ = try Interaction
|
||||
.filter(id: cellViewModel.id)
|
||||
|
@ -1765,7 +1786,7 @@ extension ConversationVC:
|
|||
self?.showInputAccessoryView()
|
||||
})
|
||||
|
||||
alertVC.addAction(UIAlertAction(
|
||||
actionSheet.addAction(UIAlertAction(
|
||||
title: (cellViewModel.threadVariant == .closedGroup ?
|
||||
"delete_message_for_everyone".localized() :
|
||||
String(format: "delete_message_for_me_and_recipient".localized(), threadName)
|
||||
|
@ -1799,13 +1820,14 @@ extension ConversationVC:
|
|||
}
|
||||
})
|
||||
|
||||
alertVC.addAction(UIAlertAction.init(title: "TXT_CANCEL_TITLE".localized(), style: .cancel) { [weak self] _ in
|
||||
actionSheet.addAction(UIAlertAction.init(title: "TXT_CANCEL_TITLE".localized(), style: .cancel) { [weak self] _ in
|
||||
self?.showInputAccessoryView()
|
||||
})
|
||||
|
||||
self.inputAccessoryView?.isHidden = true
|
||||
self.inputAccessoryView?.alpha = 0
|
||||
self.presentAlert(alertVC)
|
||||
Modal.setupForIPadIfNeeded(actionSheet, targetView: self.view)
|
||||
self.present(actionSheet, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1871,78 +1893,98 @@ extension ConversationVC:
|
|||
guard cellViewModel.threadVariant == .openGroup else { return }
|
||||
|
||||
let threadId: String = self.viewModel.threadData.threadId
|
||||
let alert: UIAlertController = UIAlertController(
|
||||
title: "Session",
|
||||
message: "This will ban the selected user from this room. It won't ban them from other rooms.",
|
||||
preferredStyle: .alert
|
||||
)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in
|
||||
Storage.shared
|
||||
.read { db -> Promise<Void> in
|
||||
guard let openGroup: OpenGroup = try OpenGroup.fetchOne(db, id: threadId) else {
|
||||
return Promise(error: StorageError.objectNotFound)
|
||||
}
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Session",
|
||||
explanation: "This will ban the selected user from this room. It won't ban them from other rooms.",
|
||||
confirmTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text,
|
||||
onConfirm: { [weak self] _ in
|
||||
Storage.shared
|
||||
.read { db -> Promise<Void> in
|
||||
guard let openGroup: OpenGroup = try OpenGroup.fetchOne(db, id: threadId) else {
|
||||
return Promise(error: StorageError.objectNotFound)
|
||||
}
|
||||
|
||||
return OpenGroupAPI
|
||||
.userBan(
|
||||
db,
|
||||
sessionId: cellViewModel.authorId,
|
||||
from: [openGroup.roomToken],
|
||||
on: openGroup.server
|
||||
)
|
||||
.map { _ in () }
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { _ in
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: CommonStrings.errorAlertTitle,
|
||||
explanation: "context_menu_ban_user_error_alert_message".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
.retainUntilComplete()
|
||||
|
||||
return OpenGroupAPI
|
||||
.userBan(
|
||||
db,
|
||||
sessionId: cellViewModel.authorId,
|
||||
from: [openGroup.roomToken],
|
||||
on: openGroup.server
|
||||
)
|
||||
.map { _ in () }
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { _ in
|
||||
OWSAlerts.showErrorAlert(message: "context_menu_ban_user_error_alert_message".localized())
|
||||
}
|
||||
.retainUntilComplete()
|
||||
|
||||
self?.becomeFirstResponder()
|
||||
}))
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { [weak self] _ in
|
||||
self?.becomeFirstResponder()
|
||||
}))
|
||||
|
||||
present(alert, animated: true, completion: nil)
|
||||
self?.becomeFirstResponder()
|
||||
},
|
||||
afterClosed: { [weak self] in self?.becomeFirstResponder() }
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
|
||||
func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel) {
|
||||
guard cellViewModel.threadVariant == .openGroup else { return }
|
||||
|
||||
let threadId: String = self.viewModel.threadData.threadId
|
||||
let alert: UIAlertController = UIAlertController(
|
||||
title: "Session",
|
||||
message: "This will ban the selected user from this room and delete all messages sent by them. It won't ban them from other rooms or delete the messages they sent there.",
|
||||
preferredStyle: .alert
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Session",
|
||||
explanation: "This will ban the selected user from this room and delete all messages sent by them. It won't ban them from other rooms or delete the messages they sent there.",
|
||||
confirmTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text,
|
||||
onConfirm: { [weak self] _ in
|
||||
Storage.shared
|
||||
.read { db -> Promise<Void> in
|
||||
guard let openGroup: OpenGroup = try OpenGroup.fetchOne(db, id: threadId) else {
|
||||
return Promise(error: StorageError.objectNotFound)
|
||||
}
|
||||
|
||||
return OpenGroupAPI
|
||||
.userBanAndDeleteAllMessages(
|
||||
db,
|
||||
sessionId: cellViewModel.authorId,
|
||||
in: openGroup.roomToken,
|
||||
on: openGroup.server
|
||||
)
|
||||
.map { _ in () }
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { _ in
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: CommonStrings.errorAlertTitle,
|
||||
explanation: "context_menu_ban_user_error_alert_message".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
.retainUntilComplete()
|
||||
|
||||
self?.becomeFirstResponder()
|
||||
},
|
||||
afterClosed: { [weak self] in self?.becomeFirstResponder() }
|
||||
)
|
||||
)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in
|
||||
Storage.shared
|
||||
.read { db -> Promise<Void> in
|
||||
guard let openGroup: OpenGroup = try OpenGroup.fetchOne(db, id: threadId) else {
|
||||
return Promise(error: StorageError.objectNotFound)
|
||||
}
|
||||
|
||||
return OpenGroupAPI
|
||||
.userBanAndDeleteAllMessages(
|
||||
db,
|
||||
sessionId: cellViewModel.authorId,
|
||||
in: openGroup.roomToken,
|
||||
on: openGroup.server
|
||||
)
|
||||
.map { _ in () }
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { _ in
|
||||
OWSAlerts.showErrorAlert(message: "context_menu_ban_user_error_alert_message".localized())
|
||||
}
|
||||
.retainUntilComplete()
|
||||
|
||||
self?.becomeFirstResponder()
|
||||
}))
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { [weak self] _ in
|
||||
self?.becomeFirstResponder()
|
||||
}))
|
||||
|
||||
present(alert, animated: true, completion: nil)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - VoiceMessageRecordingViewDelegate
|
||||
|
@ -2032,10 +2074,16 @@ extension ConversationVC:
|
|||
guard duration > 1 else {
|
||||
self.audioRecorder = nil
|
||||
|
||||
OWSAlerts.showAlert(
|
||||
title: "VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE".localized(),
|
||||
message: "VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE".localized()
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE".localized(),
|
||||
explanation: "VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -2096,13 +2144,17 @@ extension ConversationVC:
|
|||
// MARK: - Convenience
|
||||
|
||||
func showErrorAlert(for attachment: SignalAttachment, onDismiss: (() -> ())?) {
|
||||
OWSAlerts.showAlert(
|
||||
title: "ATTACHMENT_ERROR_ALERT_TITLE".localized(),
|
||||
message: (attachment.localizedErrorDescription ?? SignalAttachment.missingDataErrorMessage),
|
||||
buttonTitle: nil
|
||||
) { _ in
|
||||
onDismiss?()
|
||||
}
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "ATTACHMENT_ERROR_ALERT_TITLE".localized(),
|
||||
explanation: (attachment.localizedErrorDescription ?? SignalAttachment.missingDataErrorMessage),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text,
|
||||
afterClosed: onDismiss
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1181,9 +1181,18 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
|
|||
with: cellViewModel,
|
||||
mediaCache: mediaCache,
|
||||
playbackInfo: viewModel.playbackInfo(for: cellViewModel) { updatedInfo, error in
|
||||
DispatchQueue.main.async {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard error == nil else {
|
||||
OWSAlerts.showErrorAlert(message: "INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE".localized())
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: CommonStrings.errorAlertTitle,
|
||||
explanation: "INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -380,7 +380,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
|
|||
),
|
||||
confirmTitle: "LEAVE_BUTTON_TITLE".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
),
|
||||
onTap: { [weak self] in
|
||||
Storage.shared.writeAsync { db in
|
||||
|
@ -515,7 +515,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
|
|||
"BLOCK_LIST_BLOCK_BUTTON".localized()
|
||||
),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
),
|
||||
onTap: {
|
||||
let isBlocked: Bool = (threadViewModel.threadIsBlocked == true)
|
||||
|
@ -646,7 +646,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
|
|||
nil
|
||||
),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -623,7 +623,7 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
|
|||
),
|
||||
confirmTitle: "TXT_DELETE_TITLE".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
dismissOnConfirm: true,
|
||||
onConfirm: { [weak self] _ in
|
||||
self?.viewModel.delete(
|
||||
|
|
|
@ -196,9 +196,17 @@ final class NewDMVC: BaseVC, UIPageViewControllerDataSource, UIPageViewControlle
|
|||
"Please check the Session ID or ONS name and try again"
|
||||
)
|
||||
}()
|
||||
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
self?.presentAlert(alert)
|
||||
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Error",
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -385,24 +385,20 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
|
|||
strongSelf.delegate?.gifPickerDidSelect(attachment: attachment)
|
||||
}
|
||||
}.catch { [weak self] error in
|
||||
guard let strongSelf = self else {
|
||||
Logger.info("ignoring failure, since VC was dismissed before fetching finished.")
|
||||
return
|
||||
}
|
||||
|
||||
let alert = UIAlertController(
|
||||
title: "GIF_PICKER_FAILURE_ALERT_TITLE".localized(),
|
||||
message: error.localizedDescription,
|
||||
preferredStyle: .alert
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "GIF_PICKER_FAILURE_ALERT_TITLE".localized(),
|
||||
explanation: error.localizedDescription,
|
||||
confirmTitle: CommonStrings.retryButton,
|
||||
cancelTitle: CommonStrings.dismissButton,
|
||||
cancelStyle: .alert_text,
|
||||
onConfirm: { _ in
|
||||
self?.getFileForCell(cell)
|
||||
}
|
||||
)
|
||||
)
|
||||
alert.addAction(UIAlertAction(title: CommonStrings.retryButton, style: .default) { _ in
|
||||
strongSelf.getFileForCell(cell)
|
||||
})
|
||||
alert.addAction(UIAlertAction(title: CommonStrings.dismissButton, style: .cancel) { _ in
|
||||
strongSelf.dismiss(animated: true, completion: nil)
|
||||
})
|
||||
|
||||
strongSelf.presentAlert(alert)
|
||||
self?.present(modal, animated: true)
|
||||
}.retainUntilComplete()
|
||||
}
|
||||
|
||||
|
@ -458,7 +454,16 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
|
|||
|
||||
guard let text: String = searchBar.text else {
|
||||
// Alert message shown when user tries to search for GIFs without entering any search terms
|
||||
OWSAlerts.showErrorAlert(message: "GIF_PICKER_VIEW_MISSING_QUERY".localized())
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: CommonStrings.errorAlertTitle,
|
||||
explanation: "GIF_PICKER_VIEW_MISSING_QUERY".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -584,10 +584,11 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
|||
.deleteAll(db)
|
||||
}
|
||||
}
|
||||
actionSheet.addAction(OWSAlerts.cancelAction)
|
||||
actionSheet.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel))
|
||||
actionSheet.addAction(deleteAction)
|
||||
|
||||
self.presentAlert(actionSheet)
|
||||
Modal.setupForIPadIfNeeded(actionSheet, targetView: self.view)
|
||||
self.present(actionSheet, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - Video interaction
|
||||
|
|
|
@ -708,9 +708,10 @@ public class MediaTileViewController: UIViewController, UICollectionViewDataSour
|
|||
|
||||
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
actionSheet.addAction(deleteAction)
|
||||
actionSheet.addAction(OWSAlerts.cancelAction)
|
||||
actionSheet.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel))
|
||||
|
||||
presentAlert(actionSheet)
|
||||
Modal.setupForIPadIfNeeded(actionSheet, targetView: self.view)
|
||||
self.present(actionSheet, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -317,7 +317,7 @@ class PhotoCaptureViewController: OWSViewController {
|
|||
title: CommonStrings.errorAlertTitle,
|
||||
explanation: error.localizedDescription,
|
||||
cancelTitle: CommonStrings.dismissButton,
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
afterClosed: { [weak self] in self?.dismiss(animated: true) }
|
||||
)
|
||||
)
|
||||
|
|
|
@ -132,19 +132,15 @@ class SendMediaNavigationController: OWSNavigationController {
|
|||
}
|
||||
|
||||
private func didTapCameraModeButton() {
|
||||
self.ows_ask(forCameraPermissions: { granted in
|
||||
if (granted) {
|
||||
self.fadeTo(viewControllers: [self.captureViewController])
|
||||
}
|
||||
})
|
||||
Permissions.requestCameraPermissionIfNeeded { [weak self] in
|
||||
self?.fadeTo(viewControllers: ((self?.captureViewController).map { [$0] } ?? []))
|
||||
}
|
||||
}
|
||||
|
||||
private func didTapMediaLibraryModeButton() {
|
||||
self.ows_ask(forMediaLibraryPermissions: { granted in
|
||||
if (granted) {
|
||||
self.fadeTo(viewControllers: [self.mediaLibraryViewController])
|
||||
}
|
||||
})
|
||||
Permissions.requestLibraryPermissionIfNeeded { [weak self] in
|
||||
self?.fadeTo(viewControllers: ((self?.mediaLibraryViewController).map { [$0] } ?? []))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Views
|
||||
|
@ -265,7 +261,7 @@ class SendMediaNavigationController: OWSNavigationController {
|
|||
title: "SEND_MEDIA_ABANDON_TITLE".localized(),
|
||||
confirmTitle: "SEND_MEDIA_CONFIRM_ABANDON_ALBUM".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
onConfirm: { [weak self] _ in
|
||||
self?.sendMediaNavDelegate?.sendMediaNavDidCancel(self)
|
||||
}
|
||||
|
@ -354,8 +350,16 @@ extension SendMediaNavigationController: ImagePickerGridControllerDelegate {
|
|||
}
|
||||
.catch { error in
|
||||
Logger.error("failed to prepare attachments. error: \(error)")
|
||||
modal.dismiss {
|
||||
OWSAlerts.showAlert(title: NSLocalizedString("IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS", comment: "alert title"))
|
||||
modal.dismiss { [weak self] in
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
}
|
||||
.retainUntilComplete()
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#import "OWSNavigationController.h"
|
||||
#import "OWSWindowManager.h"
|
||||
#import "MainAppContext.h"
|
||||
#import "UIViewController+Permissions.h"
|
||||
#import <PureLayout/PureLayout.h>
|
||||
#import <Reachability/Reachability.h>
|
||||
#import <SignalCoreKit/Cryptography.h>
|
||||
|
|
|
@ -152,16 +152,23 @@ final class DisplayNameVC: BaseVC {
|
|||
|
||||
@objc private func register() {
|
||||
func showError(title: String, message: String = "") {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil))
|
||||
presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: title,
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
let displayName = displayNameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
||||
guard !displayName.isEmpty else {
|
||||
return showError(title: NSLocalizedString("vc_display_name_display_name_missing_error", comment: ""))
|
||||
return showError(title: "vc_display_name_display_name_missing_error".localized())
|
||||
}
|
||||
guard !ProfileManager.isToLong(profileName: displayName) else {
|
||||
return showError(title: NSLocalizedString("vc_display_name_display_name_too_long_error", comment: ""))
|
||||
return showError(title: "vc_display_name_display_name_too_long_error".localized())
|
||||
}
|
||||
|
||||
// Try to save the user name but ignore the result
|
||||
|
|
|
@ -143,7 +143,7 @@ final class LinkDeviceVC: BaseVC, UIPageViewControllerDataSource, UIPageViewCont
|
|||
title: "invalid_recovery_phrase".localized(),
|
||||
explanation: "INVALID_RECOVERY_PHRASE_MESSAGE".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
afterClosed: { [weak self] in
|
||||
self?.scanQRCodeWrapperVC.startCapture()
|
||||
}
|
||||
|
@ -308,9 +308,16 @@ private final class RecoveryPhraseVC: UIViewController {
|
|||
|
||||
@objc private func handleContinueButtonTapped() {
|
||||
func showError(title: String, message: String = "") {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: title,
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
let mnemonic = mnemonicTextView.text!.lowercased()
|
||||
do {
|
||||
|
|
|
@ -115,10 +115,16 @@ final class PNModeVC: BaseVC, OptionViewDelegate {
|
|||
|
||||
@objc private func register() {
|
||||
guard selectedOptionView != nil else {
|
||||
let title = "vc_pn_mode_no_option_picked_modal_title".localized()
|
||||
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
return presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "vc_pn_mode_no_option_picked_modal_title".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
return
|
||||
}
|
||||
UserDefaults.standard[.isUsingFullAPNs] = (selectedOptionView == apnsOptionView)
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ final class RestoreVC: BaseVC {
|
|||
title: title,
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
present(modal, animated: true)
|
||||
|
|
|
@ -199,7 +199,7 @@ final class JoinOpenGroupVC: BaseVC, UIPageViewControllerDataSource, UIPageViewC
|
|||
title: title,
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.navigationController?.present(confirmationModal, animated: true, completion: nil)
|
||||
|
|
|
@ -487,7 +487,7 @@ class BlockedContactsViewController: BaseVC, UITableViewDelegate, UITableViewDat
|
|||
title: confirmationTitle,
|
||||
confirmTitle: "CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
) { _ in
|
||||
// Unblock the contacts
|
||||
Storage.shared.write { db in
|
||||
|
|
|
@ -138,7 +138,7 @@ final class NukeDataModal: Modal {
|
|||
explanation: "modal_clear_all_data_explanation_2".localized(),
|
||||
confirmTitle: "modal_clear_all_data_confirm".localized(),
|
||||
confirmStyle: .danger,
|
||||
cancelStyle: .textPrimary,
|
||||
cancelStyle: .alert_text,
|
||||
dismissOnConfirm: false
|
||||
) { [weak self] confirmationModal in
|
||||
self?.clearEntireAccount(presentedViewController: confirmationModal)
|
||||
|
@ -180,18 +180,31 @@ final class NukeDataModal: Modal {
|
|||
message = String(format: "dialog_clear_all_data_deletion_failed_2".localized(), String(potentiallyMaliciousSnodes.count), potentiallyMaliciousSnodes.joined(separator: ", "))
|
||||
}
|
||||
|
||||
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
|
||||
self?.presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Error",
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { error in
|
||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||
|
||||
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
self?.presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Error",
|
||||
explanation: error.localizedDescription,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self?.present(modal, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,11 +124,16 @@ final class QRCodeVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControl
|
|||
|
||||
fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String) {
|
||||
if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) {
|
||||
let alert = UIAlertController(
|
||||
title: "invalid_session_id".localized(),
|
||||
message: "INVALID_SESSION_ID_MESSAGE".localized(), preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
||||
presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "invalid_session_id".localized(),
|
||||
explanation: "INVALID_SESSION_ID_MESSAGE".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
else {
|
||||
let maybeThread: SessionThread? = Storage.shared.write { db in
|
||||
|
|
|
@ -89,7 +89,7 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
|
|||
info: ConfirmationModal.Info(
|
||||
title: "vc_settings_display_name_missing_error".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
),
|
||||
transitionType: .present
|
||||
|
@ -102,7 +102,7 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
|
|||
info: ConfirmationModal.Info(
|
||||
title: "vc_settings_display_name_too_long_error".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
),
|
||||
transitionType: .present
|
||||
|
@ -479,7 +479,7 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
|
|||
"Please check your internet connection and try again"
|
||||
),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .textPrimary
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
),
|
||||
transitionType: .present
|
||||
|
|
|
@ -272,13 +272,17 @@ class ScreenLockUI {
|
|||
}
|
||||
|
||||
private func showScreenLockFailureAlert(message: String) {
|
||||
OWSAlerts.showAlert(
|
||||
title: "SCREEN_LOCK_UNLOCK_FAILED".localized(),
|
||||
message: message,
|
||||
buttonTitle: nil,
|
||||
buttonAction: { [weak self] _ in self?.ensureUI() }, // After the alert, update the UI
|
||||
fromViewController: screenBlockingWindow.rootViewController
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: screenBlockingWindow.rootViewController?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "SCREEN_LOCK_UNLOCK_FAILED".localized(),
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text,
|
||||
afterClosed: { [weak self] in self?.ensureUI() } // After the alert, update the UI
|
||||
)
|
||||
)
|
||||
screenBlockingWindow.rootViewController?.present(modal, animated: true)
|
||||
}
|
||||
|
||||
/// 'Screen Blocking' window obscures the app screen:
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIViewController (Permissions)
|
||||
|
||||
- (void)ows_askForCameraPermissions:(void (^)(BOOL granted))callback;
|
||||
- (void)ows_askForMediaLibraryPermissions:(void (^)(BOOL granted))callbackParam;
|
||||
- (void)ows_askForMicrophonePermissions:(void (^)(BOOL granted))callback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,175 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIViewController+Permissions.h"
|
||||
#import "Session-Swift.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <Photos/Photos.h>
|
||||
#import <SignalCoreKit/Threading.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation UIViewController (Permissions)
|
||||
|
||||
- (void)ows_askForCameraPermissions:(void (^)(BOOL granted))callbackParam
|
||||
{
|
||||
OWSLogVerbose(@"[%@] ows_askForCameraPermissions", NSStringFromClass(self.class));
|
||||
|
||||
// Ensure callback is invoked on main thread.
|
||||
void (^callback)(BOOL) = ^(BOOL granted) {
|
||||
DispatchMainThreadSafe(^{
|
||||
callbackParam(granted);
|
||||
});
|
||||
};
|
||||
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
|
||||
OWSLogError(@"Skipping camera permissions request when app is in background.");
|
||||
callback(NO);
|
||||
return;
|
||||
}
|
||||
|
||||
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
|
||||
OWSLogError(@"Camera ImagePicker source not available");
|
||||
callback(NO);
|
||||
return;
|
||||
}
|
||||
|
||||
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
if (status == AVAuthorizationStatusDenied) {
|
||||
UIAlertController *alert = [UIAlertController
|
||||
alertControllerWithTitle:NSLocalizedString(@"Session needs camera access to scan QR codes.", @"")
|
||||
message:NSLocalizedString(@"You can enable camera access in your device settings.", @"")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *openSettingsAction =
|
||||
[UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[[UIApplication sharedApplication] openSystemSettings];
|
||||
callback(NO);
|
||||
}];
|
||||
[alert addAction:openSettingsAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.dismissButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action) {
|
||||
callback(NO);
|
||||
}];
|
||||
[alert addAction:dismissAction];
|
||||
|
||||
[self presentAlert:alert];
|
||||
} else if (status == AVAuthorizationStatusAuthorized) {
|
||||
callback(YES);
|
||||
} else if (status == AVAuthorizationStatusNotDetermined) {
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
|
||||
completionHandler:callback];
|
||||
} else {
|
||||
OWSLogError(@"Unknown AVAuthorizationStatus: %ld", (long)status);
|
||||
callback(NO);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)ows_askForMediaLibraryPermissions:(void (^)(BOOL granted))callbackParam
|
||||
{
|
||||
OWSLogVerbose(@"[%@] ows_askForMediaLibraryPermissions", NSStringFromClass(self.class));
|
||||
|
||||
// Ensure callback is invoked on main thread.
|
||||
void (^completionCallback)(BOOL) = ^(BOOL granted) {
|
||||
DispatchMainThreadSafe(^{
|
||||
callbackParam(granted);
|
||||
});
|
||||
};
|
||||
|
||||
void (^presentSettingsDialog)(void) = ^(void) {
|
||||
DispatchMainThreadSafe(^{
|
||||
UIAlertController *alert = [UIAlertController
|
||||
alertControllerWithTitle:NSLocalizedString(@"MISSING_MEDIA_LIBRARY_PERMISSION_TITLE",
|
||||
@"Alert title when user has previously denied media library access")
|
||||
message:NSLocalizedString(@"MISSING_MEDIA_LIBRARY_PERMISSION_MESSAGE",
|
||||
@"Alert body when user has previously denied media library access")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *openSettingsAction =
|
||||
[UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[[UIApplication sharedApplication] openSystemSettings];
|
||||
completionCallback(NO);
|
||||
}];
|
||||
[alert addAction:openSettingsAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.dismissButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action) {
|
||||
completionCallback(NO);
|
||||
}];
|
||||
[alert addAction:dismissAction];
|
||||
|
||||
[self presentAlert:alert];
|
||||
});
|
||||
};
|
||||
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
|
||||
OWSLogError(@"Skipping media library permissions request when app is in background.");
|
||||
completionCallback(NO);
|
||||
return;
|
||||
}
|
||||
|
||||
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
|
||||
OWSLogError(@"PhotoLibrary ImagePicker source not available");
|
||||
completionCallback(NO);
|
||||
}
|
||||
|
||||
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
|
||||
|
||||
switch (status) {
|
||||
case PHAuthorizationStatusAuthorized: {
|
||||
completionCallback(YES);
|
||||
return;
|
||||
}
|
||||
case PHAuthorizationStatusDenied: {
|
||||
presentSettingsDialog();
|
||||
return;
|
||||
}
|
||||
case PHAuthorizationStatusNotDetermined: {
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus newStatus) {
|
||||
if (newStatus == PHAuthorizationStatusAuthorized) {
|
||||
completionCallback(YES);
|
||||
} else {
|
||||
presentSettingsDialog();
|
||||
}
|
||||
}];
|
||||
return;
|
||||
}
|
||||
case PHAuthorizationStatusRestricted: {
|
||||
// when does this happen?
|
||||
OWSFailDebug(@"PHAuthorizationStatusRestricted");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)ows_askForMicrophonePermissions:(void (^)(BOOL granted))callbackParam
|
||||
{
|
||||
OWSLogVerbose(@"[%@] ows_askForMicrophonePermissions", NSStringFromClass(self.class));
|
||||
|
||||
// Ensure callback is invoked on main thread.
|
||||
void (^callback)(BOOL) = ^(BOOL granted) {
|
||||
DispatchMainThreadSafe(^{
|
||||
callbackParam(granted);
|
||||
});
|
||||
};
|
||||
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
|
||||
OWSLogError(@"Skipping microphone permissions request when app is in background.");
|
||||
callback(NO);
|
||||
return;
|
||||
}
|
||||
|
||||
[[AVAudioSession sharedInstance] requestRecordPermission:callback];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -159,17 +159,17 @@ final class SAEScreenLockViewController: ScreenLockViewController {
|
|||
private func showScreenLockFailureAlert(message: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
OWSAlerts.showAlert(
|
||||
// Title for alert indicating that screen lock could not be unlocked.
|
||||
title: "SCREEN_LOCK_UNLOCK_FAILED".localized(),
|
||||
message: message,
|
||||
buttonTitle: nil,
|
||||
buttonAction: { [weak self] action in
|
||||
// After the alert, update the UI
|
||||
self?.ensureUI()
|
||||
},
|
||||
fromViewController: self
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "SCREEN_LOCK_UNLOCK_FAILED".localized(),
|
||||
explanation: message,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text,
|
||||
afterClosed: { [weak self] in self?.ensureUI() } // After the alert, update the UI
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
|
||||
func unlockButtonWasTapped() {
|
||||
|
|
|
@ -222,11 +222,17 @@ final class ShareVC: UINavigationController, ShareViewDelegate {
|
|||
return
|
||||
}
|
||||
|
||||
let alert = UIAlertController(title: "Session", message: error.localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: { _ in
|
||||
self.extensionContext!.cancelRequest(withError: error)
|
||||
}))
|
||||
presentAlert(alert)
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: "Session",
|
||||
explanation: error.localizedDescription,
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text,
|
||||
afterClosed: { [weak self] in self?.extensionContext?.cancelRequest(withError: error) }
|
||||
)
|
||||
)
|
||||
self.present(modal, animated: true)
|
||||
}
|
||||
|
||||
// MARK: Attachment Prep
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import SessionUIKit
|
||||
|
||||
public class ConfirmationModal: Modal {
|
||||
public struct Info: Equatable, Hashable {
|
||||
enum State {
|
||||
public enum State {
|
||||
case whenEnabled
|
||||
case whenDisabled
|
||||
case always
|
||||
|
||||
func shouldShow(for value: Bool) -> Bool {
|
||||
public func shouldShow(for value: Bool) -> Bool {
|
||||
switch self {
|
||||
case .whenEnabled: return (value == true)
|
||||
case .whenDisabled: return (value == false)
|
||||
|
@ -22,7 +21,7 @@ public class ConfirmationModal: Modal {
|
|||
let title: String
|
||||
let explanation: String?
|
||||
let attributedExplanation: NSAttributedString?
|
||||
let stateToShow: State
|
||||
public let stateToShow: State
|
||||
let confirmTitle: String?
|
||||
let confirmStyle: ThemeValue
|
||||
let cancelTitle: String
|
||||
|
@ -33,7 +32,7 @@ public class ConfirmationModal: Modal {
|
|||
|
||||
// MARK: - Initialization
|
||||
|
||||
init(
|
||||
public init(
|
||||
title: String,
|
||||
explanation: String? = nil,
|
||||
attributedExplanation: NSAttributedString? = nil,
|
||||
|
@ -159,9 +158,9 @@ public class ConfirmationModal: Modal {
|
|||
result.isLayoutMarginsRelativeArrangement = true
|
||||
result.layoutMargins = UIEdgeInsets(
|
||||
top: Values.largeSpacing,
|
||||
leading: Values.largeSpacing,
|
||||
left: Values.largeSpacing,
|
||||
bottom: Values.verySmallSpacing,
|
||||
trailing: Values.largeSpacing
|
||||
right: Values.largeSpacing
|
||||
)
|
||||
|
||||
return result
|
||||
|
@ -177,7 +176,7 @@ public class ConfirmationModal: Modal {
|
|||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
init(targetView: UIView? = nil, info: Info) {
|
||||
public init(targetView: UIView? = nil, info: Info) {
|
||||
self.internalOnConfirm = { viewController in
|
||||
if info.dismissOnConfirm {
|
||||
viewController.dismiss(animated: true)
|
|
@ -1,16 +1,16 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import SessionUIKit
|
||||
import SessionUtilitiesKit
|
||||
|
||||
public class Modal: BaseVC, UIGestureRecognizerDelegate {
|
||||
open class Modal: UIViewController, UIGestureRecognizerDelegate {
|
||||
private static let cornerRadius: CGFloat = 11
|
||||
|
||||
private let afterClosed: (() -> ())?
|
||||
|
||||
// MARK: - Components
|
||||
|
||||
lazy var dimmingView: UIView = {
|
||||
private lazy var dimmingView: UIView = {
|
||||
let result = UIVisualEffectView()
|
||||
|
||||
ThemeManager.onThemeChange(observer: result) { [weak result] theme, _ in
|
||||
|
@ -37,7 +37,7 @@ public class Modal: BaseVC, UIGestureRecognizerDelegate {
|
|||
return result
|
||||
}()
|
||||
|
||||
lazy var contentView: UIView = {
|
||||
public lazy var contentView: UIView = {
|
||||
let result: UIView = UIView()
|
||||
result.clipsToBounds = true
|
||||
result.layer.cornerRadius = Modal.cornerRadius
|
||||
|
@ -45,7 +45,7 @@ public class Modal: BaseVC, UIGestureRecognizerDelegate {
|
|||
return result
|
||||
}()
|
||||
|
||||
lazy var cancelButton: UIButton = {
|
||||
public lazy var cancelButton: UIButton = {
|
||||
let result: UIButton = Modal.createButton(title: "cancel".localized(), titleColor: .textPrimary)
|
||||
result.addTarget(self, action: #selector(close), for: .touchUpInside)
|
||||
|
||||
|
@ -60,22 +60,21 @@ public class Modal: BaseVC, UIGestureRecognizerDelegate {
|
|||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
// Ensure the modal doesn't crash on iPad when being presented
|
||||
if UIDevice.current.isIPad {
|
||||
self.popoverPresentationController?.permittedArrowDirections = []
|
||||
self.popoverPresentationController?.sourceView = (targetView ?? self.view)
|
||||
self.popoverPresentationController?.sourceRect = (targetView ?? self.view).bounds
|
||||
}
|
||||
Modal.setupForIPadIfNeeded(self, targetView: (targetView ?? self.view))
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("Use init(afterClosed:) instead")
|
||||
required public init?(coder: NSCoder) {
|
||||
fatalError("Use init(targetView:afterClosed:) instead")
|
||||
}
|
||||
|
||||
public override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Need to remove the background color which is added by the BaseVC
|
||||
navigationItem.backButtonTitle = ""
|
||||
view.themeBackgroundColor = .clear
|
||||
ThemeManager.applyNavigationStylingIfNeeded(to: self)
|
||||
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
|
||||
view.addSubview(dimmingView)
|
||||
view.addSubview(containerView)
|
||||
|
@ -112,12 +111,12 @@ public class Modal: BaseVC, UIGestureRecognizerDelegate {
|
|||
}
|
||||
|
||||
/// To be overridden by subclasses.
|
||||
func populateContentView() {
|
||||
open func populateContentView() {
|
||||
preconditionFailure("populateContentView() is abstract and must be overridden.")
|
||||
}
|
||||
|
||||
static func createButton(title: String, titleColor: ThemeValue) -> UIButton {
|
||||
let result: UIButton = UIButton()
|
||||
public static func createButton(title: String, titleColor: ThemeValue) -> UIButton {
|
||||
let result: UIButton = UIButton() // TODO: NEED to fix the font (looks bad)
|
||||
result.titleLabel?.font = .systemFont(ofSize: Values.mediumFontSize, weight: UIFont.Weight(600))
|
||||
result.setTitle(title, for: .normal)
|
||||
result.setThemeTitleColor(titleColor, for: .normal)
|
||||
|
@ -152,3 +151,15 @@ public class Modal: BaseVC, UIGestureRecognizerDelegate {
|
|||
return !contentView.point(inside: location, with: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Convenience
|
||||
|
||||
public extension Modal {
|
||||
static func setupForIPadIfNeeded(_ viewController: UIViewController, targetView: UIView) {
|
||||
if UIDevice.current.isIPad {
|
||||
viewController.popoverPresentationController?.permittedArrowDirections = []
|
||||
viewController.popoverPresentationController?.sourceView = targetView
|
||||
viewController.popoverPresentationController?.sourceRect = targetView.bounds
|
||||
}
|
||||
}
|
||||
}
|
|
@ -649,7 +649,16 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
|
|||
}
|
||||
|
||||
public func showInvalidAudioFileAlert() {
|
||||
OWSAlerts.showErrorAlert(message: NSLocalizedString("INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE", comment: "Message for the alert indicating that an audio file is invalid."))
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: CurrentAppContext().frontmostViewController()?.view,
|
||||
info: ConfirmationModal.Info(
|
||||
title: CommonStrings.errorAlertTitle,
|
||||
explanation: "INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE".localized(),
|
||||
cancelTitle: "BUTTON_OK".localized(),
|
||||
cancelStyle: .alert_text
|
||||
)
|
||||
)
|
||||
CurrentAppContext().frontmostViewController()?.present(modal, animated: true)
|
||||
}
|
||||
|
||||
public func audioPlayerDidFinishPlaying(_ player: OWSAudioPlayer, successfully flag: Bool) {
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import GRDB
|
||||
import SessionMessagingKit
|
||||
|
||||
@objc public class BlockListUIUtils: NSObject {
|
||||
// MARK: - Block
|
||||
|
||||
/// This method shows an alert to unblock a contact in a ContactThread and will update the `isBlocked` flag of the contact if the user decides to continue
|
||||
///
|
||||
/// **Note:** Make sure to force a config sync in the `completionBlock` if the blocked state was successfully changed
|
||||
@objc public static func showBlockThreadActionSheet(_ threadId: String, from viewController: UIViewController, completionBlock: ((Bool) -> ())? = nil) {
|
||||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
|
||||
guard threadId != userPublicKey else {
|
||||
completionBlock?(false)
|
||||
return
|
||||
}
|
||||
|
||||
let displayName: String = Profile.displayName(id: threadId)
|
||||
let actionSheet: UIAlertController = UIAlertController(
|
||||
title: String(
|
||||
format: "BLOCK_LIST_BLOCK_USER_TITLE_FORMAT".localized(),
|
||||
self.formatForAlertTitle(displayName: displayName)
|
||||
),
|
||||
message: "BLOCK_USER_BEHAVIOR_EXPLANATION".localized(),
|
||||
preferredStyle: .actionSheet
|
||||
)
|
||||
actionSheet.addAction(UIAlertAction(
|
||||
title: "BLOCK_LIST_BLOCK_BUTTON".localized(),
|
||||
accessibilityIdentifier: "\(type(of: self).self).block",
|
||||
style: .destructive,
|
||||
handler: { _ in
|
||||
Storage.shared.writeAsync(
|
||||
updates: { db in
|
||||
try Contact
|
||||
.fetchOrCreate(db, id: threadId)
|
||||
.with(isBlocked: true)
|
||||
.save(db)
|
||||
},
|
||||
completion: { _, _ in
|
||||
self.showOkAlert(
|
||||
title: "BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE".localized(),
|
||||
message: String(
|
||||
format: "BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT".localized(),
|
||||
self.formatForAlertMessage(displayName: displayName)
|
||||
),
|
||||
from: viewController,
|
||||
completionBlock: { _ in completionBlock?(true) }
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
))
|
||||
actionSheet.addAction(UIAlertAction(
|
||||
title: CommonStrings.cancelButton,
|
||||
accessibilityIdentifier: "\(type(of: self).self).dismiss",
|
||||
style: .cancel,
|
||||
handler: { _ in completionBlock?(false) }
|
||||
))
|
||||
|
||||
viewController.presentAlert(actionSheet)
|
||||
}
|
||||
|
||||
// MARK: - Unblock
|
||||
|
||||
/// This method shows an alert to unblock a contact in a ContactThread and will update the `isBlocked` flag of the contact if the user decides to continue
|
||||
///
|
||||
/// **Note:** Make sure to force a config sync in the `completionBlock` if the blocked state was successfully changed
|
||||
@objc public static func showUnblockThreadActionSheet(_ threadId: String, from viewController: UIViewController, completionBlock: ((Bool) -> ())? = nil) {
|
||||
let displayName: String = Profile.displayName(id: threadId)
|
||||
let actionSheet: UIAlertController = UIAlertController(
|
||||
title: String(
|
||||
format: "BLOCK_LIST_UNBLOCK_TITLE_FORMAT".localized(),
|
||||
self.formatForAlertTitle(displayName: displayName)
|
||||
),
|
||||
message: nil,
|
||||
preferredStyle: .actionSheet
|
||||
)
|
||||
actionSheet.addAction(UIAlertAction(
|
||||
title: "BLOCK_LIST_UNBLOCK_BUTTON".localized(),
|
||||
accessibilityIdentifier: "\(type(of: self).self).unblock",
|
||||
style: .destructive,
|
||||
handler: { _ in
|
||||
Storage.shared.writeAsync(
|
||||
updates: { db in
|
||||
try Contact
|
||||
.fetchOrCreate(db, id: threadId)
|
||||
.with(isBlocked: false)
|
||||
.save(db)
|
||||
},
|
||||
completion: { _, _ in
|
||||
self.showOkAlert(
|
||||
title: String(
|
||||
format: "BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT".localized(),
|
||||
self.formatForAlertMessage(displayName: displayName)
|
||||
),
|
||||
message: nil,
|
||||
from: viewController,
|
||||
completionBlock: { _ in completionBlock?(false) }
|
||||
)
|
||||
})
|
||||
}
|
||||
))
|
||||
actionSheet.addAction(UIAlertAction(
|
||||
title: CommonStrings.cancelButton,
|
||||
accessibilityIdentifier: "\(type(of: self).self).dismiss",
|
||||
style: .cancel,
|
||||
handler: { _ in completionBlock?(true) }
|
||||
))
|
||||
|
||||
viewController.presentAlert(actionSheet)
|
||||
}
|
||||
|
||||
// MARK: - UI
|
||||
|
||||
@objc public static func showOkAlert(title: String, message: String?, from viewController: UIViewController, completionBlock: @escaping (UIAlertAction) -> ()) {
|
||||
let alertController: UIAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(
|
||||
title: "BUTTON_OK".localized(),
|
||||
accessibilityIdentifier: "\(type(of: self).self).ok",
|
||||
style: .default,
|
||||
handler: completionBlock
|
||||
))
|
||||
|
||||
viewController.presentAlert(alertController)
|
||||
}
|
||||
|
||||
@objc public static func formatForAlertTitle(displayName: String) -> String {
|
||||
return format(displayName: displayName, maxLength: 20)
|
||||
}
|
||||
|
||||
@objc public static func formatForAlertMessage(displayName: String) -> String {
|
||||
return format(displayName: displayName, maxLength: 127)
|
||||
}
|
||||
|
||||
@objc public static func format(displayName: String, maxLength: Int) -> String {
|
||||
guard displayName.count <= maxLength else {
|
||||
return "\(displayName.substring(to: maxLength))…"
|
||||
}
|
||||
|
||||
return displayName
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SessionUtilitiesKit
|
||||
|
||||
@objc public class OWSAlerts: NSObject {
|
||||
@objc
|
||||
public class func showAlert(_ alert: UIAlertController) {
|
||||
guard let frontmostViewController = CurrentAppContext().frontmostViewController() else {
|
||||
owsFailDebug("frontmostViewController was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
frontmostViewController.presentAlert(alert)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func showAlert(title: String) {
|
||||
self.showAlert(title: title, message: nil, buttonTitle: nil)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func showAlert(title: String?, message: String) {
|
||||
self.showAlert(title: title, message: message, buttonTitle: nil)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func showAlert(title: String?, message: String? = nil, buttonTitle: String? = nil, buttonAction: ((UIAlertAction) -> Void)? = nil) {
|
||||
guard let fromViewController = CurrentAppContext().frontmostViewController() else {
|
||||
return
|
||||
}
|
||||
showAlert(title: title, message: message, buttonTitle: buttonTitle, buttonAction: buttonAction,
|
||||
fromViewController: fromViewController)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func showAlert(title: String?, message: String? = nil, buttonTitle: String? = nil, buttonAction: ((UIAlertAction) -> Void)? = nil, fromViewController: UIViewController?) {
|
||||
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
let actionTitle = buttonTitle ?? NSLocalizedString("BUTTON_OK", comment: "")
|
||||
let okAction = UIAlertAction(title: actionTitle, style: .default, handler: buttonAction)
|
||||
okAction.accessibilityIdentifier = "OWSAlerts.\("ok")"
|
||||
alert.addAction(okAction)
|
||||
fromViewController?.presentAlert(alert)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func showConfirmationAlert(title: String, message: String? = nil, proceedTitle: String? = nil, proceedAction: @escaping (UIAlertAction) -> Void) {
|
||||
assert(title.count > 0)
|
||||
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alert.addAction(self.cancelAction)
|
||||
|
||||
let actionTitle = proceedTitle ?? NSLocalizedString("BUTTON_OK", comment: "")
|
||||
let okAction = UIAlertAction(title: actionTitle, style: .default, handler: proceedAction)
|
||||
okAction.accessibilityIdentifier = "OWSAlerts.\("ok")"
|
||||
alert.addAction(okAction)
|
||||
|
||||
CurrentAppContext().frontmostViewController()?.presentAlert(alert)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func showErrorAlert(message: String) {
|
||||
self.showAlert(title: CommonStrings.errorAlertTitle, message: message, buttonTitle: nil)
|
||||
}
|
||||
|
||||
@objc
|
||||
public class var cancelAction: UIAlertAction {
|
||||
let action = UIAlertAction(title: CommonStrings.cancelButton, style: .cancel) { _ in
|
||||
Logger.debug("Cancel item")
|
||||
// Do nothing.
|
||||
}
|
||||
action.accessibilityIdentifier = "OWSAlerts.\("cancel")"
|
||||
return action
|
||||
}
|
||||
}
|
|
@ -85,54 +85,6 @@ public extension UIView {
|
|||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public extension UIViewController {
|
||||
func presentAlert(_ alert: UIAlertController) {
|
||||
self.presentAlert(alert, animated: true)
|
||||
}
|
||||
|
||||
func presentAlert(_ alert: UIAlertController, animated: Bool) {
|
||||
guard Thread.isMainThread else {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.presentAlert(alert, animated: animated)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
setupForIPadIfNeeded(alert: alert)
|
||||
|
||||
self.present(alert, animated: animated) {
|
||||
alert.applyAccessibilityIdentifiers()
|
||||
}
|
||||
}
|
||||
|
||||
func presentAlert(_ alert: UIAlertController, completion: @escaping (() -> Void)) {
|
||||
guard Thread.isMainThread else {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.presentAlert(alert, completion: completion)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
setupForIPadIfNeeded(alert: alert)
|
||||
|
||||
self.present(alert, animated: true) {
|
||||
alert.applyAccessibilityIdentifiers()
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
private func setupForIPadIfNeeded(alert: UIAlertController) {
|
||||
if UIDevice.current.isIPad {
|
||||
alert.popoverPresentationController?.permittedArrowDirections = []
|
||||
alert.popoverPresentationController?.sourceView = self.view
|
||||
alert.popoverPresentationController?.sourceRect = self.view.bounds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public extension CGFloat {
|
||||
func clamp(_ minValue: CGFloat, _ maxValue: CGFloat) -> CGFloat {
|
||||
return CGFloatClamp(self, minValue, maxValue)
|
||||
|
|
Loading…
Reference in New Issue