Updated the app settings screens

Updated the MessageRequestViewModel to have the same page size as the HomeViewModel
Fixed a couple minor UI discrepancies
Refactored the old app settings child screens to be configuration based and all in Swift
This commit is contained in:
Morgan Pretty 2022-08-17 10:51:14 +10:00
parent ea32e407a9
commit 20d63d106c
54 changed files with 2008 additions and 512 deletions

View File

@ -9,10 +9,7 @@
/* Begin PBXBuildFile section */
1FFD68A448D5A1439F2F02FD /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DBA125424EDD2417B515C63A /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */; };
3289CA2E9E89DA9D4D52A90C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BF4561630A52BE96F164CF6 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework */; };
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */; };
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */; };
340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87E204DAC8C007AEB0F /* PrivacySettingsTableViewController.m */; };
340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC883204DAC8C007AEB0F /* OWSSoundSettingsViewController.m */; };
340FC8B6204DAC8D007AEB0F /* OWSQRCodeScanningViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */; };
340FC8B7204DAC8D007AEB0F /* OWSConversationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC89A204DAC8D007AEB0F /* OWSConversationSettingsViewController.m */; };
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */; };
@ -660,6 +657,13 @@
FD37E9FD28A5F216003AE748 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3D9E43025676D3D0040E4F3 /* Configuration.swift */; };
FD37E9FF28A5F2CD003AE748 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37E9FE28A5F2CD003AE748 /* Configuration.swift */; };
FD37EA0128A60473003AE748 /* UIKit+Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0028A60473003AE748 /* UIKit+Theme.swift */; };
FD37EA0328A9FDCC003AE748 /* HelpViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0228A9FDCC003AE748 /* HelpViewModel.swift */; };
FD37EA0528AA00C1003AE748 /* NotificationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0428AA00C1003AE748 /* NotificationSettingsViewModel.swift */; };
FD37EA0728AA2CCA003AE748 /* SettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0628AA2CCA003AE748 /* SettingsTableViewController.swift */; };
FD37EA0928AA2D27003AE748 /* SettingsTableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0828AA2D27003AE748 /* SettingsTableViewModel.swift */; };
FD37EA0B28AB12E2003AE748 /* SettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA0A28AB12E2003AE748 /* SettingsCell.swift */; };
FD37EA1728AC5605003AE748 /* NotificationContentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA1628AC5605003AE748 /* NotificationContentViewModel.swift */; };
FD37EA1928AC5CCA003AE748 /* NotificationSoundViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37EA1828AC5CCA003AE748 /* NotificationSoundViewModel.swift */; };
FD3AABE928306BBD00E5099A /* ThreadPickerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3AABE828306BBD00E5099A /* ThreadPickerViewModel.swift */; };
FD3C905C27E3FBEF00CD579F /* BatchRequestInfoSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C905B27E3FBEF00CD579F /* BatchRequestInfoSpec.swift */; };
FD3C906027E410F700CD579F /* FileUploadResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C905F27E410F700CD579F /* FileUploadResponseSpec.swift */; };
@ -796,7 +800,7 @@
FDD2506E283711D600198BDA /* DifferenceKit+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */; };
FDD250702837199200198BDA /* GarbageCollectionJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */; };
FDD250722837234B00198BDA /* MediaGalleryNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */; };
FDE72118286C156E0093DF33 /* ChatSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE72117286C156E0093DF33 /* ChatSettingsViewController.swift */; };
FDE72118286C156E0093DF33 /* ConversationSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE72117286C156E0093DF33 /* ConversationSettingsViewController.swift */; };
FDE72154287FE4470093DF33 /* HighlightMentionBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE72153287FE4470093DF33 /* HighlightMentionBackgroundView.swift */; };
FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */; };
FDED2E3C282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDED2E3B282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift */; };
@ -1022,15 +1026,9 @@
2581AFACDDDC1404866D7B8C /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.app store release.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.app store release.xcconfig"; sourceTree = "<group>"; };
2691123A7F231EDD8226C4B5 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
29CF8C79F41BF00B1C2E59A0 /* Pods-SessionUIKit.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SessionUIKit.app store release.xcconfig"; path = "Target Support Files/Pods-SessionUIKit/Pods-SessionUIKit.app store release.xcconfig"; sourceTree = "<group>"; };
340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsOptionsViewController.m; sourceTree = "<group>"; };
340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsViewController.m; sourceTree = "<group>"; };
340FC87E204DAC8C007AEB0F /* PrivacySettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrivacySettingsTableViewController.m; sourceTree = "<group>"; };
340FC883204DAC8C007AEB0F /* OWSSoundSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSoundSettingsViewController.m; sourceTree = "<group>"; };
340FC888204DAC8C007AEB0F /* OWSQRCodeScanningViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSQRCodeScanningViewController.h; sourceTree = "<group>"; };
340FC88A204DAC8C007AEB0F /* NotificationSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsViewController.h; sourceTree = "<group>"; };
340FC88B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsOptionsViewController.h; sourceTree = "<group>"; };
340FC88F204DAC8C007AEB0F /* PrivacySettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivacySettingsTableViewController.h; sourceTree = "<group>"; };
340FC894204DAC8C007AEB0F /* OWSSoundSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSoundSettingsViewController.h; sourceTree = "<group>"; };
340FC896204DAC8C007AEB0F /* OWSQRCodeScanningViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSQRCodeScanningViewController.m; sourceTree = "<group>"; };
340FC899204DAC8D007AEB0F /* OWSConversationSettingsViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsViewDelegate.h; sourceTree = "<group>"; };
340FC89A204DAC8D007AEB0F /* OWSConversationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSConversationSettingsViewController.m; sourceTree = "<group>"; };
@ -1723,6 +1721,13 @@
FD37E9F828A5F14A003AE748 /* _001_ThemePreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_ThemePreferences.swift; sourceTree = "<group>"; };
FD37E9FE28A5F2CD003AE748 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
FD37EA0028A60473003AE748 /* UIKit+Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIKit+Theme.swift"; sourceTree = "<group>"; };
FD37EA0228A9FDCC003AE748 /* HelpViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpViewModel.swift; sourceTree = "<group>"; };
FD37EA0428AA00C1003AE748 /* NotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsViewModel.swift; sourceTree = "<group>"; };
FD37EA0628AA2CCA003AE748 /* SettingsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTableViewController.swift; sourceTree = "<group>"; };
FD37EA0828AA2D27003AE748 /* SettingsTableViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTableViewModel.swift; sourceTree = "<group>"; };
FD37EA0A28AB12E2003AE748 /* SettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCell.swift; sourceTree = "<group>"; };
FD37EA1628AC5605003AE748 /* NotificationContentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentViewModel.swift; sourceTree = "<group>"; };
FD37EA1828AC5CCA003AE748 /* NotificationSoundViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSoundViewModel.swift; sourceTree = "<group>"; };
FD3AABE828306BBD00E5099A /* ThreadPickerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadPickerViewModel.swift; sourceTree = "<group>"; };
FD3C905B27E3FBEF00CD579F /* BatchRequestInfoSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchRequestInfoSpec.swift; sourceTree = "<group>"; };
FD3C905F27E410F700CD579F /* FileUploadResponseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUploadResponseSpec.swift; sourceTree = "<group>"; };
@ -1852,7 +1857,7 @@
FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DifferenceKit+Utilities.swift"; sourceTree = "<group>"; };
FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GarbageCollectionJob.swift; sourceTree = "<group>"; };
FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaGalleryNavigationController.swift; sourceTree = "<group>"; };
FDE72117286C156E0093DF33 /* ChatSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatSettingsViewController.swift; sourceTree = "<group>"; };
FDE72117286C156E0093DF33 /* ConversationSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationSettingsViewController.swift; sourceTree = "<group>"; };
FDE7214F287E50D50093DF33 /* ProtoWrappers.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = ProtoWrappers.py; sourceTree = "<group>"; };
FDE72150287E50D50093DF33 /* LintLocalizableStrings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LintLocalizableStrings.swift; sourceTree = "<group>"; };
FDE72153287FE4470093DF33 /* HighlightMentionBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightMentionBackgroundView.swift; sourceTree = "<group>"; };
@ -2823,22 +2828,22 @@
isa = PBXGroup;
children = (
FD37E9CD28A1E682003AE748 /* Views */,
340FC88B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.h */,
340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */,
340FC88A204DAC8C007AEB0F /* NotificationSettingsViewController.h */,
340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */,
B894D0742339EDCF00B4D94D /* NukeDataModal.swift */,
340FC894204DAC8C007AEB0F /* OWSSoundSettingsViewController.h */,
340FC883204DAC8C007AEB0F /* OWSSoundSettingsViewController.m */,
340FC88F204DAC8C007AEB0F /* PrivacySettingsTableViewController.h */,
340FC87E204DAC8C007AEB0F /* PrivacySettingsTableViewController.m */,
7B13E1EA2811138200BD4F64 /* PrivacySettingsTableViewController.swift */,
B886B4A62398B23E00211ABE /* QRCodeVC.swift */,
B86BD08523399CEF000F5AE3 /* SeedModal.swift */,
B8CCF6422397711F0091D419 /* SettingsVC.swift */,
B886B4A62398B23E00211ABE /* QRCodeVC.swift */,
FD37EA0828AA2D27003AE748 /* SettingsTableViewModel.swift */,
FD37EA0628AA2CCA003AE748 /* SettingsTableViewController.swift */,
FD37EA0428AA00C1003AE748 /* NotificationSettingsViewModel.swift */,
FD37EA1828AC5CCA003AE748 /* NotificationSoundViewModel.swift */,
FD37EA1628AC5605003AE748 /* NotificationContentViewModel.swift */,
FD37E9CB28A1E578003AE748 /* AppearanceViewController.swift */,
FDE72117286C156E0093DF33 /* ChatSettingsViewController.swift */,
FDE72117286C156E0093DF33 /* ConversationSettingsViewController.swift */,
FD37EA0228A9FDCC003AE748 /* HelpViewModel.swift */,
B86BD08523399CEF000F5AE3 /* SeedModal.swift */,
7B7CB18A270591630079FF93 /* ShareLogsModal.swift */,
B894D0742339EDCF00B4D94D /* NukeDataModal.swift */,
);
path = Settings;
sourceTree = "<group>";
@ -3637,6 +3642,7 @@
FD37E9D028A1F2EB003AE748 /* ThemeSelectionView.swift */,
FD37E9DA28A244E9003AE748 /* ThemePreviewView.swift */,
FD37E9DC28A384EB003AE748 /* PrimaryColorSelectionView.swift */,
FD37EA0A28AB12E2003AE748 /* SettingsCell.swift */,
);
path = Views;
sourceTree = "<group>";
@ -5352,6 +5358,7 @@
34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */,
7B13E1EB2811138200BD4F64 /* PrivacySettingsTableViewController.swift in Sources */,
C3E5C2FA251DBABB0040DFFC /* EditClosedGroupVC.swift in Sources */,
FD37EA0928AA2D27003AE748 /* SettingsTableViewModel.swift in Sources */,
7BAF54D027ACCEEC003D12F8 /* EmptySearchResultCell.swift in Sources */,
B8783E9E23EB948D00404FB8 /* UILabel+Interaction.swift in Sources */,
FD37E9D928A230F2003AE748 /* TraitObservingWindow.swift in Sources */,
@ -5362,6 +5369,7 @@
454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */,
451A13B11E13DED2000A50FD /* AppNotifications.swift in Sources */,
34D99CE4217509C2000AFB39 /* AppEnvironment.swift in Sources */,
FD37EA0528AA00C1003AE748 /* NotificationSettingsViewModel.swift in Sources */,
C328255225CA64470062D0A7 /* ContextMenuVC+ActionView.swift in Sources */,
450DF2091E0DD2C6003D14BE /* UserNotificationsAdaptee.swift in Sources */,
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */,
@ -5370,7 +5378,7 @@
EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */,
45CD81EF1DC030E7004C9430 /* SyncPushTokensJob.swift in Sources */,
B83524A525C3BA4B0089A44F /* InfoMessageCell.swift in Sources */,
FDE72118286C156E0093DF33 /* ChatSettingsViewController.swift in Sources */,
FDE72118286C156E0093DF33 /* ConversationSettingsViewController.swift in Sources */,
B84A89BC25DE328A0040017D /* ProfilePictureVC.swift in Sources */,
34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */,
FDCDB8E02811007F00352A0C /* HomeViewModel.swift in Sources */,
@ -5380,7 +5388,6 @@
B83F2B88240CB75A000A54AB /* UIImage+Scaling.swift in Sources */,
3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */,
FDE72154287FE4470093DF33 /* HighlightMentionBackgroundView.swift in Sources */,
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
4C090A1B210FD9C7001FD7F9 /* HapticFeedback.swift in Sources */,
34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */,
B886B4A92398BA1500211ABE /* QRCode.swift in Sources */,
@ -5392,7 +5399,6 @@
4C4AEC4520EC343B0020E72B /* DismissableTextField.swift in Sources */,
3496955E219B605E00DCFE74 /* PhotoLibrary.swift in Sources */,
C3A76A8D25DB83F90074CB90 /* PermissionMissingModal.swift in Sources */,
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */,
B849789625D4A2F500D0D0B3 /* LinkPreviewView.swift in Sources */,
C3D0972B2510499C00F6E3E4 /* BackgroundPoller.swift in Sources */,
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */,
@ -5411,6 +5417,7 @@
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */,
C331FFFE2558FF3B00070591 /* FullConversationCell.swift in Sources */,
FDFDE128282D05530098B17F /* MediaPresentationContext.swift in Sources */,
FD37EA0328A9FDCC003AE748 /* HelpViewModel.swift in Sources */,
FDFDE124282D04F20098B17F /* MediaDismissAnimationController.swift in Sources */,
7BA6890F27325CE300EFC32F /* SessionCallManager+CXProvider.swift in Sources */,
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */,
@ -5429,6 +5436,7 @@
C374EEEB25DA3CA70073A857 /* ConversationTitleView.swift in Sources */,
FD716E7128505E5200C96BF4 /* MessageRequestsCell.swift in Sources */,
B88FA7F2260C3EB10049422F /* OpenGroupSuggestionGrid.swift in Sources */,
FD37EA1928AC5CCA003AE748 /* NotificationSoundViewModel.swift in Sources */,
4CA485BB2232339F004B9E7D /* PhotoCaptureViewController.swift in Sources */,
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */,
C328254925CA60E60062D0A7 /* ContextMenuVC+Action.swift in Sources */,
@ -5442,6 +5450,7 @@
B848A4C5269EAAA200617031 /* UserDetailsSheet.swift in Sources */,
34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */,
7BAF54CF27ACCEEC003D12F8 /* GlobalSearchViewController.swift in Sources */,
FD37EA1728AC5605003AE748 /* NotificationContentViewModel.swift in Sources */,
B886B4A72398B23E00211ABE /* QRCodeVC.swift in Sources */,
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */,
C331FFF42558FF0300070591 /* PNOptionView.swift in Sources */,
@ -5452,6 +5461,7 @@
B8CCF63F23975CFB0091D419 /* JoinOpenGroupVC.swift in Sources */,
FD848B9828422F1A000E298B /* Date+Utilities.swift in Sources */,
FD37E9DB28A244E9003AE748 /* ThemePreviewView.swift in Sources */,
FD37EA0728AA2CCA003AE748 /* SettingsTableViewController.swift in Sources */,
B85357C323A1BD1200AAF6CD /* SeedVC.swift in Sources */,
45B5360E206DD8BB00D61655 /* UIResponder+OWS.swift in Sources */,
B8D84ECF25E3108A005A043E /* ExpandingAttachmentsButton.swift in Sources */,
@ -5490,6 +5500,7 @@
B8269D3D25C7B34D00488AB4 /* InputTextView.swift in Sources */,
340FC8B6204DAC8D007AEB0F /* OWSQRCodeScanningViewController.m in Sources */,
7B0EFDF0275084AA00FFAAE7 /* CallMessageCell.swift in Sources */,
FD37EA0B28AB12E2003AE748 /* SettingsCell.swift in Sources */,
7B93D06A27CF173D00811CB6 /* MessageRequestsViewController.swift in Sources */,
C33100082558FF6D00070591 /* NewConversationButtonSet.swift in Sources */,
C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */,
@ -5506,7 +5517,6 @@
FD716E6C28505E1C00C96BF4 /* MessageRequestsViewModel.swift in Sources */,
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */,
B835249B25C3AB650089A44F /* VisibleMessageCell.swift in Sources */,
340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */,
B8D0A25025E3678700C1835E /* LinkDeviceVC.swift in Sources */,
B894D0752339EDCF00B4D94D /* NukeDataModal.swift in Sources */,
7B93D07727CF1A8A00811CB6 /* MockDataGenerator.swift in Sources */,

