SettingsSection.swift 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //
  2. // SettingsSection.swift
  3. // Mastodon
  4. //
  5. // Created by MainasuK Cirno on 2021-4-25.
  6. //
  7. import UIKit
  8. import CoreData
  9. import CoreDataStack
  10. import MastodonAsset
  11. import MastodonCore
  12. import MastodonLocalization
  13. enum SettingsSection: Hashable {
  14. case appearance
  15. case appearancePreference
  16. case preference
  17. case notifications
  18. case boringZone
  19. case spicyZone
  20. var title: String {
  21. switch self {
  22. case .appearance: return L10n.Scene.Settings.Section.LookAndFeel.title
  23. case .appearancePreference: return ""
  24. case .preference: return ""
  25. case .notifications: return L10n.Scene.Settings.Section.Notifications.title
  26. case .boringZone: return L10n.Scene.Settings.Section.BoringZone.title
  27. case .spicyZone: return L10n.Scene.Settings.Section.SpicyZone.title
  28. }
  29. }
  30. }
  31. extension SettingsSection {
  32. static func tableViewDiffableDataSource(
  33. for tableView: UITableView,
  34. managedObjectContext: NSManagedObjectContext,
  35. settingsAppearanceTableViewCellDelegate: SettingsAppearanceTableViewCellDelegate,
  36. settingsToggleCellDelegate: SettingsToggleCellDelegate
  37. ) -> UITableViewDiffableDataSource<SettingsSection, SettingsItem> {
  38. UITableViewDiffableDataSource(tableView: tableView) { [
  39. weak settingsAppearanceTableViewCellDelegate,
  40. weak settingsToggleCellDelegate
  41. ] tableView, indexPath, item -> UITableViewCell? in
  42. switch item {
  43. case .appearance(let record):
  44. let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsAppearanceTableViewCell.self), for: indexPath) as! SettingsAppearanceTableViewCell
  45. managedObjectContext.performAndWait {
  46. guard let setting = record.object(in: managedObjectContext) else { return }
  47. cell.configure(setting: setting)
  48. }
  49. cell.delegate = settingsAppearanceTableViewCellDelegate
  50. return cell
  51. case .appearancePreference(let record, _):
  52. let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell
  53. cell.delegate = settingsToggleCellDelegate
  54. managedObjectContext.performAndWait {
  55. guard let setting = record.object(in: managedObjectContext) else { return }
  56. SettingsSection.configureSettingToggle(cell: cell, item: item, setting: setting)
  57. ManagedObjectObserver.observe(object: setting)
  58. .receive(on: DispatchQueue.main)
  59. .sink(receiveCompletion: { _ in
  60. // do nothing
  61. }, receiveValue: { [weak cell] change in
  62. guard let cell = cell else { return }
  63. guard case .update(let object) = change.changeType,
  64. let setting = object as? Setting else { return }
  65. SettingsSection.configureSettingToggle(cell: cell, item: item, setting: setting)
  66. })
  67. .store(in: &cell.disposeBag)
  68. }
  69. return cell
  70. case .preference(let record, _):
  71. let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell
  72. cell.delegate = settingsToggleCellDelegate
  73. managedObjectContext.performAndWait {
  74. guard let setting = record.object(in: managedObjectContext) else { return }
  75. SettingsSection.configureSettingToggle(cell: cell, item: item, setting: setting)
  76. ManagedObjectObserver.observe(object: setting)
  77. .receive(on: DispatchQueue.main)
  78. .sink(receiveCompletion: { _ in
  79. // do nothing
  80. }, receiveValue: { [weak cell] change in
  81. guard let cell = cell else { return }
  82. guard case .update(let object) = change.changeType,
  83. let setting = object as? Setting else { return }
  84. SettingsSection.configureSettingToggle(cell: cell, item: item, setting: setting)
  85. })
  86. .store(in: &cell.disposeBag)
  87. }
  88. return cell
  89. case .notification(let record, let switchMode):
  90. let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell
  91. managedObjectContext.performAndWait {
  92. guard let setting = record.object(in: managedObjectContext) else { return }
  93. if let subscription = setting.activeSubscription {
  94. SettingsSection.configureSettingToggle(cell: cell, switchMode: switchMode, subscription: subscription)
  95. }
  96. ManagedObjectObserver.observe(object: setting)
  97. .sink(receiveCompletion: { _ in
  98. // do nothing
  99. }, receiveValue: { [weak cell] change in
  100. guard let cell = cell else { return }
  101. guard case .update(let object) = change.changeType,
  102. let setting = object as? Setting else { return }
  103. guard let subscription = setting.activeSubscription else { return }
  104. SettingsSection.configureSettingToggle(cell: cell, switchMode: switchMode, subscription: subscription)
  105. })
  106. .store(in: &cell.disposeBag)
  107. }
  108. cell.delegate = settingsToggleCellDelegate
  109. return cell
  110. case .boringZone(let item),
  111. .spicyZone(let item):
  112. let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsLinkTableViewCell.self), for: indexPath) as! SettingsLinkTableViewCell
  113. cell.update(with: item)
  114. return cell
  115. } // end switch
  116. }
  117. }
  118. }
  119. extension SettingsSection {
  120. public static func configureSettingToggle(
  121. cell: SettingsToggleTableViewCell,
  122. item: SettingsItem,
  123. setting: Setting
  124. ) {
  125. switch item {
  126. case .appearancePreference(_, let appearanceType):
  127. cell.textLabel?.text = appearanceType.title
  128. switch appearanceType {
  129. case .preferredTrueDarkMode:
  130. cell.switchButton.isOn = setting.preferredTrueBlackDarkMode
  131. }
  132. case .preference(_, let preferenceType):
  133. cell.textLabel?.text = preferenceType.title
  134. switch preferenceType {
  135. case .disableAvatarAnimation:
  136. cell.switchButton.isOn = setting.preferredStaticAvatar
  137. case .disableEmojiAnimation:
  138. cell.switchButton.isOn = setting.preferredStaticEmoji
  139. case .useDefaultBrowser:
  140. cell.switchButton.isOn = setting.preferredUsingDefaultBrowser
  141. }
  142. default:
  143. assertionFailure()
  144. }
  145. }
  146. public static func configureSettingToggle(
  147. cell: SettingsToggleTableViewCell,
  148. switchMode: SettingsItem.NotificationSwitchMode,
  149. subscription: NotificationSubscription
  150. ) {
  151. cell.textLabel?.text = switchMode.title
  152. let enabled: Bool?
  153. switch switchMode {
  154. case .favorite: enabled = subscription.alert.favourite
  155. case .follow: enabled = subscription.alert.follow
  156. case .reblog: enabled = subscription.alert.reblog
  157. case .mention: enabled = subscription.alert.mention
  158. }
  159. cell.update(enabled: enabled)
  160. }
  161. }