diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 4dff7e96f..3a15c8bd0 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -208,8 +208,6 @@ 34E3EF101EFC2684007F6822 /* DebugUIPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0F1EFC2684007F6822 /* DebugUIPage.m */; }; 34E8BF381EE9E2FD00F5F4CA /* FingerprintViewScanController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E8BF371EE9E2FD00F5F4CA /* FingerprintViewScanController.m */; }; 34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */; }; - 34F77040203F55D000C7CBB7 /* OWS107LegacySounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F7703E203F55D000C7CBB7 /* OWS107LegacySounds.m */; }; - 34F77041203F55D000C7CBB7 /* OWS107LegacySounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F7703F203F55D000C7CBB7 /* OWS107LegacySounds.h */; }; 34F77045203F5E4C00C7CBB7 /* messageReceivedClassic-quiet.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34F77044203F5E4B00C7CBB7 /* messageReceivedClassic-quiet.caf */; }; 34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */; }; 4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4505C2BE1E648EA300CEBF41 /* ExperienceUpgrade.swift */; }; @@ -799,8 +797,6 @@ 34E8BF371EE9E2FD00F5F4CA /* FingerprintViewScanController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewScanController.m; sourceTree = ""; }; 34F308A01ECB469700BB7697 /* OWSBezierPathView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBezierPathView.h; sourceTree = ""; }; 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBezierPathView.m; sourceTree = ""; }; - 34F7703E203F55D000C7CBB7 /* OWS107LegacySounds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS107LegacySounds.m; sourceTree = ""; }; - 34F7703F203F55D000C7CBB7 /* OWS107LegacySounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS107LegacySounds.h; sourceTree = ""; }; 34F77044203F5E4B00C7CBB7 /* messageReceivedClassic-quiet.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "messageReceivedClassic-quiet.caf"; path = "Signal/AudioFiles/messageReceivedClassic-quiet.caf"; sourceTree = SOURCE_ROOT; }; 34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWSAnyTouchGestureRecognizer.h; path = views/OWSAnyTouchGestureRecognizer.h; sourceTree = ""; }; 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSAnyTouchGestureRecognizer.m; path = views/OWSAnyTouchGestureRecognizer.m; sourceTree = ""; }; @@ -1344,8 +1340,6 @@ 346129F31FD5F31400532771 /* OWS105AttachmentFilePaths.h */, 346129EA1FD5F31300532771 /* OWS105AttachmentFilePaths.m */, 346129F11FD5F31400532771 /* OWS106EnsureProfileComplete.swift */, - 34F7703F203F55D000C7CBB7 /* OWS107LegacySounds.h */, - 34F7703E203F55D000C7CBB7 /* OWS107LegacySounds.m */, 346129931FD1E30000532771 /* OWSDatabaseMigration.h */, 346129941FD1E30000532771 /* OWSDatabaseMigration.m */, 346129E51FD5C0C600532771 /* OWSDatabaseMigrationRunner.h */, @@ -2175,7 +2169,6 @@ 34480B551FD0A7A400BC14EF /* DebugLogger.h in Headers */, 344F248420069E9C00CFB4F4 /* CountryCodeViewController.h in Headers */, 346129CA1FD2072E00532771 /* UIImage+OWS.h in Headers */, - 34F77041203F55D000C7CBB7 /* OWS107LegacySounds.h in Headers */, 346129711FD1D74C00532771 /* SignalKeyingStorage.h in Headers */, 34612A011FD5F31400532771 /* OWS104CreateRecipientIdentities.h in Headers */, 450998691FD8C10200D89EB3 /* AttachmentSharing.h in Headers */, @@ -2914,7 +2907,6 @@ files = ( 45F59A0A2029140500E8D2B0 /* OWSVideoPlayer.swift in Sources */, 344F249B200FD03300CFB4F4 /* SharingThreadPickerViewController.m in Sources */, - 34F77040203F55D000C7CBB7 /* OWS107LegacySounds.m in Sources */, 45194F951FD7216600333B2C /* TSUnreadIndicatorInteraction.m in Sources */, 45BE4EA22012AD2000935E59 /* DisappearingTimerConfigurationView.swift in Sources */, 346129F71FD5F31400532771 /* OWS105AttachmentFilePaths.m in Sources */, diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index 17f30267e..6e4510306 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -15,6 +15,7 @@ #import "HomeViewController.h" #import "MediaDetailViewController.h" #import "NSString+OWS.h" +#import "NotificationSettingsViewController.h" #import "NotificationsManager.h" #import "OWSAnyTouchGestureRecognizer.h" #import "OWSAudioPlayer.h" diff --git a/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift b/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift index 7772c46f9..b5dc87592 100644 --- a/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift +++ b/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift @@ -5,6 +5,123 @@ import Foundation import SignalMessaging +private class IntroducingCustomNotificationAudioExperienceUpgradeViewController: ExperienceUpgradeViewController { + + var buttonAction: ((UIButton) -> Void)? + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + // Opt users in to the new default sound ("note") after they've seen the splash screen. + OWSSounds.setGlobalNotificationSound(.note) + } + + override func loadView() { + self.view = UIView.container() + + /// Create Views + + // Title label + let titleLabel = UILabel() + view.addSubview(titleLabel) + titleLabel.text = header + titleLabel.textAlignment = .center + titleLabel.font = UIFont.ows_regularFont(withSize: ScaleFromIPhone5(24)) + titleLabel.textColor = UIColor.white + titleLabel.minimumScaleFactor = 0.5 + titleLabel.adjustsFontSizeToFitWidth = true + + // Body label + let bodyLabel = UILabel() + self.bodyLabel = bodyLabel + view.addSubview(bodyLabel) + bodyLabel.text = body + bodyLabel.font = UIFont.ows_lightFont(withSize: ScaleFromIPhone5To7Plus(17, 22)) + bodyLabel.textColor = UIColor.black + bodyLabel.numberOfLines = 0 + bodyLabel.lineBreakMode = .byWordWrapping + bodyLabel.textAlignment = .center + + // Image + let imageView = UIImageView(image: image) + view.addSubview(imageView) + imageView.contentMode = .scaleAspectFit + + let buttonTitle = NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_SETTINGS_BUTTON", comment: "button label shown one time, after upgrade") + let button = addButton(title: buttonTitle) { _ in + // dismiss the modally presented view controller, then proceed. + self.experienceUpgradesPageViewController.dismiss(animated: true) { + guard let fromViewController = UIApplication.shared.frontmostViewController as? HomeViewController else { + owsFail("unexpected frontmostViewController: \(String(describing: UIApplication.shared.frontmostViewController))") + return + } + + // Construct the "settings" view & push the "notifications settings" view. + let navigationController = AppSettingsViewController.inModalNavigationController() + navigationController.pushViewController(NotificationSettingsViewController(), animated:false) + + fromViewController.present(navigationController, animated: true) + } + } + + let bottomSpacer = UIView() + view.addSubview(bottomSpacer) + + /// Layout Views + + // Image layout + imageView.autoAlignAxis(toSuperviewAxis: .vertical) + imageView.autoPinToSquareAspectRatio() + imageView.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: ScaleFromIPhone5To7Plus(36, 40)) + imageView.autoSetDimension(.height, toSize: ScaleFromIPhone5(225)) + + // Title label layout + titleLabel.autoSetDimension(.height, toSize: ScaleFromIPhone5(40)) + titleLabel.autoPinWidthToSuperview(withMargin: ScaleFromIPhone5To7Plus(16, 24)) + titleLabel.autoPinTopToSuperview() + + // Body label layout + bodyLabel.autoPinEdge(.top, to: .bottom, of: imageView, withOffset: ScaleFromIPhone5To7Plus(18, 28)) + bodyLabel.autoPinWidthToSuperview(withMargin: bodyMargin) + bodyLabel.setContentHuggingVerticalHigh() + + // Button layout + button.autoPinEdge(.top, to: .bottom, of: bodyLabel, withOffset: ScaleFromIPhone5(16)) + button.autoPinWidthToSuperview(withMargin: ScaleFromIPhone5(32)) + + bottomSpacer.autoPinEdge(.top, to: .bottom, of: button, withOffset: ScaleFromIPhone5(16)) + bottomSpacer.autoPinEdge(toSuperviewEdge: .bottom) + bottomSpacer.autoPinWidthToSuperview() + } + + // MARK: - Actions + + func addButton(title: String, action: @escaping (UIButton) -> Void) -> UIButton { + self.buttonAction = action + let button = MultiLineButton() + view.addSubview(button) + button.setTitle(title, for: .normal) + button.setTitleColor(UIColor.ows_signalBrandBlue, for: .normal) + button.isUserInteractionEnabled = true + button.addTarget(self, action:#selector(didTapButton), for: .touchUpInside) + button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + button.titleLabel?.textAlignment = .center + button.titleLabel?.font = UIFont.ows_mediumFont(withSize: ScaleFromIPhone5(18)) + return button + } + + func didTapButton(sender: UIButton) { + Logger.debug("\(TAG) in \(#function)") + + guard let buttonAction = self.buttonAction else { + owsFail("\(TAG) button action was nil") + return + } + + buttonAction(sender) + } +} + private class IntroductingReadReceiptsExperienceUpgradeViewController: ExperienceUpgradeViewController { var buttonAction: ((UIButton) -> Void)? @@ -557,6 +674,8 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl return IntroductingProfilesExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self) case .introducingReadReceipts: return IntroductingReadReceiptsExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self) + case .introducingCustomNotificationAudio: + return IntroducingCustomNotificationAudioExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self) default: return ExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self) } diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.m b/Signal/src/ViewControllers/NotificationSettingsViewController.m index fdd986d69..b0620f4eb 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/NotificationSettingsViewController.m @@ -36,8 +36,8 @@ // Sounds section. OWSTableSection *soundsSection = [OWSTableSection new]; - soundsSection.headerTitle = NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", - @"Label for the sounds section of settings views."); + soundsSection.headerTitle + = NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", @"Header Label for the sounds section of settings views."); [soundsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 @@ -53,6 +53,10 @@ OWSSoundSettingsViewController *vc = [OWSSoundSettingsViewController new]; [weakSelf.navigationController pushViewController:vc animated:YES]; }]]; + [soundsSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"NOTIFICATIONS_SECTION_INAPP", nil) + isOn:[prefs soundInForeground] + target:weakSelf + selector:@selector(didToggleSoundNotificationsSwitch:)]]; [contents addSection:soundsSection]; OWSTableSection *backgroundSection = [OWSTableSection new]; @@ -78,13 +82,6 @@ = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_DESCRIPTION", @"table section footer"); [contents addSection:backgroundSection]; - OWSTableSection *inAppSection = [OWSTableSection new]; - inAppSection.headerTitle = NSLocalizedString(@"NOTIFICATIONS_SECTION_INAPP", nil); - [inAppSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"NOTIFICATIONS_SOUND", nil) - isOn:[prefs soundInForeground] - target:weakSelf - selector:@selector(didToggleSoundNotificationsSwitch:)]]; - [contents addSection:inAppSection]; self.contents = contents; } diff --git a/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift b/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift index e4e8588bb..59f9db8f0 100644 --- a/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift +++ b/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -9,7 +9,8 @@ enum ExperienceUpgradeId: String { case videoCalling = "001", callKit = "002", introducingProfiles = "003", - introducingReadReceipts = "004" + introducingReadReceipts = "004", + introducingCustomNotificationAudio = "005" } class ExperienceUpgradeFinder: NSObject { @@ -53,6 +54,13 @@ class ExperienceUpgradeFinder: NSObject { image:#imageLiteral(resourceName: "introductory_splash_read_receipts")) } + var configurableNotificationAudio: ExperienceUpgrade { + return ExperienceUpgrade(uniqueId: ExperienceUpgradeId.introducingCustomNotificationAudio.rawValue, + title: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_TITLE", comment: "Header for upgrade experience"), + body: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_DESCRIPTION", comment: "Description for notification audio customization"), + image:#imageLiteral(resourceName: "introductory_splash_read_receipts")) + } + // Keep these ordered by increasing uniqueId. private var allExperienceUpgrades: [ExperienceUpgrade] { return [ @@ -62,9 +70,10 @@ class ExperienceUpgradeFinder: NSObject { // // videoCalling, // (UIDevice.current.supportsCallKit ? callKit : nil), - // introducingProfiles, - introducingReadReceipts - ].flatMap { $0 } + // introducingProfiles, + // introducingReadReceipts, + configurableNotificationAudio + ].compactMap { $0 } } // MARK: - Instance Methods diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index bfc1dc1bb..0982cbf93 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1150,7 +1150,7 @@ "NOTIFICATIONS_NONE" = "No Name or Content"; /* No comment provided by engineer. */ -"NOTIFICATIONS_SECTION_INAPP" = "In-App Notifications"; +"NOTIFICATIONS_SECTION_INAPP" = "Play While App is Open"; /* Label for settings UI that allows user to change the notification sound. */ "NOTIFICATIONS_SECTION_SOUNDS" = "Sounds"; @@ -1164,9 +1164,6 @@ /* No comment provided by engineer. */ "NOTIFICATIONS_SHOW" = "Show"; -/* No comment provided by engineer. */ -"NOTIFICATIONS_SOUND" = "Notification Sounds"; - /* No comment provided by engineer. */ "OK" = "OK"; @@ -1567,7 +1564,7 @@ "SETTINGS_INVITE_TWITTER_TEXT" = "You can reach me using Signal by @WhisperSystems, get it now."; /* Label for settings view that allows user to change the notification sound. */ -"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Notification"; +"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound"; /* Title for settings activity */ "SETTINGS_NAV_BAR_TITLE" = "Settings"; @@ -1614,7 +1611,7 @@ /* Label for the notifications section of conversation settings view. */ "SETTINGS_SECTION_NOTIFICATIONS" = "Notifications"; -/* Label for the sounds section of settings views. */ +/* Header Label for the sounds section of settings views. */ "SETTINGS_SECTION_SOUNDS" = "Sounds"; /* settings topic header for table section */ @@ -1788,6 +1785,15 @@ /* Header for upgrade experience */ "UPGRADE_EXPERIENCE_CALLKIT_TITLE" = "Just Swipe to Answer"; +/* Description for notification audio customization */ +"UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_DESCRIPTION" = "You can now specify default and per thread text tones. And calls now respect your system contact's ringtone."; + +/* button label shown one time, after upgrade */ +"UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_SETTINGS_BUTTON" = "Review Notification Settings"; + +/* Header for upgrade experience */ +"UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_TITLE" = "Updated Call and Message Sounds"; + /* button label shown one time, after user upgrades app */ "UPGRADE_EXPERIENCE_INTRODUCING_PROFILES_BUTTON" = "Set up Your Profile"; diff --git a/SignalMessaging/environment/migrations/OWS107LegacySounds.h b/SignalMessaging/environment/migrations/OWS107LegacySounds.h deleted file mode 100644 index f6e75f382..000000000 --- a/SignalMessaging/environment/migrations/OWS107LegacySounds.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "OWSDatabaseMigration.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface OWS107LegacySounds : OWSDatabaseMigration - -@end - -NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/environment/migrations/OWS107LegacySounds.m b/SignalMessaging/environment/migrations/OWS107LegacySounds.m deleted file mode 100644 index 2c3214edb..000000000 --- a/SignalMessaging/environment/migrations/OWS107LegacySounds.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. -// - -#import "OWS107LegacySounds.h" -#import "OWSSounds.h" -#import - -NS_ASSUME_NONNULL_BEGIN - -// Increment a similar constant for every future DBMigration -static NSString *const OWS107LegacySoundsMigrationId = @"107"; - -@implementation OWS107LegacySounds - -+ (NSString *)migrationId -{ - return OWS107LegacySoundsMigrationId; -} - -- (void)runUpWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - OWSAssert(transaction); - - [OWSSounds setGlobalNotificationSound:OWSSound_ClassicNotification transaction:transaction]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m b/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m index c44054702..913bc26f7 100644 --- a/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m +++ b/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m @@ -8,7 +8,6 @@ #import "OWS103EnableVideoCalling.h" #import "OWS104CreateRecipientIdentities.h" #import "OWS105AttachmentFilePaths.h" -#import "OWS107LegacySounds.h" #import "OWSDatabaseMigration.h" #import #import @@ -40,7 +39,6 @@ NS_ASSUME_NONNULL_BEGIN [[OWS104CreateRecipientIdentities alloc] initWithStorageManager:storageManager], [[OWS105AttachmentFilePaths alloc] initWithStorageManager:storageManager], [[OWS106EnsureProfileComplete alloc] initWithStorageManager:storageManager], - [[OWS107LegacySounds alloc] initWithStorageManager:storageManager], ]; }