View File

@ -139,7 +139,7 @@ final class LinkPreviewView: UIView {
var image: UIImage? = state.image
let stateHasImage: Bool = (image != nil)
if image == nil && (state is LinkPreview.DraftState || state is LinkPreview.SentState) {
image = UIImage(named: "Link")
image = UIImage(named: "Link")?.withRenderingMode(.alwaysTemplate)
}
// Image view
@ -164,15 +164,8 @@ final class LinkPreviewView: UIView {
if image != nil { loader.stopAnimating() } else { loader.startAnimating() }
// Title
let sentLinkPreviewTextColor: UIColor = {
switch (isOutgoing, AppModeManager.shared.currentAppMode) {
case (false, .light): return .black
case (true, .light): return Colors.grey
default: return .white
}
}()
titleLabel.textColor = sentLinkPreviewTextColor
titleLabel.text = state.title
titleLabel.themeTextColor = .textPrimary
// Horizontal stack view
switch state {

View File

@ -138,7 +138,12 @@ final class QuoteView: UIView {
.withRenderingMode(.alwaysTemplate)
)
imageView.tintColor = .white
imageView.themeTintColor = {
switch mode {
case .regular: return (direction == .outgoing ? .white : .messageBubble_outgoingText)
case .draft: return .messageBubble_outgoingText
}
}()
imageView.contentMode = .center
imageView.themeBackgroundColor = lineColor
imageView.layer.cornerRadius = VisibleMessageCell.smallCornerRadius
@ -204,7 +209,9 @@ final class QuoteView: UIView {
isOutgoingMessage: isOutgoing,
textColor: textColor,
primaryColor: primaryColor,
attributes: [:]
attributes: [
.foregroundColor: textColor
]
)
}
.defaulting(
@ -256,14 +263,6 @@ final class QuoteView: UIView {
mainStackView.addArrangedSubview(bodyLabel)
}
// Cancel button
let cancelButton = UIButton(type: .custom)
cancelButton.setImage(UIImage(named: "X")?.withRenderingMode(.alwaysTemplate), for: UIControl.State.normal)
cancelButton.tintColor = (isLightMode ? .black : .white)
cancelButton.set(.width, to: cancelButtonSize)
cancelButton.set(.height, to: cancelButtonSize)
cancelButton.addTarget(self, action: #selector(cancel), for: UIControl.Event.touchUpInside)
// Constraints
contentView.addSubview(mainStackView)
mainStackView.pin(to: contentView)
@ -292,6 +291,14 @@ final class QuoteView: UIView {
lineView.set(.height, to: contentViewHeight - 8) // Add a small amount of spacing above and below the line
if mode == .draft {
// Cancel button
let cancelButton = UIButton(type: .custom)
cancelButton.setImage(UIImage(named: "X")?.withRenderingMode(.alwaysTemplate), for: .normal)
cancelButton.themeTintColor = .textPrimary
cancelButton.set(.width, to: cancelButtonSize)
cancelButton.set(.height, to: cancelButtonSize)
cancelButton.addTarget(self, action: #selector(cancel), for: UIControl.Event.touchUpInside)
addSubview(cancelButton)
cancelButton.center(.vertical, in: self)
cancelButton.pin(.right, to: .right, of: self)

View File

@ -73,6 +73,7 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, NewConve
private lazy var tableView: UITableView = {
let result = UITableView()
result.separatorStyle = .none
result.backgroundColor = .clear
result.contentInset = UIEdgeInsets(
top: 0,
left: 0,

View File

@ -17,7 +17,7 @@ public class MessageRequestsViewModel {
// MARK: - Variables
public static let pageSize: Int = 20
public static let pageSize: Int = 15
// MARK: - Initialization

View File

@ -118,8 +118,8 @@ class MessageRequestsCell: UITableViewCell {
unreadCountView.heightAnchor.constraint(equalToConstant: FullConversationCell.unreadCountViewSize),
unreadCountLabel.topAnchor.constraint(equalTo: unreadCountView.topAnchor),
unreadCountLabel.leftAnchor.constraint(equalTo: unreadCountView.leftAnchor),
unreadCountLabel.rightAnchor.constraint(equalTo: unreadCountView.rightAnchor),
unreadCountLabel.leftAnchor.constraint(equalTo: unreadCountView.leftAnchor, constant: 4),
unreadCountLabel.rightAnchor.constraint(equalTo: unreadCountView.rightAnchor, constant: -4),
unreadCountLabel.bottomAnchor.constraint(equalTo: unreadCountView.bottomAnchor)
])
}

View File

@ -4,7 +4,6 @@
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -28,7 +27,7 @@
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" name="session_navigation_bar_background"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="b92-yg-YYQ" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="ec1-lk-fbn"/>
<constraint firstItem="b92-yg-YYQ" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="jLr-XH-MKf"/>
@ -42,8 +41,5 @@
</scenes>
<resources>
<image name="SessionGreen64" width="57.5" height="64"/>
<namedColor name="session_navigation_bar_background">
<color red="0.9882352941176471" green="0.9882352941176471" blue="0.9882352941176471" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
</resources>
</document>

View File

@ -9,7 +9,6 @@
// Separate iOS Frameworks from other imports.
#import "AvatarViewHelper.h"
#import "AVAudioSession+OWS.h"
#import "NotificationSettingsViewController.h"
#import "OWSAudioPlayer.h"
#import "OWSBezierPathView.h"
#import "OWSConversationSettingsViewController.h"

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -684,6 +684,20 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1" = "Go to ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2" = "device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name and Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
@ -693,3 +707,10 @@
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";

View File

@ -164,12 +164,3 @@ extension SyncPushTokensJob {
.retainUntilComplete()
}
}
// MARK: - Objective C Support
@objc(OWSSyncPushTokensJob)
class OWSSyncPushTokensJob: NSObject {
@objc static func run() {
SyncPushTokensJob.run(uploadOnlyIfStale: false)
}
}

View File

@ -5,7 +5,7 @@ import SessionUIKit
import SignalUtilitiesKit
// FIXME: Refactor to be MVVM and use database observation
class ChatSettingsViewController: OWSTableViewController {
class ConversationSettingsViewController: OWSTableViewController {
// MARK: - Lifecycle
override func viewDidLoad() {

View File

@ -0,0 +1,122 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
class HelpViewModel: SettingsTableViewModel<HelpViewModel.Section, HelpViewModel.Section> {
// MARK: - Section
public enum Section: SettingSection {
case report
case translate
case feedback
case faq
case support
var title: String { "" } // No titles
}
// MARK: - Content
override var title: String { "HELP_TITLE".localized() }
private var _settingsData: [SectionModel] = []
public override var settingsData: [SectionModel] { _settingsData }
public override var observableSettingsData: ObservableData { _observableSettingsData }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
///
/// **Note:** This observation will be triggered twice immediately (and be de-duped by the `removeDuplicates`)
/// this is due to the behaviour of `ValueConcurrentObserver.asyncStartObservation` which triggers it's own
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
private lazy var _observableSettingsData: ObservableData = ValueObservation
.trackingConstantRegion { db -> [SectionModel] in
return [
SectionModel(
model: .report,
elements: [
SettingInfo(
id: .report,
title: "HELP_REPORT_BUG_TITLE".localized(),
subtitle: "HELP_REPORT_BUG_DESCRIPTION".localized(),
action: .rightButtonModal(
title: "HELP_REPORT_BUG_ACTION_TITLE".localized(),
createModal: {
let shareLogsModal: ShareLogsModal = ShareLogsModal()
shareLogsModal.modalPresentationStyle = .overFullScreen
shareLogsModal.modalTransitionStyle = .crossDissolve
return shareLogsModal
}
)
)
]
),
SectionModel(
model: .translate,
elements: [
SettingInfo(
id: .translate,
title: "HELP_TRANSLATE_TITLE".localized(),
action: .trigger(action: {
guard let url: URL = URL(string: "https://crowdin.com/project/session-ios") else {
return
}
UIApplication.shared.open(url)
})
)
]
),
SectionModel(
model: .feedback,
elements: [
SettingInfo(
id: .feedback,
title: "HELP_FEEDBACK_TITLE".localized(),
action: .trigger(action: {
guard let url: URL = URL(string: "https://getsession.org/survey") else {
return
}
UIApplication.shared.open(url)
})
)
]
),
SectionModel(
model: .faq,
elements: [
SettingInfo(
id: .faq,
title: "HELP_FAQ_TITLE".localized(),
action: .trigger(action: {
guard let url: URL = URL(string: "https://getsession.org/faq") else {
return
}
UIApplication.shared.open(url)
})
)
]
)
]
}
.removeDuplicates()
// MARK: - Functions
public override func updateSettings(_ updatedSettings: [SectionModel]) {
self._settingsData = updatedSettings
}
public override func saveChanges() {}
}

View File

@ -0,0 +1,71 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
class NotificationContentViewModel: SettingsTableViewModel<NotificationSettingsViewModel.Section, Preferences.NotificationPreviewType> {
// MARK: - Section
public enum Section: SettingSection {
case content
var title: String { return "" } // No title
}
// MARK: - Content
override var title: String { "NOTIFICATIONS_STYLE_CONTENT_TITLE".localized() }
private var _settingsData: [SectionModel] = []
public override var settingsData: [SectionModel] { _settingsData }
public override var observableSettingsData: ObservableData { _observableSettingsData }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
///
/// **Note:** This observation will be triggered twice immediately (and be de-duped by the `removeDuplicates`)
/// this is due to the behaviour of `ValueConcurrentObserver.asyncStartObservation` which triggers it's own
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
private lazy var _observableSettingsData: ObservableData = ValueObservation
.trackingConstantRegion { [weak self] db -> [SectionModel] in
let currentSelection: Preferences.NotificationPreviewType? = db[.preferencesNotificationPreviewType]
return [
SectionModel(
model: .content,
elements: Preferences.NotificationPreviewType.allCases
.map { previewType in
SettingInfo(
id: previewType,
title: previewType.name,
action: .listSelection(
isSelected: { (currentSelection == previewType) },
storedSelection: (currentSelection == previewType),
shouldAutoSave: true,
selectValue: {
Storage.shared.write { db in
db[.preferencesNotificationPreviewType] = previewType
}
}
)
)
}
)
]
}
.removeDuplicates()
// MARK: - Functions
public override func updateSettings(_ updatedSettings: [SectionModel]) {
self._settingsData = updatedSettings
}
public override func saveChanges() {}
}

View File

@ -1,9 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSTableViewController.h"
@interface NotificationSettingsOptionsViewController : OWSTableViewController
@end

View File

@ -1,56 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "NotificationSettingsOptionsViewController.h"
#import "Session-Swift.h"
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
@implementation NotificationSettingsOptionsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self updateTableContents];
[LKViewControllerUtilities setUpDefaultSessionStyleForVC:self withTitle:NSLocalizedString(@"Content", @"") customBackButton:NO];
self.tableView.backgroundColor = UIColor.clearColor;
}
#pragma mark - Table Contents
- (void)updateTableContents
{
OWSTableContents *contents = [OWSTableContents new];
__weak NotificationSettingsOptionsViewController *weakSelf = self;
OWSTableSection *section = [OWSTableSection new];
// section.footerTitle = NSLocalizedString(@"NOTIFICATIONS_FOOTER_WARNING", nil);
NSInteger selectedNotifType = [SMKPreferences notificationPreviewType];
for (NSNumber *option in [SMKPreferences notificationTypes]) {
[section addItem:[OWSTableItem
itemWithCustomCellBlock:^{
UITableViewCell *cell = [OWSTableItem newCell];
cell.tintColor = LKColors.accent;
[[cell textLabel] setText:[SMKPreferences nameForNotificationPreviewType:option.intValue]];
if (selectedNotifType == option.intValue) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
cell.accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER_WITH_NAME(NotificationSettingsOptionsViewController, [SMKPreferences accessibilityIdentifierForNotificationPreviewType:option.intValue]);
return cell;
}
actionBlock:^{
[SMKPreferences setNotificationPreviewType: option.intValue];
[weakSelf.navigationController popViewControllerAnimated:YES];
}]];
}
[contents addSection:section];
self.contents = contents;
}
@end

View File

@ -1,9 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSTableViewController.h"
@interface NotificationSettingsViewController : OWSTableViewController
@end

View File

@ -1,119 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
@import PromiseKit;
#import "NotificationSettingsViewController.h"
#import "NotificationSettingsOptionsViewController.h"
#import "OWSSoundSettingsViewController.h"
#import <SessionMessagingKit/SessionMessagingKit-Swift.h>
#import <SignalUtilitiesKit/UIUtil.h>
#import "Session-Swift.h"
@implementation NotificationSettingsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self updateTableContents];
[LKViewControllerUtilities setUpDefaultSessionStyleForVC:self withTitle:NSLocalizedString(@"vc_notification_settings_title", @"") customBackButton:YES];
self.tableView.backgroundColor = UIColor.clearColor;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateTableContents];
}
#pragma mark - Table Contents
- (void)updateTableContents
{
OWSTableContents *contents = [OWSTableContents new];
__weak NotificationSettingsViewController *weakSelf = self;
OWSTableSection *strategySection = [OWSTableSection new];
strategySection.headerTitle = NSLocalizedString(@"preferences_notifications_strategy_category_title", @"");
[strategySection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"vc_notification_settings_notification_mode_title", @"")
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"push_notification_strategy")
isOnBlock:^{
return [NSUserDefaults.standardUserDefaults boolForKey:@"isUsingFullAPNs"];
}
isEnabledBlock:^{
return YES;
}
target:weakSelf
selector:@selector(didToggleAPNsSwitch:)]];
strategySection.footerTitle = @"Youll be notified of new messages reliably and immediately using Apples notification servers.";
[contents addSection:strategySection];
// Sounds section.
OWSTableSection *soundsSection = [OWSTableSection new];
soundsSection.headerTitle
= NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", @"Header Label for the sounds section of settings views.");
[soundsSection
addItem:[OWSTableItem disclosureItemWithText:
NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND",
@"Label for settings view that allows user to change the notification sound.")
detailText:[SMKSound displayNameFor:[SMKSound defaultNotificationSound]]
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"message_sound")
actionBlock:^{
OWSSoundSettingsViewController *vc = [OWSSoundSettingsViewController new];
[weakSelf.navigationController pushViewController:vc animated:YES];
}]];
NSString *inAppSoundsLabelText = NSLocalizedString(@"NOTIFICATIONS_SECTION_INAPP",
@"Table cell switch label. When disabled, Signal will not play notification sounds while the app is in the "
@"foreground.");
[soundsSection addItem:[OWSTableItem switchItemWithText:inAppSoundsLabelText
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"in_app_sounds")
isOnBlock:^{
return [SMKPreferences playNotificationSoundInForeground];
}
isEnabledBlock:^{
return YES;
}
target:weakSelf
selector:@selector(didToggleSoundNotificationsSwitch:)]];
[contents addSection:soundsSection];
OWSTableSection *backgroundSection = [OWSTableSection new];
backgroundSection.headerTitle = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_TITLE", @"table section header");
[backgroundSection
addItem:[OWSTableItem
disclosureItemWithText:NSLocalizedString(@"NOTIFICATIONS_SHOW", nil)
detailText:[SMKPreferences nameForNotificationPreviewType:[SMKPreferences notificationPreviewType]]
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"options")
actionBlock:^{
NotificationSettingsOptionsViewController *vc =
[NotificationSettingsOptionsViewController new];
[weakSelf.navigationController pushViewController:vc animated:YES];
}]];
backgroundSection.footerTitle
= NSLocalizedString(@"The information shown in notifications when your phone is locked.", @"");
[contents addSection:backgroundSection];
self.contents = contents;
}
#pragma mark - Events
- (void)didToggleSoundNotificationsSwitch:(UISwitch *)sender
{
[SMKPreferences setPlayNotificationSoundInForeground:sender.on];
}
- (void)didToggleAPNsSwitch:(UISwitch *)sender
{
[NSUserDefaults.standardUserDefaults setBool:sender.on forKey:@"isUsingFullAPNs"];
[OWSSyncPushTokensJob run]; // FIXME: Only usage of 'OWSSyncPushTokensJob' - remove when gone
}
@end

