diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 6a03c9765..d5d513b82 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -161,6 +161,7 @@ D8D688F92AB8B970000F651A /* SearchResultOverviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D688F82AB8B970000F651A /* SearchResultOverviewCoordinator.swift */; }; D8E5C346296DAB84007E76A7 /* DataSourceFacade+Status+History.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */; }; D8E5C349296DB8A3007E76A7 /* StatusEditHistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E5C348296DB8A3007E76A7 /* StatusEditHistoryViewController.swift */; }; + D8ECC8102AC31EA400AE0818 /* NotificationSettingsDisabledTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8ECC80F2AC31EA400AE0818 /* NotificationSettingsDisabledTableViewCell.swift */; }; D8F0372C29D232730027DE2E /* HashtagIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F0372B29D232730027DE2E /* HashtagIntentHandler.swift */; }; D8F8A03A29CA5C15000195DD /* HashtagWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F8A03929CA5C15000195DD /* HashtagWidgetView.swift */; }; D8F8A03C29CA5CB6000195DD /* HashtagWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F8A03B29CA5CB6000195DD /* HashtagWidget.swift */; }; @@ -828,6 +829,7 @@ D8D688F82AB8B970000F651A /* SearchResultOverviewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultOverviewCoordinator.swift; sourceTree = ""; }; D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceFacade+Status+History.swift"; sourceTree = ""; }; D8E5C348296DB8A3007E76A7 /* StatusEditHistoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditHistoryViewController.swift; sourceTree = ""; }; + D8ECC80F2AC31EA400AE0818 /* NotificationSettingsDisabledTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsDisabledTableViewCell.swift; sourceTree = ""; }; D8F0372B29D232730027DE2E /* HashtagIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagIntentHandler.swift; sourceTree = ""; }; D8F8A03929CA5C15000195DD /* HashtagWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagWidgetView.swift; sourceTree = ""; }; D8F8A03B29CA5CB6000195DD /* HashtagWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagWidget.swift; sourceTree = ""; }; @@ -1929,6 +1931,7 @@ children = ( D8B5E4ED2A4EB8920008970C /* NotificationSettingTableViewToggleCell.swift */, D8B5E4EF2A4EB8A00008970C /* NotificationSettingTableViewCell.swift */, + D8ECC80F2AC31EA400AE0818 /* NotificationSettingsDisabledTableViewCell.swift */, ); path = Cells; sourceTree = ""; @@ -4023,6 +4026,7 @@ DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */, DB98EB6527B216500082E365 /* ReportResultViewModel.swift in Sources */, DB4F096A269EDAD200D62E92 /* SearchResultViewModel+State.swift in Sources */, + D8ECC8102AC31EA400AE0818 /* NotificationSettingsDisabledTableViewCell.swift in Sources */, 5BB04FF5262F0E6D0043BFF6 /* ReportSection.swift in Sources */, DBEFCD82282A2AB100C0ABEA /* ReportServerRulesView.swift in Sources */, DBA94436265CBB7400C537E1 /* ProfileFieldItem.swift in Sources */, diff --git a/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewCell.swift b/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewCell.swift index 7fb17750d..1144d4fd4 100644 --- a/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewCell.swift +++ b/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewCell.swift @@ -8,24 +8,22 @@ class NotificationSettingTableViewCell: UITableViewCell { func configure(with entry: NotificationSettingEntry, viewModel: NotificationSettingsViewModel, notificationsEnabled: Bool) { - switch entry { - case.alert(_): - // we use toggle cells for these - break - case .policy: - var content = UIListContentConfiguration.valueCell() - content.text = L10n.Scene.Settings.Notifications.Policy.title - content.secondaryText = viewModel.selectedPolicy.title - if notificationsEnabled { - content.textProperties.color = .label - content.secondaryTextProperties.color = .secondaryLabel - } else { - content.textProperties.color = .secondaryLabel - content.secondaryTextProperties.color = .tertiaryLabel - } + isUserInteractionEnabled = notificationsEnabled - contentConfiguration = content + guard case .policy = entry else { return } + + var content = UIListContentConfiguration.valueCell() + content.text = L10n.Scene.Settings.Notifications.Policy.title + content.secondaryText = viewModel.selectedPolicy.title + if notificationsEnabled { + content.textProperties.color = .label + content.secondaryTextProperties.color = .secondaryLabel + } else { + content.textProperties.color = .secondaryLabel + content.secondaryTextProperties.color = .tertiaryLabel } + + contentConfiguration = content } } diff --git a/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewToggleCell.swift b/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewToggleCell.swift index 2d4bf4d6b..6a8dfb063 100644 --- a/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewToggleCell.swift +++ b/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingTableViewToggleCell.swift @@ -25,6 +25,8 @@ class NotificationSettingTableViewToggleCell: ToggleTableViewCell { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(with alert: NotificationAlert, viewModel: NotificationSettingsViewModel, notificationsEnabled: Bool) { + + isUserInteractionEnabled = notificationsEnabled self.alert = alert let toggleIsOn: Bool diff --git a/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingsDisabledTableViewCell.swift b/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingsDisabledTableViewCell.swift new file mode 100644 index 000000000..907da183a --- /dev/null +++ b/Mastodon/Scene/Settings/Notification Settings/Cells/NotificationSettingsDisabledTableViewCell.swift @@ -0,0 +1,66 @@ +// Copyright © 2023 Mastodon gGmbH. All rights reserved. + +import UIKit +import MastodonAsset + +class NotificationSettingsDisabledTableViewCell: UITableViewCell { + + static let reuseIdentifier = "NotificationSettingsDisabledTableViewCell" + + let appBadgeImageView: UIImageView + let notificationHintLabel: UILabel + let goToSettingsLabel: UILabel + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + + appBadgeImageView = UIImageView(image: UIImage(systemName: "app.badge.fill")) + appBadgeImageView.tintColor = Asset.Colors.Brand.blurple.color + appBadgeImageView.translatesAutoresizingMaskIntoConstraints = false + + notificationHintLabel = UILabel() + notificationHintLabel.translatesAutoresizingMaskIntoConstraints = false + notificationHintLabel.numberOfLines = 0 + notificationHintLabel.textColor = .label + notificationHintLabel.text = "Turn on notifications from your device settings to see updates on your lock screen." + notificationHintLabel.font = UIFontMetrics(forTextStyle: .callout).scaledFont(for: .systemFont(ofSize: 16, weight: .regular)) + + goToSettingsLabel = UILabel() + goToSettingsLabel.textColor = Asset.Colors.Brand.blurple.color + goToSettingsLabel.translatesAutoresizingMaskIntoConstraints = false + goToSettingsLabel.text = "Go to Notification Settings" + goToSettingsLabel.font = UIFontMetrics(forTextStyle: .callout).scaledFont(for: .systemFont(ofSize: 16, weight: .bold)) + + super.init(style: style, reuseIdentifier: reuseIdentifier) + + contentView.addSubview(appBadgeImageView) + contentView.addSubview(notificationHintLabel) + contentView.addSubview(goToSettingsLabel) + + backgroundColor = Asset.Colors.Brand.blurple.color.withAlphaComponent(0.15) + + setupConstraints() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func setupConstraints() { + let constraints: [NSLayoutConstraint] = [ + appBadgeImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), + appBadgeImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), + appBadgeImageView.widthAnchor.constraint(equalToConstant: 34), + appBadgeImageView.heightAnchor.constraint(equalToConstant: 34), + + notificationHintLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), + notificationHintLabel.leadingAnchor.constraint(equalTo: appBadgeImageView.trailingAnchor, constant: 16), + contentView.trailingAnchor.constraint(equalTo: notificationHintLabel.trailingAnchor, constant: 16), + + goToSettingsLabel.topAnchor.constraint(equalTo: notificationHintLabel.bottomAnchor, constant: 8), + goToSettingsLabel.leadingAnchor.constraint(equalTo: notificationHintLabel.leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: goToSettingsLabel.trailingAnchor, constant: 16), + contentView.bottomAnchor.constraint(equalTo: goToSettingsLabel.bottomAnchor, constant: 16), + ] + + NSLayoutConstraint.activate(constraints) + } +} + diff --git a/Mastodon/Scene/Settings/Notification Settings/NotificationSettings.swift b/Mastodon/Scene/Settings/Notification Settings/NotificationSettings.swift index b0adb9c23..3c02b411c 100644 --- a/Mastodon/Scene/Settings/Notification Settings/NotificationSettings.swift +++ b/Mastodon/Scene/Settings/Notification Settings/NotificationSettings.swift @@ -10,6 +10,7 @@ struct NotificationSettingsSection: Hashable { } enum NotificationSettingEntry: Hashable { + case notificationDisabled case policy case alert(NotificationAlert) } diff --git a/Mastodon/Scene/Settings/Notification Settings/NotificationSettingsViewController.swift b/Mastodon/Scene/Settings/Notification Settings/NotificationSettingsViewController.swift index 729697447..f1d249e45 100644 --- a/Mastodon/Scene/Settings/Notification Settings/NotificationSettingsViewController.swift +++ b/Mastodon/Scene/Settings/Notification Settings/NotificationSettingsViewController.swift @@ -7,6 +7,7 @@ import MastodonLocalization protocol NotificationSettingsViewControllerDelegate: AnyObject { func viewWillDisappear(_ viewController: UIViewController, viewModel: NotificationSettingsViewModel) func showPolicyList(_ viewController: UIViewController, viewModel: NotificationSettingsViewModel) + func showNotificationSettings(_ viewController: UIViewController) } class NotificationSettingsViewController: UIViewController { @@ -28,16 +29,24 @@ class NotificationSettingsViewController: UIViewController { notifyFavorites: alert?.favourite ?? false, notifyNewFollowers: alert?.follow ?? false) - sections = [ - NotificationSettingsSection(entries: [.policy]), - NotificationSettingsSection(entries: NotificationAlert.allCases.map { NotificationSettingEntry.alert($0) } ) - ] + if notificationsEnabled { + sections = [ + NotificationSettingsSection(entries: [.policy]), + NotificationSettingsSection(entries: NotificationAlert.allCases.map { NotificationSettingEntry.alert($0) } ) + ] + } else { + sections = [ + NotificationSettingsSection(entries: [.notificationDisabled]), + NotificationSettingsSection(entries: [.policy]), + NotificationSettingsSection(entries: NotificationAlert.allCases.map { NotificationSettingEntry.alert($0) } ) + ] + } tableView = UITableView(frame: .zero, style: .insetGrouped) tableView.translatesAutoresizingMaskIntoConstraints = false tableView.register(NotificationSettingTableViewCell.self, forCellReuseIdentifier: NotificationSettingTableViewCell.reuseIdentifier) tableView.register(NotificationSettingTableViewToggleCell.self, forCellReuseIdentifier: NotificationSettingTableViewToggleCell.reuseIdentifier) - tableView.isUserInteractionEnabled = notificationsEnabled + tableView.register(NotificationSettingsDisabledTableViewCell.self, forCellReuseIdentifier: NotificationSettingsDisabledTableViewCell.reuseIdentifier) super.init(nibName: nil, bundle: nil) @@ -46,6 +55,11 @@ class NotificationSettingsViewController: UIViewController { let cell: UITableViewCell switch itemIdentifier { + case .notificationDisabled: + guard let notificationsDisabledCell = tableView.dequeueReusableCell(withIdentifier: NotificationSettingsDisabledTableViewCell.reuseIdentifier, for: indexPath) as? NotificationSettingsDisabledTableViewCell else { fatalError("WTF Wrong cell!?") } + + cell = notificationsDisabledCell + case .policy: guard let self, let notificationCell = tableView.dequeueReusableCell(withIdentifier: NotificationSettingTableViewCell.reuseIdentifier, for: indexPath) as? NotificationSettingTableViewCell else { fatalError("WTF Wrong cell!?") } @@ -110,8 +124,6 @@ extension NotificationSettingsViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let entry = sections[indexPath.section].entries[indexPath.row] - - switch entry { case .alert(let alert): @@ -124,6 +136,8 @@ extension NotificationSettingsViewController: UITableViewDelegate { case .policy: delegate?.showPolicyList(self, viewModel: viewModel) + case .notificationDisabled: + delegate?.showNotificationSettings(self) } tableView.deselectRow(at: indexPath, animated: true) diff --git a/Mastodon/Scene/Settings/SettingsCoordinator.swift b/Mastodon/Scene/Settings/SettingsCoordinator.swift index 7bc735507..fab59ea79 100644 --- a/Mastodon/Scene/Settings/SettingsCoordinator.swift +++ b/Mastodon/Scene/Settings/SettingsCoordinator.swift @@ -175,6 +175,18 @@ extension SettingsCoordinator: NotificationSettingsViewControllerDelegate { }) .store(in: &disposeBag) } + + func showNotificationSettings(_ viewController: UIViewController) { + if #available(iOS 16.0, *) { + if let url = URL(string: UIApplication.openNotificationSettingsURLString) { + UIApplication.shared.open(url) + } + } else { + if let url = URL(string: UIApplication.openSettingsURLString) { + UIApplication.shared.open(url) + } + } + } } //MARK: - PolicySelectionViewControllerDelegate