From c14418c44003e9c272fc6bc215a110e56247aeea Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Thu, 29 Jun 2023 11:05:49 +0200 Subject: [PATCH] Implement toggle-cell and improve selection-cell for general-settings (IOS-14) and hook up the cell with the viewmodel. Also: Put DiffableTableViewDataSource into its own file (and fix a typo while doing so) --- Mastodon.xcodeproj/project.pbxproj | 4 ++ .../GeneralSettingSelectionCell.swift | 15 ++++- .../GeneralSettingToggleCell.swift | 64 ++++++++++++++++--- .../General Settings/GeneralSettings.swift | 4 ++ ...lSettingsDiffableTableViewDataSource.swift | 11 ++++ .../GeneralSettingsViewController.swift | 33 ++++++---- 6 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 Mastodon/Scene/Settings/General Settings/GeneralSettingsDiffableTableViewDataSource.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 0992e9939..0c0ad9fce 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -166,6 +166,7 @@ D8F9170F2A4B47EF008A5370 /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F9170E2A4B47EF008A5370 /* Coordinator.swift */; }; D8F917112A4C6B40008A5370 /* GeneralSettingToggleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F917102A4C6B40008A5370 /* GeneralSettingToggleCell.swift */; }; D8F917122A4C6B67008A5370 /* GeneralSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8318A832A4468A800C0FB73 /* GeneralSettingsViewController.swift */; }; + D8F917142A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */; }; DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; settings = {ATTRIBUTES = (codegen, ); }; }; DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; }; DB023D26279FFB0A005AC798 /* ShareActivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */; }; @@ -825,6 +826,7 @@ D8F9170C2A4B3C6F008A5370 /* AboutMastodonTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutMastodonTableViewCell.swift; sourceTree = ""; }; D8F9170E2A4B47EF008A5370 /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = ""; }; D8F917102A4C6B40008A5370 /* GeneralSettingToggleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingToggleCell.swift; sourceTree = ""; }; + D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsDiffableTableViewDataSource.swift; sourceTree = ""; }; DB0009A826AEE5DC009B9D2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; DB0009AD26AEE5E4009B9D2D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Intents.strings; sourceTree = ""; }; DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareActivityProvider.swift; sourceTree = ""; }; @@ -1905,6 +1907,7 @@ D8F917052A4B0791008A5370 /* GeneralSettings.swift */, D8F917102A4C6B40008A5370 /* GeneralSettingToggleCell.swift */, D8F917072A4B0B16008A5370 /* GeneralSettingSelectionCell.swift */, + D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */, ); path = "General Settings"; sourceTree = ""; @@ -3908,6 +3911,7 @@ D8BEBCB62A1B7FFD0004F475 /* SuggestionAccountTableViewCell+ViewModel.swift in Sources */, DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */, DB4F0966269ED52200D62E92 /* SearchResultViewModel.swift in Sources */, + D8F917142A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift in Sources */, DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */, 2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */, DB6B7500272FF73800C70B6E /* UserTableViewCell.swift in Sources */, diff --git a/Mastodon/Scene/Settings/General Settings/GeneralSettingSelectionCell.swift b/Mastodon/Scene/Settings/General Settings/GeneralSettingSelectionCell.swift index 8275fde55..76b1a3838 100644 --- a/Mastodon/Scene/Settings/General Settings/GeneralSettingSelectionCell.swift +++ b/Mastodon/Scene/Settings/General Settings/GeneralSettingSelectionCell.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Mastodon gGmbH. All rights reserved. import UIKit +import MastodonAsset class GeneralSettingSelectionCell: UITableViewCell { static let reuseIdentifier = "GeneralSettingSelectionCell" @@ -18,21 +19,31 @@ class GeneralSettingSelectionCell: UITableViewCell { } private func configureAppearanceSetting(appearanceSetting: GeneralSetting.Appearance, viewModel: GeneralSettingsViewModel) { - textLabel?.text = appearanceSetting.title + var content = defaultContentConfiguration() + content.text = appearanceSetting.title + tintColor = Asset.Colors.Brand.blurple.color + if viewModel.selectedAppearence == appearanceSetting { accessoryType = .checkmark } else { accessoryType = .none } + + contentConfiguration = content } private func configureOpenLinkSetting(openLinkSetting: GeneralSetting.OpenLinksIn, viewModel: GeneralSettingsViewModel) { - textLabel?.text = openLinkSetting.title + var content = defaultContentConfiguration() + content.text = openLinkSetting.title + tintColor = Asset.Colors.Brand.blurple.color + if viewModel.selectedOpenLinks == openLinkSetting { accessoryType = .checkmark } else { accessoryType = .none } + + contentConfiguration = content } } diff --git a/Mastodon/Scene/Settings/General Settings/GeneralSettingToggleCell.swift b/Mastodon/Scene/Settings/General Settings/GeneralSettingToggleCell.swift index be595420b..1d66e38ce 100644 --- a/Mastodon/Scene/Settings/General Settings/GeneralSettingToggleCell.swift +++ b/Mastodon/Scene/Settings/General Settings/GeneralSettingToggleCell.swift @@ -1,31 +1,79 @@ // Copyright © 2023 Mastodon gGmbH. All rights reserved. import UIKit +import MastodonAsset protocol GeneralSettingToggleCellDelegate: AnyObject { - + func toggle(_ cell: GeneralSettingToggleCell, setting: GeneralSetting, isOn: Bool) } class GeneralSettingToggleCell: UITableViewCell { static let reuseIdentifier = "GeneralSettingToggleCell" - // add title label - // add switch + let label: UILabel + let toggle: UISwitch + weak var delegate: GeneralSettingToggleCellDelegate? + + var setting: GeneralSetting? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + + label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)) + label.numberOfLines = 0 + + toggle = UISwitch() + toggle.translatesAutoresizingMaskIntoConstraints = false + toggle.onTintColor = Asset.Colors.Brand.blurple.color + + super.init(style: style, reuseIdentifier: reuseIdentifier) + + toggle.addTarget(self, action: #selector(GeneralSettingToggleCell.toggleValueChanged(_:)), for: .valueChanged) + + contentView.addSubview(label) + contentView.addSubview(toggle) + setupConstraints() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func setupConstraints() { + let constraints = [ + label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 11), + label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), + contentView.bottomAnchor.constraint(equalTo: label.bottomAnchor, constant: 11), + + toggle.leadingAnchor.constraint(greaterThanOrEqualTo: label.trailingAnchor, constant: 16), + toggle.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + contentView.trailingAnchor.constraint(equalTo: toggle.trailingAnchor, constant: 16) + + ] + NSLayoutConstraint.activate(constraints) + } func configure(with setting: GeneralSetting, viewModel: GeneralSettingsViewModel) { + + self.setting = setting + switch setting { case .appearance(_), .openLinksIn(_): assertionFailure("Only for Design") case .design(let designSetting): - textLabel?.text = designSetting.title + label.text = designSetting.title switch designSetting { case .showAnimations: - //TODO: Implement - if viewModel.playAnimations == true { - print("play animations") - } + toggle.isOn = viewModel.playAnimations } } } + + @objc + func toggleValueChanged(_ sender: UISwitch) { + guard let setting else { return } + + delegate?.toggle(self, setting: setting, isOn: sender.isOn) + + } } diff --git a/Mastodon/Scene/Settings/General Settings/GeneralSettings.swift b/Mastodon/Scene/Settings/General Settings/GeneralSettings.swift index 3ad2fd5c1..69ced92fc 100644 --- a/Mastodon/Scene/Settings/General Settings/GeneralSettings.swift +++ b/Mastodon/Scene/Settings/General Settings/GeneralSettings.swift @@ -14,6 +14,7 @@ enum GeneralSettingsSectionType: Hashable { var sectionTitle: String { switch self { + //TODO: @zeitschlag Localization case .appearance: return "Appearance" case .design: @@ -35,6 +36,7 @@ enum GeneralSetting: Hashable { case dark = 2 case system = 0 + //TODO: @zeitschlag Localization var title: String { switch self { case .light: @@ -54,6 +56,7 @@ enum GeneralSetting: Hashable { enum Design: Hashable { case showAnimations + //TODO: @zeitschlag Localization var title: String { switch self { case .showAnimations: @@ -66,6 +69,7 @@ enum GeneralSetting: Hashable { case mastodon case browser + //TODO: @zeitschlag Localization var title: String { switch self { case .mastodon: diff --git a/Mastodon/Scene/Settings/General Settings/GeneralSettingsDiffableTableViewDataSource.swift b/Mastodon/Scene/Settings/General Settings/GeneralSettingsDiffableTableViewDataSource.swift new file mode 100644 index 000000000..bd94f66c0 --- /dev/null +++ b/Mastodon/Scene/Settings/General Settings/GeneralSettingsDiffableTableViewDataSource.swift @@ -0,0 +1,11 @@ +// Copyright © 2023 Mastodon gGmbH. All rights reserved. + +import UIKit + +class GeneralSettingsDiffableTableViewDataSource: UITableViewDiffableDataSource { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + guard let settingsSection = sectionIdentifier(for: section) else { return nil } + + return settingsSection.type.sectionTitle.uppercased() + } +} diff --git a/Mastodon/Scene/Settings/General Settings/GeneralSettingsViewController.swift b/Mastodon/Scene/Settings/General Settings/GeneralSettingsViewController.swift index f399fae76..f0ecb817c 100644 --- a/Mastodon/Scene/Settings/General Settings/GeneralSettingsViewController.swift +++ b/Mastodon/Scene/Settings/General Settings/GeneralSettingsViewController.swift @@ -17,7 +17,7 @@ class GeneralSettingsViewController: UIViewController { weak var delegate: GeneralSettingsViewControllerDelegate? let tableView: UITableView - var tableViewDataSource: GeneralSettingsDiffableTablaViewDataSource? + var tableViewDataSource: GeneralSettingsDiffableTableViewDataSource? private(set) var viewModel: GeneralSettingsViewModel let sections: [GeneralSettingsSection] @@ -50,7 +50,7 @@ class GeneralSettingsViewController: UIViewController { tableView.delegate = self - let tableViewDataSource = GeneralSettingsDiffableTablaViewDataSource(tableView: tableView, cellProvider: { tableView, indexPath, itemIdentifier in + let tableViewDataSource = GeneralSettingsDiffableTableViewDataSource(tableView: tableView, cellProvider: { tableView, indexPath, itemIdentifier in let cell: UITableViewCell switch itemIdentifier { case .appearance(let setting): @@ -61,8 +61,8 @@ class GeneralSettingsViewController: UIViewController { case .design(let setting): guard let toggleCell = tableView.dequeueReusableCell(withIdentifier: GeneralSettingToggleCell.reuseIdentifier, for: indexPath) as? GeneralSettingToggleCell else { fatalError("WTF? Wrong Cell!") } - //TODO: Set Delegate toggleCell.configure(with: .design(setting), viewModel: self.viewModel) + toggleCell.delegate = self cell = toggleCell case .openLinksIn(let setting): @@ -113,13 +113,13 @@ extension GeneralSettingsViewController: UITableViewDelegate { viewModel.selectedAppearence = appearanceOption UserDefaults.shared.customUserInterfaceStyle = appearanceOption.interfaceStyle case .design(_): - // do nothing? + break case .openLinksIn(let openLinksInOption): viewModel.selectedOpenLinks = openLinksInOption } - //FIXME: @zeitschlag Store in Settings???? + //TODO: @zeitschlag Store in Settings???? if let snapshot = tableViewDataSource?.snapshot() { tableViewDataSource?.applySnapshotUsingReloadData(snapshot) @@ -127,14 +127,25 @@ extension GeneralSettingsViewController: UITableViewDelegate { tableView.deselectRow(at: indexPath, animated: true) } - - } -class GeneralSettingsDiffableTablaViewDataSource: UITableViewDiffableDataSource { - override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - guard let settingsSection = sectionIdentifier(for: section) else { return nil } +extension GeneralSettingsViewController: GeneralSettingToggleCellDelegate { + func toggle(_ cell: GeneralSettingToggleCell, setting: GeneralSetting, isOn: Bool) { + switch setting { + case .appearance(_), .openLinksIn(_): + assertionFailure("No toggle") + case .design(let designSetting): + switch designSetting { + case .showAnimations: + viewModel.playAnimations = isOn + } + } + + //TODO: @zeitschlag Store in Settings???? + + if let snapshot = tableViewDataSource?.snapshot() { + tableViewDataSource?.applySnapshotUsingReloadData(snapshot) + } - return settingsSection.type.sectionTitle.uppercased() } }