View File

@ -0,0 +1,141 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
class NotificationSettingsViewModel: SettingsTableViewModel<NotificationSettingsViewModel.Section, NotificationSettingsViewModel.Setting> {
// MARK: - Section
public enum Section: SettingSection {
case strategy
case style
case content
var title: String {
switch self {
case .strategy: return "NOTIFICATIONS_SECTION_STRATEGY".localized()
case .style: return "NOTIFICATIONS_SECTION_STYLE".localized()
case .content: return "" // No title
}
}
}
public enum Setting: Differentiable {
case strategyUseFastMode
case styleSound
case styleSoundWhenAppIsOpen
case content
}
// MARK: - Content
override var title: String { "NOTIFICATIONS_TITLE".localized() }
private var _settingsData: [SectionModel] = []
public override var settingsData: [SectionModel] { _settingsData }
public override var observableSettingsData: ObservableData { _observableSettingsData }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
///
/// **Note:** This observation will be triggered twice immediately (and be de-duped by the `removeDuplicates`)
/// this is due to the behaviour of `ValueConcurrentObserver.asyncStartObservation` which triggers it's own
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
private lazy var _observableSettingsData: ObservableData = ValueObservation
.trackingConstantRegion { db -> [SectionModel] in
return [
SectionModel(
model: .strategy,
elements: [
SettingInfo(
id: .strategyUseFastMode,
title: "NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE".localized(),
subtitle: "NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION".localized(),
action: .userDefaultsBool(
defaults: UserDefaults.standard,
key: "isUsingFullAPNs",
onChange: {
// Force sync the push tokens on change
SyncPushTokensJob.run(uploadOnlyIfStale: false)
}
),
extraActionTitle: { _, primaryColor in
NSMutableAttributedString()
.appending(
NSAttributedString(
string: "NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_1".localized(),
attributes: [
.foregroundColor: primaryColor.color
]
)
)
.appending(
NSAttributedString(
string: "NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION_2".localized()
)
)
},
onExtraAction: { UIApplication.shared.openSystemSettings() }
)
]
),
SectionModel(
model: .style,
elements: [
SettingInfo(
id: .styleSound,
title: "NOTIFICATIONS_STYLE_SOUND_TITLE".localized(),
action: .settingEnum(
db,
type: Preferences.Sound.self,
key: .defaultNotificationSound,
titleGenerator: { $0?.displayName },
createUpdateScreen: {
SettingsTableViewController(viewModel: NotificationSoundViewModel())
}
)
),
SettingInfo(
id: .styleSoundWhenAppIsOpen,
title: "NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE".localized(),
action: .settingBool(key: .playNotificationSoundInForeground)
)
]
),
SectionModel(
model: .content,
elements: [
SettingInfo(
id: .content,
title: "NOTIFICATIONS_STYLE_CONTENT_TITLE".localized(),
subtitle: "NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION".localized(),
action: .settingEnum(
db,
type: Preferences.NotificationPreviewType.self,
key: .preferencesNotificationPreviewType,
titleGenerator: { $0?.name },
createUpdateScreen: {
SettingsTableViewController(viewModel: NotificationContentViewModel())
}
)
)
]
)
]
}
.removeDuplicates()
// MARK: - Functions
public override func updateSettings(_ updatedSettings: [SectionModel]) {
self._settingsData = updatedSettings
}
public override func saveChanges() {}
}

