mastodon-ios/Mastodon/Scene/Settings/Notification Settings/NotificationSettingsViewCon...

163 lines
7.0 KiB
Swift

// Copyright © 2023 Mastodon gGmbH. All rights reserved.
import UIKit
import CoreDataStack
import MastodonLocalization
protocol NotificationSettingsViewControllerDelegate: AnyObject {
func viewWillDisappear(_ viewController: UIViewController, viewModel: NotificationSettingsViewModel)
func showPolicyList(_ viewController: UIViewController, viewModel: NotificationSettingsViewModel)
func showNotificationSettings(_ viewController: UIViewController)
}
class NotificationSettingsViewController: UIViewController {
weak var delegate: NotificationSettingsViewControllerDelegate?
let tableView: UITableView
var tableViewDataSource: UITableViewDiffableDataSource<NotificationSettingsSection, NotificationSettingEntry>?
let sections: [NotificationSettingsSection]
var viewModel: NotificationSettingsViewModel
init(currentSetting: Setting?, notificationsEnabled: Bool) {
let activeSubscription = currentSetting?.activeSubscription
let alert = activeSubscription?.alert
viewModel = NotificationSettingsViewModel(selectedPolicy: activeSubscription?.notificationPolicy ?? .noone,
notifyMentions: alert?.mention ?? false,
notifyBoosts: alert?.reblog ?? false,
notifyFavorites: alert?.favourite ?? false,
notifyNewFollowers: alert?.follow ?? false)
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.register(NotificationSettingsDisabledTableViewCell.self, forCellReuseIdentifier: NotificationSettingsDisabledTableViewCell.reuseIdentifier)
super.init(nibName: nil, bundle: nil)
let tableViewDataSource = UITableViewDiffableDataSource<NotificationSettingsSection, NotificationSettingEntry>(tableView: tableView) { [ weak self] tableView, indexPath, itemIdentifier in
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!?") }
notificationCell.configure(with: .policy, viewModel: self.viewModel, notificationsEnabled: notificationsEnabled)
cell = notificationCell
case .alert(let alert):
guard let self,
let toggleCell = tableView.dequeueReusableCell(withIdentifier: NotificationSettingTableViewToggleCell.reuseIdentifier, for: indexPath) as? NotificationSettingTableViewToggleCell else { fatalError("WTF Wrong cell!?") }
toggleCell.configure(with: alert, viewModel: self.viewModel, notificationsEnabled: notificationsEnabled)
toggleCell.delegate = self
cell = toggleCell
}
return cell
}
tableView.dataSource = tableViewDataSource
tableView.delegate = self
self.tableViewDataSource = tableViewDataSource
view.backgroundColor = .systemGroupedBackground
view.addSubview(tableView)
tableView.pinToParent()
title = L10n.Scene.Settings.Notifications.title
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
override func viewDidLoad() {
super.viewDidLoad()
var snapshot = NSDiffableDataSourceSnapshot<NotificationSettingsSection, NotificationSettingEntry>()
for section in sections {
snapshot.appendSections([section])
snapshot.appendItems(section.entries)
}
tableViewDataSource?.apply(snapshot, animatingDifferences: false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let snapshot = tableViewDataSource?.snapshot() {
tableViewDataSource?.applySnapshotUsingReloadData(snapshot)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
delegate?.viewWillDisappear(self, viewModel: viewModel)
}
}
extension NotificationSettingsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let entry = sections[indexPath.section].entries[indexPath.row]
switch entry {
case .alert(let alert):
guard let cell = tableView.cellForRow(at: indexPath) as? NotificationSettingTableViewToggleCell else { return }
let newValue = (cell.toggle.isOn == false)
cell.toggle.setOn(newValue, animated: true)
toggleValueChanged(cell, alert: alert, newValue: newValue)
case .policy:
delegate?.showPolicyList(self, viewModel: viewModel)
case .notificationDisabled:
delegate?.showNotificationSettings(self)
}
tableView.deselectRow(at: indexPath, animated: true)
}
}
extension NotificationSettingsViewController: NotificationSettingToggleCellDelegate {
func toggleValueChanged(_ tableViewCell: NotificationSettingTableViewToggleCell, alert: NotificationAlert, newValue: Bool) {
switch alert {
case .mentionsAndReplies:
viewModel.notifyMentions = newValue
case .boosts:
viewModel.notifyBoosts = newValue
case .favorites:
viewModel.notifyFavorites = newValue
case .newFollowers:
viewModel.notifyNewFollowers = newValue
}
viewModel.updated = true
}
}