View File

@ -0,0 +1,104 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
class NotificationSoundViewModel: SettingsTableViewModel<NotificationSettingsViewModel.Section, Preferences.Sound> {
private var audioPlayer: OWSAudioPlayer?
private var currentSelection: Preferences.Sound?
deinit {
self.audioPlayer?.stop()
self.audioPlayer = nil
}
// MARK: - Section
public enum Section: SettingSection {
case content
var title: String { return "" } // No title
}
// MARK: - Content
override var title: String { "NOTIFICATIONS_STYLE_SOUND_TITLE".localized() }
private var _settingsData: [SectionModel] = []
public override var settingsData: [SectionModel] { _settingsData }
public override var observableSettingsData: ObservableData { _observableSettingsData }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
///
/// **Note:** This observation will be triggered twice immediately (and be de-duped by the `removeDuplicates`)
/// this is due to the behaviour of `ValueConcurrentObserver.asyncStartObservation` which triggers it's own
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
private lazy var _observableSettingsData: ObservableData = ValueObservation
.trackingConstantRegion { [weak self] db -> [SectionModel] in
self?.currentSelection = (self?.currentSelection ?? db[.defaultNotificationSound])
return [
SectionModel(
model: .content,
elements: Preferences.Sound.notificationSounds
.map { sound in
SettingInfo(
id: sound,
title: {
guard sound != .note else {
return String(
format: "SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT".localized(),
sound.displayName
)
}
return sound.displayName
}(),
action: .listSelection(
isSelected: { (self?.currentSelection == sound) },
storedSelection: (db[.defaultNotificationSound] == sound),
shouldAutoSave: false,
selectValue: {
self?.currentSelection = sound
// Play the sound (to prevent UI lag we dispatch this to the next
// run loop
DispatchQueue.main.async {
self?.audioPlayer?.stop()
self?.audioPlayer = SMKSound.audioPlayer(
for: sound.rawValue,
audioBehavior: .playback
)
self?.audioPlayer?.isLooping = false
self?.audioPlayer?.play()
}
}
)
)
}
)
]
}
.removeDuplicates()
// MARK: - Functions
public override func updateSettings(_ updatedSettings: [SectionModel]) {
self._settingsData = updatedSettings
}
public override func saveChanges() {
guard let currentSelection: Preferences.Sound = self.currentSelection else { return }
Storage.shared.write { db in
db[.defaultNotificationSound] = currentSelection
}
}
}

View File

@ -1,19 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSTableViewController.h"
NS_ASSUME_NONNULL_BEGIN
@class TSThread;
@interface OWSSoundSettingsViewController : OWSTableViewController
// This property is optional. If it is not set, we are
// editing the global notification sound.
@property (nonatomic, nullable) NSString *threadId;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,169 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWSSoundSettingsViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <SessionMessagingKit/OWSAudioPlayer.h>
#import <SessionMessagingKit/SessionMessagingKit-Swift.h>
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
#import <SignalUtilitiesKit/UIUtil.h>
#import "Session-Swift.h"
NS_ASSUME_NONNULL_BEGIN
@interface OWSSoundSettingsViewController ()
@property (nonatomic) BOOL isDirty;
@property (nonatomic) NSInteger currentSound;
@property (nonatomic, nullable) OWSAudioPlayer *audioPlayer;
@end
#pragma mark -
@implementation OWSSoundSettingsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND",
@"Label for settings view that allows user to change the notification sound.")];
self.currentSound = [SMKSound notificationSoundFor:self.threadId];
[self updateTableContents];
[self updateNavigationItems];
[LKViewControllerUtilities setUpDefaultSessionStyleForVC:self withTitle:NSLocalizedString(@"Sound", @"") customBackButton:NO];
self.tableView.backgroundColor = UIColor.clearColor;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateTableContents];
}
- (void)updateNavigationItems
{
UIBarButtonItem *cancelItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:@selector(cancelWasPressed:)
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"cancel")];
cancelItem.tintColor = LKColors.text;
self.navigationItem.leftBarButtonItem = cancelItem;
if (self.isDirty) {
UIBarButtonItem *saveItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self
action:@selector(saveWasPressed:)
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"save")];
self.navigationItem.rightBarButtonItem = saveItem;
} else {
self.navigationItem.rightBarButtonItem = nil;
}
}
#pragma mark - Table Contents
- (void)updateTableContents
{
OWSTableContents *contents = [OWSTableContents new];
__weak OWSSoundSettingsViewController *weakSelf = self;
OWSTableSection *soundsSection = [OWSTableSection new];
soundsSection.headerTitle = NSLocalizedString(
@"NOTIFICATIONS_SECTION_SOUNDS", @"Label for settings UI that allows user to change the notification sound.");
NSArray<NSNumber *> *allSounds = [SMKSound notificationSounds];
for (NSNumber *nsValue in allSounds) {
NSInteger sound = nsValue.integerValue;
OWSTableItem *item;
NSString *soundLabelText = ^{
NSString *baseName = [SMKSound displayNameFor:sound];
if ([SMKSound isNote:sound]) {
NSString *noteStringFormat = NSLocalizedString(@"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT",
@"Format string for the default 'Note' sound. Embeds the system {{sound name}}.");
return [NSString stringWithFormat:noteStringFormat, baseName];
}
else {
return [SMKSound displayNameFor:sound];
}
}();
if (sound == self.currentSound) {
item = [OWSTableItem
checkmarkItemWithText:soundLabelText
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, [SMKSound displayNameFor:sound])
actionBlock:^{
[weakSelf soundWasSelected:sound];
}];
} else {
item = [OWSTableItem
actionItemWithText:soundLabelText
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, [SMKSound displayNameFor:sound])
actionBlock:^{
[weakSelf soundWasSelected:sound];
}];
}
[soundsSection addItem:item];
}
[contents addSection:soundsSection];
self.contents = contents;
}
#pragma mark - Events
- (void)soundWasSelected:(NSInteger)sound
{
[self.audioPlayer stop];
self.audioPlayer = [SMKSound audioPlayerFor:sound audioBehavior:OWSAudioBehavior_Playback];
// Suppress looping in this view.
self.audioPlayer.isLooping = NO;
[self.audioPlayer play];
if (self.currentSound == sound) {
return;
}
self.currentSound = sound;
self.isDirty = YES;
[self updateTableContents];
[self updateNavigationItems];
}
- (void)cancelWasPressed:(id)sender
{
// TODO: Add "discard changes?" alert.
[self.audioPlayer stop];
[self.navigationController popViewControllerAnimated:YES];
}
- (void)saveWasPressed:(id)sender
{
if (self.threadId) {
[SMKSound setNotificationSound:self.currentSound forThreadId:self.threadId];
}
else {
[SMKSound setGlobalNotificationSound:self.currentSound];
}
[self.audioPlayer stop];
[self.navigationController popViewControllerAnimated:YES];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,391 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import GRDB
import DifferenceKit
import SessionUIKit
import SessionUtilitiesKit
import SignalUtilitiesKit
class SettingsTableViewController<Section: SettingSection, SettingItem: Hashable & Differentiable>: BaseVC, UITableViewDataSource, UITableViewDelegate {
typealias SectionModel = SettingsTableViewModel<Section, SettingItem>.SectionModel
private let viewModel: SettingsTableViewModel<Section, SettingItem>
private var dataChangeObservable: DatabaseCancellable?
private var hasLoadedInitialSettingsData: Bool = false
// MARK: - Components
private lazy var tableView: UITableView = {
let result: UITableView = UITableView()
result.translatesAutoresizingMaskIntoConstraints = false
result.separatorStyle = .none
result.backgroundColor = .clear
result.showsVerticalScrollIndicator = false
result.showsHorizontalScrollIndicator = false
result.register(view: SettingsCell.self)
result.registerHeaderFooterView(view: SettingHeaderView.self)
result.dataSource = self
result.delegate = self
if #available(iOS 15.0, *) {
result.sectionHeaderTopPadding = 0
}
return result
}()
// MARK: - Initialization
init(viewModel: SettingsTableViewModel<Section, SettingItem>) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
ViewControllerUtilities.setUpDefaultSessionStyle(
for: self,
title: viewModel.title,
hasCustomBackButton: false
)
view.themeBackgroundColor = .backgroundPrimary
view.addSubview(tableView)
setupLayout()
// Notifications
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive(_:)),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidResignActive(_:)),
name: UIApplication.didEnterBackgroundNotification, object: nil
)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startObservingChanges()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
stopObservingChanges()
}
@objc func applicationDidBecomeActive(_ notification: Notification) {
startObservingChanges()
}
@objc func applicationDidResignActive(_ notification: Notification) {
stopObservingChanges()
}
private func setupLayout() {
tableView.pin(to: view)
}
// MARK: - Updating
private func startObservingChanges() {
// Start observing for data changes
dataChangeObservable = Storage.shared.start(
viewModel.observableSettingsData,
// If we haven't done the initial load the trigger it immediately (blocking the main
// thread so we remain on the launch screen until it completes to be consistent with
// the old behaviour)
scheduling: (hasLoadedInitialSettingsData ?
.async(onQueue: .main) :
.immediate
),
onError: { _ in },
onChange: { [weak self] settingsData in
// The default scheduler emits changes on the main thread
self?.handleSettingsUpdates(settingsData)
}
)
}
private func stopObservingChanges() {
// Stop observing database changes
dataChangeObservable?.cancel()
}
private func handleSettingsUpdates(_ updatedData: [SectionModel], initialLoad: Bool = false) {
// Ensure the first load runs without animations (if we don't do this the cells will animate
// in from a frame of CGRect.zero)
guard hasLoadedInitialSettingsData else {
hasLoadedInitialSettingsData = true
UIView.performWithoutAnimation { handleSettingsUpdates(updatedData, initialLoad: true) }
return
}
// Navigation bar
updateNavigation(updatedData)
// Reload the table content (animate changes after the first load)
tableView.reload(
using: StagedChangeset(source: viewModel.settingsData, target: updatedData),
deleteSectionsAnimation: .none,
insertSectionsAnimation: .none,
reloadSectionsAnimation: .none,
deleteRowsAnimation: .bottom,
insertRowsAnimation: .none,
reloadRowsAnimation: .none,
interrupt: { $0.changeCount > 100 } // Prevent too many changes from causing performance issues
) { [weak self] updatedData in
self?.viewModel.updateSettings(updatedData)
}
}
private func updateNavigation(_ data: [SectionModel]) {
guard
case .listSelection(_, _, let shouldAutoSave, _) = data.first?.elements.first?.action,
!shouldAutoSave
else {
navigationItem.leftBarButtonItem = nil
navigationItem.rightBarButtonItem = nil
return
}
let isStoredSelected: Bool = (data.first?.elements ?? []).contains { info in
switch info.action {
case .listSelection(let isSelected, let storedSelection, _, _):
return (isSelected() && storedSelection)
default: return false
}
}
let cancelButton: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelButtonPressed))
cancelButton.themeTintColor = .textPrimary
navigationItem.leftBarButtonItem = cancelButton
let saveButton: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveButtonPressed))
saveButton.themeTintColor = .textPrimary
navigationItem.rightBarButtonItem = (isStoredSelected ? nil : saveButton)
}
// MARK: - UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int {
return self.viewModel.settingsData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.viewModel.settingsData[section].elements.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section: SectionModel = viewModel.settingsData[indexPath.section]
let settingInfo: SettingInfo<SettingItem> = section.elements[indexPath.row]
let cell: SettingsCell = tableView.dequeue(type: SettingsCell.self, for: indexPath)
cell.update(
title: settingInfo.title,
subtitle: settingInfo.subtitle,
action: settingInfo.action,
extraActionTitle: settingInfo.extraActionTitle,
onExtraAction: settingInfo.onExtraAction,
isFirstInSection: (indexPath.row == 0),
isLastInSection: (indexPath.row == (section.elements.count - 1))
)
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let section: SectionModel = viewModel.settingsData[section]
let view: SettingHeaderView = tableView.dequeueHeaderFooterView(type: SettingHeaderView.self)
view.update(with: section.model.title)
return view
}
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let section: SectionModel = self.viewModel.settingsData[indexPath.section]
let settingInfo: SettingInfo<SettingItem> = section.elements[indexPath.row]
switch settingInfo.action {
case .trigger(let action):
action()
case .rightButtonModal(_, let createModal):
let viewController: UIViewController = createModal()
present(viewController, animated: true, completion: nil)
case .userDefaultsBool(let defaults, let key, let onChange):
defaults.set(!defaults.bool(forKey: key), forKey: key)
manuallyReload(indexPath: indexPath, section: section, settingInfo: settingInfo)
onChange?()
case .settingBool(let key):
Storage.shared.write { db in db[key] = !db[key] }
manuallyReload(indexPath: indexPath, section: section, settingInfo: settingInfo)
case .push(let createDestination), .dangerPush(let createDestination),
.settingEnum(_, _, let createDestination):
let viewController: UIViewController = createDestination()
navigationController?.pushViewController(viewController, animated: true)
case .listSelection(_, _, let shouldAutoSave, let selectValue):
let maybeOldSelection: (Int, SettingInfo<SettingItem>)? = section.elements
.enumerated()
.first(where: { index, info in
switch info.action {
case .listSelection(let isSelected, _, _, _): return isSelected()
default: return false
}
})
selectValue()
updateNavigation(viewModel.settingsData)
manuallyReload(indexPath: indexPath, section: section, settingInfo: settingInfo)
// Update the old selection as well
if let oldSelection: (index: Int, info: SettingInfo<SettingItem>) = maybeOldSelection {
manuallyReload(
indexPath: IndexPath(
row: oldSelection.index,
section: indexPath.section
),
section: section,
settingInfo: oldSelection.info
)
}
guard shouldAutoSave else { return }
navigationController?.popViewController(animated: true)
}
}
private func manuallyReload(
indexPath: IndexPath,
section: SectionModel,
settingInfo: SettingInfo<SettingItem>
) {
// Try update the existing cell to have a nice animation instead of reloading the cell
if let existingCell: SettingsCell = tableView.cellForRow(at: indexPath) as? SettingsCell {
existingCell.update(
title: settingInfo.title,
subtitle: settingInfo.subtitle,
action: settingInfo.action,
extraActionTitle: settingInfo.extraActionTitle,
onExtraAction: settingInfo.onExtraAction,
isFirstInSection: (indexPath.row == 0),
isLastInSection: (indexPath.row == (section.elements.count - 1))
)
}
else {
tableView.reloadRows(at: [indexPath], with: .none)
}
}
// MARK: - NavigationActions
@objc private func cancelButtonPressed() {
navigationController?.popViewController(animated: true)
}
@objc private func saveButtonPressed() {
viewModel.saveChanges()
navigationController?.popViewController(animated: true)
}
}
// MARK: - SettingHeaderView
class SettingHeaderView: UITableViewHeaderFooterView {
// MARK: - UI
private let stackView: UIStackView = {
let result: UIStackView = UIStackView()
result.translatesAutoresizingMaskIntoConstraints = false
result.axis = .vertical
result.distribution = .fill
result.alignment = .fill
result.isLayoutMarginsRelativeArrangement = true
result.layoutMargins = UIEdgeInsets(
top: Values.mediumSpacing,
left: Values.largeSpacing,
bottom: Values.smallSpacing,
right: Values.largeSpacing
)
return result
}()
private let titleLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .systemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textSecondary
return result
}()
private let separator: UIView = UIView.separator()
// MARK: - Initialization
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
self.backgroundView = UIView()
self.backgroundView?.themeBackgroundColor = .backgroundPrimary
addSubview(stackView)
addSubview(separator)
stackView.addArrangedSubview(titleLabel)
setupLayout()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupLayout() {
self.heightAnchor.constraint(greaterThanOrEqualToConstant: Values.mediumSpacing).isActive = true
stackView.pin(to: self)
separator.pin(.left, to: .left, of: self)
separator.pin(.right, to: .right, of: self)
separator.pin(.bottom, to: .bottom, of: self)
}
// MARK: - Content
fileprivate func update(with title: String) {
titleLabel.text = title
titleLabel.isHidden = title.isEmpty
}
}

View File

@ -0,0 +1,200 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import DifferenceKit
import SessionUIKit
import SessionUtilitiesKit
class SettingsTableViewModel<Section: SettingSection, SettingItem: Hashable & Differentiable> {
typealias SectionModel = ArraySection<Section, SettingInfo<SettingItem>>
typealias ObservableData = ValueObservation<ValueReducers.RemoveDuplicates<ValueReducers.Fetch<[SectionModel]>>>
open var title: String { preconditionFailure("abstract class - override in subclass") }
open var settingsData: [SectionModel] { preconditionFailure("abstract class - override in subclass") }
open var observableSettingsData: ObservableData {
preconditionFailure("abstract class - override in subclass")
}
func updateSettings(_ updatedSettings: [SectionModel]) {
preconditionFailure("abstract class - override in subclass")
}
func saveChanges() {
preconditionFailure("abstract class - override in subclass")
}
}
// MARK: - SettingSection
protocol SettingSection: Differentiable {
var title: String { get }
}
// MARK: - SettingInfo
struct SettingInfo<ID: Hashable & Differentiable>: Equatable, Hashable, Differentiable {
let id: ID
let title: String
let subtitle: String?
let action: SettingsAction
let extraActionTitle: ((Theme, Theme.PrimaryColor) -> NSAttributedString)?
let onExtraAction: (() -> Void)?
// MARK: - Initialization
init(
id: ID,
title: String,
subtitle: String? = nil,
action: SettingsAction,
extraActionTitle: ((Theme, Theme.PrimaryColor) -> NSAttributedString)? = nil,
onExtraAction: (() -> Void)? = nil
) {
self.id = id
self.title = title
self.subtitle = subtitle
self.action = action
self.extraActionTitle = extraActionTitle
self.onExtraAction = onExtraAction
}
// MARK: - Conformance
var differenceIdentifier: ID { id }
func hash(into hasher: inout Hasher) {
id.hash(into: &hasher)
title.hash(into: &hasher)
subtitle.hash(into: &hasher)
action.hash(into: &hasher)
}
static func == (lhs: SettingInfo<ID>, rhs: SettingInfo<ID>) -> Bool {
return (
lhs.id == rhs.id &&
lhs.title == rhs.title &&
lhs.subtitle == rhs.subtitle &&
lhs.action == rhs.action
)
}
}
// MARK: - SettingsAction
public enum SettingsAction: Hashable, Equatable {
case userDefaultsBool(
defaults: UserDefaults,
key: String,
onChange: (() -> Void)?
)
case settingBool(key: Setting.BoolKey)
case settingEnum(
key: String,
title: String?,
createUpdateScreen: () -> UIViewController
)
case trigger(action: () -> Void)
case push(createDestination: () -> UIViewController)
case dangerPush(createDestination: () -> UIViewController)
case listSelection(
isSelected: () -> Bool,
storedSelection: Bool,
shouldAutoSave: Bool,
selectValue: () -> Void
)
case rightButtonModal(
title: String,
createModal: () -> UIViewController
)
private var actionName: String {
switch self {
case .userDefaultsBool: return "userDefaultsBool"
case .settingBool: return "settingBool"
case .settingEnum: return "settingEnum"
case .trigger: return "trigger"
case .push: return "push"
case .dangerPush: return "dangerPush"
case .listSelection: return "listSelection"
case .rightButtonModal: return "rightButtonModal"
}
}
// MARK: - Convenience
public static func settingEnum<ET: EnumIntSetting>(
_ db: Database,
type: ET.Type,
key: Setting.EnumKey,
titleGenerator: @escaping ((ET?) -> String?),
createUpdateScreen: @escaping () -> UIViewController
) -> SettingsAction {
return SettingsAction.settingEnum(
key: key.rawValue,
title: titleGenerator(db[key]),
createUpdateScreen: createUpdateScreen
)
}
public static func settingEnum<ET: EnumStringSetting>(
_ db: Database,
type: ET.Type,
key: Setting.EnumKey,
titleGenerator: @escaping ((ET?) -> String?),
createUpdateScreen: @escaping () -> UIViewController
) -> SettingsAction {
return SettingsAction.settingEnum(
key: key.rawValue,
title: titleGenerator(db[key]),
createUpdateScreen: createUpdateScreen
)
}
// MARK: - Conformance
public func hash(into hasher: inout Hasher) {
actionName.hash(into: &hasher)
switch self {
case .userDefaultsBool(_, let key, _): key.hash(into: &hasher)
case .settingBool(let key): key.hash(into: &hasher)
case .settingEnum(let key, let title, _):
key.hash(into: &hasher)
title.hash(into: &hasher)
case .listSelection(let isSelected, let storedSelection, let shouldAutoSave, _):
isSelected().hash(into: &hasher)
storedSelection.hash(into: &hasher)
shouldAutoSave.hash(into: &hasher)
default: break
}
}
public static func == (lhs: SettingsAction, rhs: SettingsAction) -> Bool {
switch (lhs, rhs) {
case (.userDefaultsBool(_, let lhsKey, _), .userDefaultsBool(_, let rhsKey, _)):
return (lhsKey == rhsKey)
case (.settingBool(let lhsKey), .settingBool(let rhsKey)): return (lhsKey == rhsKey)
case (.settingEnum(let lhsKey, let lhsTitle, _), .settingEnum(let rhsKey, let rhsTitle, _)):
return (
lhsKey == rhsKey &&
lhsTitle == rhsTitle
)
case (.listSelection(let lhsIsSelected, let lhsStoredSelection, let lhsShouldAutoSave, _), .listSelection(let rhsIsSelected, let rhsStoredSelection, let rhsShouldAutoSave, _)):
return (
lhsIsSelected() == rhsIsSelected() &&
lhsStoredSelection == rhsStoredSelection &&
lhsShouldAutoSave == rhsShouldAutoSave
)
default: return false
}
}
}

View File

@ -254,7 +254,7 @@ final class SettingsVC: BaseVC, AvatarViewHelperDelegate {
UIView.separator(),
getSettingButton(title: "vc_settings_notifications_button_title".localized(), action: #selector(showNotificationSettings)),
UIView.separator(),
getSettingButton(title: "CONVERSATIONS_TITLE".localized(), action: #selector(showChatSettings)),
getSettingButton(title: "CONVERSATIONS_TITLE".localized(), action: #selector(showConversationSettings)),
UIView.separator(),
getSettingButton(title: "MESSAGE_REQUESTS_TITLE".localized(), action: #selector(showMessageRequests)),
UIView.separator(),
@ -544,8 +544,10 @@ final class SettingsVC: BaseVC, AvatarViewHelperDelegate {
}
@objc private func showNotificationSettings() {
let notificationSettingsVC = NotificationSettingsViewController()
self.navigationController?.pushViewController(notificationSettingsVC, animated: true)
let settingsViewController: SettingsTableViewController = SettingsTableViewController(
viewModel: NotificationSettingsViewModel()
)
self.navigationController?.pushViewController(settingsViewController, animated: true)
}
@objc private func showMessageRequests() {
@ -553,9 +555,9 @@ final class SettingsVC: BaseVC, AvatarViewHelperDelegate {
self.navigationController?.pushViewController(viewController, animated: true)
}
@objc private func showChatSettings() {
let chatSettingsVC = ChatSettingsViewController()
self.navigationController?.pushViewController(chatSettingsVC, animated: true)
@objc private func showConversationSettings() {
let conversationSettingsVC = ConversationSettingsViewController()
self.navigationController?.pushViewController(conversationSettingsVC, animated: true)
}
@objc private func showAppearanceSettings() {
@ -571,7 +573,10 @@ final class SettingsVC: BaseVC, AvatarViewHelperDelegate {
}
@objc private func showHelp() {
let settingsViewController: SettingsTableViewController = SettingsTableViewController(
viewModel: HelpViewModel()
)
self.navigationController?.pushViewController(settingsViewController, animated: true)
}
@objc private func clearAllData() {

View File

@ -0,0 +1,402 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import GRDB
import SessionUIKit
class SettingsCell: UITableViewCell {
/// This value is here to allow the theming update callback to be released when preparing for reuse
private var instanceView: UIView = UIView()
private var onExtraAction: (() -> Void)?
// MARK: - UI
private let topSeparator: UIView = {
let result: UIView = UIView.separator()
result.translatesAutoresizingMaskIntoConstraints = false
result.isHidden = true
return result
}()
private let contentStackView: UIStackView = {
let result: UIStackView = UIStackView()
result.translatesAutoresizingMaskIntoConstraints = false
result.axis = .horizontal
result.distribution = .equalSpacing
result.alignment = .fill
result.spacing = Values.mediumSpacing
result.isLayoutMarginsRelativeArrangement = true
result.layoutMargins = UIEdgeInsets(
top: Values.mediumSpacing,
leading: Values.largeSpacing,
bottom: Values.mediumSpacing,
trailing: Values.largeSpacing
)
return result
}()
private let titleStackView: UIStackView = {
let result: UIStackView = UIStackView()
result.translatesAutoresizingMaskIntoConstraints = false
result.axis = .vertical
result.distribution = .equalSpacing
result.alignment = .fill
return result
}()
private let titleLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textPrimary
result.numberOfLines = 0
return result
}()
private let subtitleLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .systemFont(ofSize: Values.smallFontSize)
result.themeTextColor = .textPrimary
result.numberOfLines = 0
result.isHidden = true
return result
}()
private lazy var extraActionButton: UIButton = {
let result: UIButton = UIButton()
result.translatesAutoresizingMaskIntoConstraints = false
result.titleLabel?.font = .boldSystemFont(ofSize: Values.smallFontSize)
result.contentHorizontalAlignment = .left
result.contentEdgeInsets = UIEdgeInsets(
top: 8,
left: 0,
bottom: 0,
right: 0
)
result.addTarget(self, action: #selector(extraActionTapped), for: .touchUpInside)
result.isHidden = true
return result
}()
private let actionContainerView: UIView = {
let result: UIView = UIView()
result.translatesAutoresizingMaskIntoConstraints = false
result.isHidden = true
return result
}()
private let pushChevronImageView: UIImageView = {
let result: UIImageView = UIImageView(image: UIImage(systemName: "chevron.right"))
result.translatesAutoresizingMaskIntoConstraints = false
result.themeTintColor = .textPrimary
result.isHidden = true
return result
}()
private let toggleSwitch: UISwitch = {
let result: UISwitch = UISwitch()
result.translatesAutoresizingMaskIntoConstraints = false
result.isUserInteractionEnabled = false // Triggered by didSelectCell instead
result.themeOnTintColor = .primary
result.isHidden = true
return result
}()
private let dropDownImageView: UIImageView = {
let result: UIImageView = UIImageView(image: UIImage(systemName: "arrowtriangle.down.fill"))
result.translatesAutoresizingMaskIntoConstraints = false
result.themeTintColor = .textPrimary
result.isHidden = true
return result
}()
private let dropDownLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .systemFont(ofSize: Values.smallFontSize, weight: .medium)
result.themeTextColor = .textPrimary
result.isHidden = true
return result
}()
private let tickImageView: UIImageView = {
let result: UIImageView = UIImageView(image: UIImage(systemName: "checkmark"))
result.translatesAutoresizingMaskIntoConstraints = false
result.themeTintColor = .primary
result.isHidden = true
return result
}()
private lazy var rightActionButtonContainerView: UIView = {
let result: UIView = UIView()
result.translatesAutoresizingMaskIntoConstraints = false
result.themeBackgroundColor = .solidButton_background
result.layer.cornerRadius = 5
result.isHidden = true
return result
}()
private lazy var rightActionButtonLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .boldSystemFont(ofSize: Values.smallFontSize)
result.themeTextColor = .textPrimary
return result
}()
private let botSeparator: UIView = {
let result: UIView = UIView.separator()
result.translatesAutoresizingMaskIntoConstraints = false
result.isHidden = true
return result
}()
// MARK: - Initialization
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViewHierarchy()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupViewHierarchy()
}
private func setupViewHierarchy() {
themeBackgroundColor = .settings_tabBackground
// Highlight color
let selectedBackgroundView = UIView()
selectedBackgroundView.themeBackgroundColor = .settings_tabHighlight
self.selectedBackgroundView = selectedBackgroundView
contentView.addSubview(topSeparator)
contentView.addSubview(contentStackView)
contentView.addSubview(botSeparator)
contentStackView.addArrangedSubview(titleStackView)
contentStackView.addArrangedSubview(actionContainerView)
titleStackView.addArrangedSubview(titleLabel)
titleStackView.addArrangedSubview(subtitleLabel)
titleStackView.addArrangedSubview(extraActionButton)
actionContainerView.addSubview(pushChevronImageView)
actionContainerView.addSubview(toggleSwitch)
actionContainerView.addSubview(dropDownImageView)
actionContainerView.addSubview(dropDownLabel)
actionContainerView.addSubview(tickImageView)
actionContainerView.addSubview(rightActionButtonContainerView)
rightActionButtonContainerView.addSubview(rightActionButtonLabel)
setupLayout()
}
private func setupLayout() {
topSeparator.pin(.top, to: .top, of: contentView)
topSeparator.pin(.left, to: .left, of: contentView)
topSeparator.pin(.right, to: .right, of: contentView)
contentStackView.pin(to: contentView)
pushChevronImageView.center(.vertical, in: actionContainerView)
pushChevronImageView.pin(.right, to: .right, of: actionContainerView)
actionContainerView.widthAnchor
.constraint(greaterThanOrEqualTo: toggleSwitch.widthAnchor)
.isActive = true
toggleSwitch.setCompressionResistanceHigh()
toggleSwitch.center(.vertical, in: actionContainerView)
toggleSwitch.pin(.right, to: .right, of: actionContainerView)
dropDownLabel.setCompressionResistanceHigh()
dropDownLabel.center(.vertical, in: actionContainerView)
dropDownLabel.pin(.right, to: .right, of: actionContainerView)
dropDownImageView.center(.vertical, in: actionContainerView)
dropDownImageView.pin(.left, to: .left, of: actionContainerView)
dropDownImageView.pin(.right, to: .left, of: dropDownLabel, withInset: -Values.verySmallSpacing)
dropDownImageView.set(.width, to: 10)
dropDownImageView.set(.height, to: 10)
tickImageView.center(.vertical, in: actionContainerView)
tickImageView.pin(.right, to: .right, of: actionContainerView)
rightActionButtonContainerView.center(.vertical, in: actionContainerView)
rightActionButtonContainerView.pin(.left, to: .left, of: actionContainerView)
rightActionButtonContainerView.pin(.right, to: .right, of: actionContainerView)
rightActionButtonLabel.setCompressionResistanceHigh()
rightActionButtonLabel.pin(to: rightActionButtonContainerView, withInset: Values.smallSpacing)
botSeparator.pin(.left, to: .left, of: contentView)
botSeparator.pin(.right, to: .right, of: contentView)
botSeparator.pin(.bottom, to: .bottom, of: contentView)
}
// MARK: - Content
override func prepareForReuse() {
super.prepareForReuse()
self.instanceView = UIView()
self.onExtraAction = nil
titleLabel.text = ""
titleLabel.themeTextColor = .textPrimary
subtitleLabel.text = ""
dropDownLabel.text = ""
topSeparator.isHidden = true
subtitleLabel.isHidden = true
extraActionButton.isHidden = true
actionContainerView.isHidden = true
pushChevronImageView.isHidden = true
toggleSwitch.isHidden = true
dropDownImageView.isHidden = true
dropDownLabel.isHidden = true
tickImageView.isHidden = true
tickImageView.alpha = 1
rightActionButtonContainerView.isHidden = true
botSeparator.isHidden = true
}
public func update(
title: String,
subtitle: String?,
action: SettingsAction,
extraActionTitle: ((Theme, Theme.PrimaryColor) -> NSAttributedString)?,
onExtraAction: (() -> Void)?,
isFirstInSection: Bool,
isLastInSection: Bool
) {
self.instanceView = UIView()
self.onExtraAction = onExtraAction
// Left content
titleLabel.text = title
subtitleLabel.text = subtitle
subtitleLabel.isHidden = (subtitle == nil)
extraActionButton.isHidden = (extraActionTitle == nil)
// Separator Visibility
switch action {
case .dangerPush:
topSeparator.isHidden = true
botSeparator.isHidden = true
default:
topSeparator.isHidden = isFirstInSection
botSeparator.isHidden = !isLastInSection
}
// Action Behaviours
switch action {
case .userDefaultsBool(let defaults, let key, _):
actionContainerView.isHidden = false
toggleSwitch.isHidden = false
let newValue: Bool = defaults.bool(forKey: key)
if newValue != toggleSwitch.isOn {
toggleSwitch.setOn(newValue, animated: true)
}
case .settingBool(let key):
actionContainerView.isHidden = false
toggleSwitch.isHidden = false
let newValue: Bool = Storage.shared[key]
if newValue != toggleSwitch.isOn {
toggleSwitch.setOn(newValue, animated: true)
}
case .settingEnum(_, let value, _):
actionContainerView.isHidden = false
dropDownImageView.isHidden = false
dropDownLabel.isHidden = false
dropDownLabel.text = value
case .listSelection(let isSelected, let storedSelection, _, _):
actionContainerView.isHidden = false
tickImageView.isHidden = (!isSelected() && !storedSelection)
tickImageView.alpha = (!isSelected() && storedSelection ? 0.3 : 1)
case .trigger, .push:
actionContainerView.isHidden = false
pushChevronImageView.isHidden = false
case .dangerPush:
titleLabel.themeTextColor = .danger
actionContainerView.isHidden = false
case .rightButtonModal(let title, _):
actionContainerView.isHidden = false
rightActionButtonContainerView.isHidden = false
rightActionButtonLabel.text = title
}
// Extra action
if let extraActionTitle: ((Theme, Theme.PrimaryColor) -> NSAttributedString) = extraActionTitle {
ThemeManager.onThemeChange(observer: instanceView) { [weak extraActionButton] theme, primaryColor in
extraActionButton?.setAttributedTitle(
extraActionTitle(theme, primaryColor),
for: .normal
)
}
}
}
// MARK: - Interaction
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
// Note: Only setting the highlighted state is done here, the unhighlight is done
// in 'setSelected'
guard highlighted else { return }
rightActionButtonContainerView.themeBackgroundColor = .solidButton_highlight
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Note: Only un-setting the unhighlighted state is done here, the highlighted state is done
// in 'setHighlighted'
guard !selected else { return }
guard animated else {
rightActionButtonContainerView.themeBackgroundColor = .solidButton_background
return
}
UIView.animate(withDuration: 0.4) { [weak self] in
self?.rightActionButtonContainerView.themeBackgroundColor = .solidButton_background
}
}
@objc private func extraActionTapped() {
onExtraAction?()
}
}

View File

@ -1,9 +1,10 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
import AudioToolbox
import GRDB
import DifferenceKit
import SessionUtilitiesKit
public extension Setting.EnumKey {
/// Controls how notifications should appear for the user (See `NotificationPreviewType` for the options)
@ -77,7 +78,7 @@ public extension Setting.DoubleKey {
}
public enum Preferences {
public enum NotificationPreviewType: Int, CaseIterable, EnumIntSetting {
public enum NotificationPreviewType: Int, CaseIterable, EnumIntSetting, Differentiable {
/// Notifications should include both the sender name and a preview of the message content
case nameAndPreview
@ -87,7 +88,7 @@ public enum Preferences {
/// Notifications should be a generic message
case noNameNoPreview
var name: String {
public var name: String {
switch self {
case .nameAndPreview: return "NOTIFICATIONS_SENDER_AND_MESSAGE".localized()
case .nameNoPreview: return "NOTIFICATIONS_SENDER_ONLY".localized()
@ -96,7 +97,7 @@ public enum Preferences {
}
}
public enum Sound: Int, Codable, DatabaseValueConvertible, EnumIntSetting {
public enum Sound: Int, Codable, DatabaseValueConvertible, EnumIntSetting, Differentiable {
public static var defaultiOSIncomingRingtone: Sound = .opening
public static var defaultNotificationSound: Sound = .note
@ -157,7 +158,7 @@ public enum Preferences {
]
}
var displayName: String {
public var displayName: String {
// TODO: Should we localize these sound names?
switch self {
case .`default`: return ""
@ -234,7 +235,7 @@ public enum Preferences {
let url: URL = URL(fileURLWithPath: filename)
return Bundle.main.url(
forResource: url.deletingPathExtension().absoluteString,
forResource: url.deletingPathExtension().path,
withExtension: url.pathExtension
)
}
@ -306,50 +307,6 @@ public enum Preferences {
@objc(SMKPreferences)
public class SMKPreferences: NSObject {
@objc public static let notificationTypes: [Int] = Preferences.NotificationPreviewType
.allCases
.map { $0.rawValue }
@objc public static func nameForNotificationPreviewType(_ previewType: Int) -> String {
return Preferences.NotificationPreviewType(rawValue: previewType)
.defaulting(to: .nameAndPreview)
.name
}
@objc public static func notificationPreviewType() -> Int {
return Storage.shared[.preferencesNotificationPreviewType]
.defaulting(to: Preferences.NotificationPreviewType.nameAndPreview)
.rawValue
}
@objc public static func setNotificationPreviewType(_ previewType: Int) {
Storage.shared.write { db in
db[.preferencesNotificationPreviewType] = Preferences.NotificationPreviewType(rawValue: previewType)
.defaulting(to: .nameAndPreview)
}
}
@objc public static func accessibilityIdentifierForNotificationPreviewType(_ previewType: Int) -> String {
let notificationPreviewType: Preferences.NotificationPreviewType = Preferences.NotificationPreviewType(rawValue: previewType)
.defaulting(to: .nameAndPreview)
switch notificationPreviewType {
case .nameAndPreview: return "NotificationNamePreview"
case .nameNoPreview: return "NotificationNameNoPreview"
case .noNameNoPreview: return "NotificationNoNameNoPreview"
}
}
@objc(setPlayNotificationSoundInForeground:)
static func objc_setPlayNotificationSoundInForeground(_ enabled: Bool) {
Storage.shared.write { db in db[.playNotificationSoundInForeground] = enabled }
}
@objc(playNotificationSoundInForeground)
static func objc_playNotificationSoundInForeground() -> Bool {
return Storage.shared[.playNotificationSoundInForeground]
}
@objc(setScreenSecurity:)
static func objc_setScreenSecurity(_ enabled: Bool) {
Storage.shared.write { db in db[.appSwitcherPreviewEnabled] = enabled }

View File

@ -8,6 +8,7 @@ internal enum Theme_ClassicDark: ThemeColors {
.primary: .primary,
.defaultPrimary: Theme.PrimaryColor.green.color,
.danger: #colorLiteral(red: 1, green: 0.2274509804, blue: 0.2274509804, alpha: 1),
.white: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.clear: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0),
.backgroundPrimary: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1),
.backgroundSecondary: #colorLiteral(red: 0.1058823529, green: 0.1058823529, blue: 0.1058823529, alpha: 1),
@ -51,6 +52,10 @@ internal enum Theme_ClassicDark: ThemeColors {
.outlineButton_destructiveHighlight: #colorLiteral(red: 1, green: 0.2274509804, blue: 0.2274509804, alpha: 0.3),
.outlineButton_destructiveBorder: #colorLiteral(red: 1, green: 0.2274509804, blue: 0.2274509804, alpha: 1),
// SolidButton
.solidButton_background: #colorLiteral(red: 0.1764705882, green: 0.1764705882, blue: 0.1764705882, alpha: 1),
.solidButton_highlight: #colorLiteral(red: 0.3254901961, green: 0.3254901961, blue: 0.3254901961, alpha: 1),
// Settings
.settings_tabBackground: #colorLiteral(red: 0.1058823529, green: 0.1058823529, blue: 0.1058823529, alpha: 1),
.settings_tabHighlight: #colorLiteral(red: 0.2549019608, green: 0.2549019608, blue: 0.2549019608, alpha: 1),

View File

@ -8,6 +8,7 @@ internal enum Theme_ClassicLight: ThemeColors {
.primary: .primary,
.defaultPrimary: Theme.PrimaryColor.green.color,
.danger: #colorLiteral(red: 0.8823529412, green: 0.1764705882, blue: 0.09803921569, alpha: 1),
.white: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.clear: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0),
.backgroundPrimary: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.backgroundSecondary: #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1),
@ -51,6 +52,10 @@ internal enum Theme_ClassicLight: ThemeColors {
.outlineButton_destructiveHighlight: #colorLiteral(red: 0.8823529412, green: 0.1764705882, blue: 0.09803921569, alpha: 0.3),
.outlineButton_destructiveBorder: #colorLiteral(red: 0.8823529412, green: 0.1764705882, blue: 0.09803921569, alpha: 1),
// SolidButton
.solidButton_background: #colorLiteral(red: 0.9411764706, green: 0.9411764706, blue: 0.9411764706, alpha: 1),
.solidButton_highlight: #colorLiteral(red: 0.8156862745, green: 0.8156862745, blue: 0.8156862745, alpha: 1),
// Settings
.settings_tabBackground: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.settings_tabHighlight: #colorLiteral(red: 0.8745098039, green: 0.8745098039, blue: 0.8745098039, alpha: 1),

View File

@ -8,6 +8,7 @@ internal enum Theme_OceanDark: ThemeColors {
.primary: .primary,
.defaultPrimary: Theme.PrimaryColor.blue.color,
.danger: #colorLiteral(red: 1, green: 0.2274509804, blue: 0.2274509804, alpha: 1),
.white: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.clear: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0),
.backgroundPrimary: #colorLiteral(red: 0.1450980392, green: 0.1529411765, blue: 0.2078431373, alpha: 1),
.backgroundSecondary: #colorLiteral(red: 0.1019607843, green: 0.1098039216, blue: 0.1568627451, alpha: 1),
@ -51,6 +52,10 @@ internal enum Theme_OceanDark: ThemeColors {
.outlineButton_destructiveHighlight: #colorLiteral(red: 1, green: 0.2274509804, blue: 0.2274509804, alpha: 0.3),
.outlineButton_destructiveBorder: #colorLiteral(red: 1, green: 0.2274509804, blue: 0.2274509804, alpha: 1),
// SolidButton
.solidButton_background: #colorLiteral(red: 0.1450980392, green: 0.1529411765, blue: 0.2078431373, alpha: 1),
.solidButton_highlight: #colorLiteral(red: 0.2117647059, green: 0.2196078431, blue: 0.3019607844, alpha: 1),
// Settings
.settings_tabBackground: #colorLiteral(red: 0.1019607843, green: 0.1098039216, blue: 0.1568627451, alpha: 1),
.settings_tabHighlight: #colorLiteral(red: 0.168627451, green: 0.1764705882, blue: 0.2509803922, alpha: 1),
@ -66,8 +71,8 @@ internal enum Theme_OceanDark: ThemeColors {
.conversationButton_unreadBackground: #colorLiteral(red: 0.1450980392, green: 0.1529411765, blue: 0.2078431373, alpha: 1),
.conversationButton_unreadHighlight: #colorLiteral(red: 0.168627451, green: 0.1764705882, blue: 0.2509803922, alpha: 1),
.conversationButton_unreadStripBackground: .primary,
.conversationButton_unreadBubbleBackground: Theme.PrimaryColor.blue.color,
.conversationButton_unreadBubbleText: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.conversationButton_unreadBubbleBackground: .primary,
.conversationButton_unreadBubbleText: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1),
.conversationButton_pinBackground: Theme.PrimaryColor.yellow.color
]
}

View File

@ -8,6 +8,7 @@ internal enum Theme_OceanLight: ThemeColors {
.primary: .primary,
.defaultPrimary: Theme.PrimaryColor.blue.color,
.danger: #colorLiteral(red: 0.8823529412, green: 0.1764705882, blue: 0.09803921569, alpha: 1),
.white: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
.clear: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0),
.backgroundPrimary: #colorLiteral(red: 0.9882352941, green: 1, blue: 1, alpha: 1),
.backgroundSecondary: #colorLiteral(red: 0.9254901961, green: 0.9803921569, blue: 0.9843137255, alpha: 1),
@ -51,6 +52,10 @@ internal enum Theme_OceanLight: ThemeColors {
.outlineButton_destructiveHighlight: #colorLiteral(red: 0.8823529412, green: 0.1764705882, blue: 0.09803921569, alpha: 0.3),
.outlineButton_destructiveBorder: #colorLiteral(red: 0.8823529412, green: 0.1764705882, blue: 0.09803921569, alpha: 1),
// SolidButton
.solidButton_background: #colorLiteral(red: 0.9254901961, green: 0.9803921569, blue: 0.9843137255, alpha: 1),
.solidButton_highlight: #colorLiteral(red: 0.8431372549, green: 0.9333333334, blue: 0.9411764706, alpha: 1),
// Settings
.settings_tabBackground: #colorLiteral(red: 0.9882352941, green: 1, blue: 1, alpha: 1),
.settings_tabHighlight: #colorLiteral(red: 0.9058823529, green: 0.9529411765, blue: 0.9568627451, alpha: 1),

View File

@ -4,7 +4,7 @@ import UIKit.UIColor
import SessionUtilitiesKit
public extension Theme {
public enum PrimaryColor: String, Codable, CaseIterable, EnumStringSetting {
enum PrimaryColor: String, Codable, CaseIterable, EnumStringSetting {
case green
case blue
case purple
@ -24,7 +24,7 @@ public extension Theme {
public var color: UIColor {
switch self {
case .green: return #colorLiteral(red: 0.1882352941, green: 0.9411764706, blue: 0.6549019608, alpha: 1)
case .green: return #colorLiteral(red: 0.1921568627, green: 0.9450980392, blue: 0.5882352941, alpha: 1)
case .blue: return #colorLiteral(red: 0.3411764706, green: 0.7882352941, blue: 0.9803921569, alpha: 1)
case .purple: return #colorLiteral(red: 0.7882352941, green: 0.5764705882, blue: 1, alpha: 1)
case .pink: return #colorLiteral(red: 1, green: 0.5843137255, blue: 0.937254902, alpha: 1)

View File

@ -59,6 +59,7 @@ public enum ThemeValue {
case primary
case defaultPrimary
case danger
case white
case clear
case backgroundPrimary
case backgroundSecondary
@ -102,6 +103,10 @@ public enum ThemeValue {
case outlineButton_destructiveHighlight
case outlineButton_destructiveBorder
// SolidButton
case solidButton_background
case solidButton_highlight
// Settings
case settings_tabBackground
case settings_tabHighlight

View File

@ -83,7 +83,7 @@ extension Setting {
// MARK: - Keys
public extension Setting {
struct BoolKey: RawRepresentable, ExpressibleByStringLiteral {
struct BoolKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
public init(_ rawValue: String) { self.rawValue = rawValue }
@ -93,7 +93,7 @@ public extension Setting {
public init(extendedGraphemeClusterLiteral value: String) { self.init(value) }
}
struct DateKey: RawRepresentable, ExpressibleByStringLiteral {
struct DateKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
public init(_ rawValue: String) { self.rawValue = rawValue }
@ -103,7 +103,7 @@ public extension Setting {
public init(extendedGraphemeClusterLiteral value: String) { self.init(value) }
}
struct DoubleKey: RawRepresentable, ExpressibleByStringLiteral {
struct DoubleKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
public init(_ rawValue: String) { self.rawValue = rawValue }
@ -113,7 +113,7 @@ public extension Setting {
public init(extendedGraphemeClusterLiteral value: String) { self.init(value) }
}
struct IntKey: RawRepresentable, ExpressibleByStringLiteral {
struct IntKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
public init(_ rawValue: String) { self.rawValue = rawValue }
@ -123,7 +123,7 @@ public extension Setting {
public init(extendedGraphemeClusterLiteral value: String) { self.init(value) }
}
struct StringKey: RawRepresentable, ExpressibleByStringLiteral {
struct StringKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
public init(_ rawValue: String) { self.rawValue = rawValue }
@ -133,7 +133,7 @@ public extension Setting {
public init(extendedGraphemeClusterLiteral value: String) { self.init(value) }
}
struct EnumKey: RawRepresentable, ExpressibleByStringLiteral {
struct EnumKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
public init(_ rawValue: String) { self.rawValue = rawValue }