From f2e3870850080576b795bb8404dae56af78498e3 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Thu, 13 Jun 2019 17:53:17 -0700 Subject: [PATCH] Start rewriting preferences in SwiftUI --- Tusker.xcodeproj/project.pbxproj | 24 ++++++ Tusker/Extensions/Visibility+Helpers.swift | 12 ++- Tusker/Preferences/Preference.swift | 60 +++++++++++++++ Tusker/Preferences/Preferences.swift | 34 ++++++--- .../Compose/ComposeViewController.swift | 4 +- .../Preferences/AdvancedPrefsView.swift | 41 ++++++++++ .../Preferences/AppearancePrefsView.swift | 40 ++++++++++ .../Preferences/BehaviorPrefsView.swift | 49 ++++++++++++ .../Screens/Preferences/PreferencesView.swift | 37 ++++++++++ .../Preferences/SilentActionPrefs.swift | 74 +++++++++++++++++++ .../MyProfileTableViewController.swift | 11 ++- .../UIAlertController+Visibility.swift | 2 +- 12 files changed, 367 insertions(+), 21 deletions(-) create mode 100644 Tusker/Preferences/Preference.swift create mode 100644 Tusker/Screens/Preferences/AdvancedPrefsView.swift create mode 100644 Tusker/Screens/Preferences/AppearancePrefsView.swift create mode 100644 Tusker/Screens/Preferences/BehaviorPrefsView.swift create mode 100644 Tusker/Screens/Preferences/PreferencesView.swift create mode 100644 Tusker/Screens/Preferences/SilentActionPrefs.swift diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index c6ccbfb6..d69581a6 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -7,8 +7,14 @@ objects = { /* Begin PBXBuildFile section */ + 0427033622B30B3D000D31B6 /* Preference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0427033522B30B3D000D31B6 /* Preference.swift */; }; + 0427033822B30F5F000D31B6 /* BehaviorPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0427033722B30F5F000D31B6 /* BehaviorPrefsView.swift */; }; + 0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0427033922B31269000D31B6 /* AdvancedPrefsView.swift */; }; + 0427037C22B316B9000D31B6 /* SilentActionPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0427037B22B316B9000D31B6 /* SilentActionPrefs.swift */; }; 04496BD721625361001F1B23 /* ContentLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04496BD621625361001F1B23 /* ContentLabel.swift */; }; 0450531F22B0097E00100BA2 /* Timline+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0450531E22B0097E00100BA2 /* Timline+UI.swift */; }; + 04586B4122B2FFB10021BD04 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04586B4022B2FFB10021BD04 /* PreferencesView.swift */; }; + 04586B4322B301470021BD04 /* AppearancePrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04586B4222B301470021BD04 /* AppearancePrefsView.swift */; }; 0461A3902163CBAE00C0A807 /* Cache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0461A38F2163CBAE00C0A807 /* Cache.framework */; }; 0461A3912163CBAE00C0A807 /* Cache.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0461A38F2163CBAE00C0A807 /* Cache.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */; }; @@ -235,8 +241,14 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0427033522B30B3D000D31B6 /* Preference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preference.swift; sourceTree = ""; }; + 0427033722B30F5F000D31B6 /* BehaviorPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BehaviorPrefsView.swift; sourceTree = ""; }; + 0427033922B31269000D31B6 /* AdvancedPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedPrefsView.swift; sourceTree = ""; }; + 0427037B22B316B9000D31B6 /* SilentActionPrefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SilentActionPrefs.swift; sourceTree = ""; }; 04496BD621625361001F1B23 /* ContentLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentLabel.swift; sourceTree = ""; }; 0450531E22B0097E00100BA2 /* Timline+UI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Timline+UI.swift"; sourceTree = ""; }; + 04586B4022B2FFB10021BD04 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; + 04586B4222B301470021BD04 /* AppearancePrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePrefsView.swift; sourceTree = ""; }; 0461A38F2163CBAE00C0A807 /* Cache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Cache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarViewController.swift; sourceTree = ""; }; 04DACE8D212CC7CC009840C4 /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -702,6 +714,11 @@ D67E0512216438A7000E0927 /* AppearanceTableViewController.swift */, D627FF80217FE8F400CC0648 /* BehaviorTableViewController.swift */, D6C693C92161253F007D6A6D /* SilentActionPermissionsTableViewController.swift */, + 04586B4022B2FFB10021BD04 /* PreferencesView.swift */, + 04586B4222B301470021BD04 /* AppearancePrefsView.swift */, + 0427033722B30F5F000D31B6 /* BehaviorPrefsView.swift */, + 0427033922B31269000D31B6 /* AdvancedPrefsView.swift */, + 0427037B22B316B9000D31B6 /* SilentActionPrefs.swift */, ); path = Preferences; sourceTree = ""; @@ -760,6 +777,7 @@ D663626121360B1900C9CBA2 /* Preferences.swift */, D663626321360D2300C9CBA2 /* AvatarStyle.swift */, D66362692136163000C9CBA2 /* PreferencesAdaptive.swift */, + 0427033522B30B3D000D31B6 /* Preference.swift */, ); path = Preferences; sourceTree = ""; @@ -1353,6 +1371,7 @@ buildActionMask = 2147483647; files = ( D6285B5321EA708700FE4B39 /* StatusFormat.swift in Sources */, + 0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */, D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */, 04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */, D6C693F92162E4DB007D6A6D /* StatusContentLabel.swift in Sources */, @@ -1381,11 +1400,13 @@ D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */, D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */, D6BED174212667E900F02DA0 /* StatusTableViewCell.swift in Sources */, + 0427033822B30F5F000D31B6 /* BehaviorPrefsView.swift in Sources */, D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */, D6C94D892139E6EC00CB5196 /* AttachmentView.swift in Sources */, D6C693EF216192C2007D6A6D /* TuskerNavigationDelegate.swift in Sources */, D6C94D872139E62700CB5196 /* LargeImageViewController.swift in Sources */, D6434EB3215B1856001A919A /* XCBRequest.swift in Sources */, + 0427033622B30B3D000D31B6 /* Preference.swift in Sources */, D663626221360B1900C9CBA2 /* Preferences.swift in Sources */, D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */, D641C77F213DC78A004B4513 /* InlineTextAttachment.swift in Sources */, @@ -1401,12 +1422,14 @@ D627FF76217E923E00CC0648 /* DraftsManager.swift in Sources */, D663626821360E2C00C9CBA2 /* PreferencesTableViewController.swift in Sources */, D64F80E2215875CC00BEF393 /* XCBActionType.swift in Sources */, + 04586B4322B301470021BD04 /* AppearancePrefsView.swift in Sources */, D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */, D66362752137068A00C9CBA2 /* Visibility+Helpers.swift in Sources */, D67E0513216438A7000E0927 /* AppearanceTableViewController.swift in Sources */, D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */, D646C95A213B5D0500269FB5 /* LargeImageInteractionController.swift in Sources */, D6F953EC212519E700CF0F2B /* TimelineTableViewController.swift in Sources */, + 04586B4122B2FFB10021BD04 /* PreferencesView.swift in Sources */, D663626A2136163000C9CBA2 /* PreferencesAdaptive.swift in Sources */, D667E5EB21349EF80057A976 /* ProfileHeaderTableViewCell.swift in Sources */, D641C77D213CB024004B4513 /* FollowNotificationTableViewCell.swift in Sources */, @@ -1414,6 +1437,7 @@ D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */, D6C693CF216125FC007D6A6D /* SilentActionPermissionTableViewCell.swift in Sources */, D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */, + 0427037C22B316B9000D31B6 /* SilentActionPrefs.swift in Sources */, D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */, D667E5F12134D5050057A976 /* UIViewController+Delegates.swift in Sources */, D6BC8748219738E1006163F1 /* EnhancedTableViewController.swift in Sources */, diff --git a/Tusker/Extensions/Visibility+Helpers.swift b/Tusker/Extensions/Visibility+Helpers.swift index b69dbad3..2d2f2495 100644 --- a/Tusker/Extensions/Visibility+Helpers.swift +++ b/Tusker/Extensions/Visibility+Helpers.swift @@ -24,19 +24,17 @@ extension Status.Visibility { } } - var image: UIImage { - let name: String + var imageName: String { switch self { case .public: - name = "globe" + return "globe" case .unlisted: - name = "lock.open.fill" + return "lock.open.fill" case .private: - name = "lock.fill" + return "lock.fill" case .direct: - name = "envelope.fill" + return "envelope.fill" } - return UIImage(systemName: name)! } } diff --git a/Tusker/Preferences/Preference.swift b/Tusker/Preferences/Preference.swift new file mode 100644 index 00000000..ac05294f --- /dev/null +++ b/Tusker/Preferences/Preference.swift @@ -0,0 +1,60 @@ +// Preference.swift +// Tusker +// +// Created by Shadowfacts on 6/13/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI + +@propertyWrapper +struct Preference: BindingConvertible { + let path: WritableKeyPath + let binding: Binding + + init(_ path: WritableKeyPath) { + self.path = path + self.binding = Binding(getValue: { + return Preferences.shared[keyPath: path] + }, setValue: { (newValue) in + Preferences.shared[keyPath: path] = newValue + }) + } + + var value: Value { + get { + return Preferences.shared[keyPath: path] + } + set { + Preferences.shared[keyPath: path] = newValue + } + } +} + +@propertyWrapper +struct MappedPreference: BindingConvertible { + let path: WritableKeyPath + let fromPref: (PrefValue) -> Value + let toPref: (Value) -> PrefValue + let binding: Binding + + init(_ path: WritableKeyPath, fromPref: @escaping (PrefValue) -> Value, toPref: @escaping (Value) -> PrefValue) { + self.path = path + self.fromPref = fromPref + self.toPref = toPref + self.binding = Binding(getValue: { + return fromPref(Preferences.shared[keyPath: path]) + }, setValue: { (newValue) in + Preferences.shared[keyPath: path] = toPref(newValue) + }) + } + + var value: Value { + get { + return fromPref(Preferences.shared[keyPath: path]) + } + set { + Preferences.shared[keyPath: path] = toPref(newValue) + } + } +} diff --git a/Tusker/Preferences/Preferences.swift b/Tusker/Preferences/Preferences.swift index f29bcc91..35408677 100644 --- a/Tusker/Preferences/Preferences.swift +++ b/Tusker/Preferences/Preferences.swift @@ -8,10 +8,12 @@ import Foundation import Pachyderm +import SwiftUI +import Combine -class Preferences: Codable { +class Preferences: Codable, BindableObject { - private(set) static var shared: Preferences = load() + static var shared: Preferences = load() private static var documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! private static var archiveURL = Preferences.documentsDirectory.appendingPathComponent("preferences").appendingPathExtension("plist") @@ -33,22 +35,34 @@ class Preferences: Codable { private init() {} + let didChange = PassthroughSubject() + // MARK: - Appearance - var showRepliesInProfiles = false - var avatarStyle = AvatarStyle.roundRect - var hideCustomEmojiInUsernames = false + var showRepliesInProfiles = false { didSet { didChange.send(self) } } + var avatarStyle = AvatarStyle.roundRect { didSet { didChange.send(self) } } + var hideCustomEmojiInUsernames = false { didSet { didChange.send(self) } } // MARK: - Behavior - var defaultPostVisibility = Status.Visibility.public - var automaticallySaveDrafts = true - var openLinksInApps = true + var defaultPostVisibility = Status.Visibility.public { didSet { didChange.send(self) } } + var automaticallySaveDrafts = true { didSet { didChange.send(self) } } + var openLinksInApps = true { didSet { didChange.send(self) } } // MARK: - Advanced - var silentActions: [String: Permission] = [:] - var statusContentType: StatusContentType = .plain + var silentActions: [String: Permission] = [:] { didSet { didChange.send(self) } } + var statusContentType: StatusContentType = .plain { didSet { didChange.send(self) } } } +extension PassthroughSubject: Codable { + public convenience init(from decoder: Decoder) throws { + self.init() + } + + public func encode(to encoder: Encoder) throws { + + } +} + extension Preferences { enum Permission: String, Codable { case undecided, accepted, rejected diff --git a/Tusker/Screens/Compose/ComposeViewController.swift b/Tusker/Screens/Compose/ComposeViewController.swift index 96b645ec..1e277833 100644 --- a/Tusker/Screens/Compose/ComposeViewController.swift +++ b/Tusker/Screens/Compose/ComposeViewController.swift @@ -103,7 +103,7 @@ class ComposeViewController: UIViewController { let toolbar = UIToolbar() contentWarningBarButtonItem = UIBarButtonItem(title: "CW", style: .plain, target: self, action: #selector(contentWarningButtonPressed)) - visibilityBarButtonItem = UIBarButtonItem(image: Preferences.shared.defaultPostVisibility.image, style: .plain, target: self, action: #selector(visibilityButtonPressed)) + visibilityBarButtonItem = UIBarButtonItem(image: UIImage(systemName: Preferences.shared.defaultPostVisibility.imageName), style: .plain, target: self, action: #selector(visibilityButtonPressed)) toolbar.items = [ contentWarningBarButtonItem, visibilityBarButtonItem, @@ -297,7 +297,7 @@ class ComposeViewController: UIViewController { } func visibilityChanged() { - visibilityBarButtonItem.image = visibility.image + visibilityBarButtonItem.image = UIImage(systemName: visibility.imageName) } func saveDraft() { diff --git a/Tusker/Screens/Preferences/AdvancedPrefsView.swift b/Tusker/Screens/Preferences/AdvancedPrefsView.swift new file mode 100644 index 00000000..91364902 --- /dev/null +++ b/Tusker/Screens/Preferences/AdvancedPrefsView.swift @@ -0,0 +1,41 @@ +// AdvancedPrefsView.swift +// Tusker +// +// Created by Shadowfacts on 6/13/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI +import Pachyderm + +struct AdvancedPrefsView : View { + @Preference(\.statusContentType) var statusContentType: StatusContentType + + var body: some View { + List { + Section(footer: Text("This option is only supported for Pleroma and Mastodon instances with formatting enabled. On all other instances, formatting symbols will remain in the unformatted plain text.").lineLimit(nil)) { + Picker(selection: $statusContentType.binding, label: Text("Post Content Type")) { + ForEach(StatusContentType.allCases.identified(by: \.self)) { type in + Text(type.displayName).tag(type) + } + } + } + + Section(header: Text("AUTOMATION")) { + NavigationButton(destination: SilentActionPrefs()) { + Text("Silent Action Permissions") + } + } + } + .listStyle(.grouped) + .navigationBarTitle(Text("Advanced")) + } +} + +#if DEBUG +struct AdvancedPrefsView_Previews : PreviewProvider { + static var previews: some View { + AdvancedPrefsView() + } +} +#endif diff --git a/Tusker/Screens/Preferences/AppearancePrefsView.swift b/Tusker/Screens/Preferences/AppearancePrefsView.swift new file mode 100644 index 00000000..c115d1fc --- /dev/null +++ b/Tusker/Screens/Preferences/AppearancePrefsView.swift @@ -0,0 +1,40 @@ +// AppearancePrefsView.swift +// Tusker +// +// Created by Shadowfacts on 6/13/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI + +struct AppearancePrefsView : View { + @Preference(\.showRepliesInProfiles) var showRepliesInProfiles: Bool + @Preference(\.hideCustomEmojiInUsernames) var hideCustomEmojiInUsernames: Bool + + @MappedPreference(\.avatarStyle, fromPref: { $0 == .circle }, toPref: { $0 ? .circle : .roundRect }) + var useCircularAvatars: Bool + + var body: some View { + List { + Toggle(isOn: $showRepliesInProfiles.binding) { + Text("Show Replies in Profiles") + } + Toggle(isOn: $useCircularAvatars.binding) { + Text("Use Circular Avatars") + } + Toggle(isOn: $hideCustomEmojiInUsernames.binding) { + Text("Hide Custom Emoji in Usernames") + } + } + .listStyle(.grouped) + .navigationBarTitle(Text("Appearance")) + } +} + +#if DEBUG +struct AppearancePrefsView_Previews : PreviewProvider { + static var previews: some View { + AppearancePrefsView() + } +} +#endif diff --git a/Tusker/Screens/Preferences/BehaviorPrefsView.swift b/Tusker/Screens/Preferences/BehaviorPrefsView.swift new file mode 100644 index 00000000..6404fb25 --- /dev/null +++ b/Tusker/Screens/Preferences/BehaviorPrefsView.swift @@ -0,0 +1,49 @@ +// BehaviorPrefsView.swift +// Tusker +// +// Created by Shadowfacts on 6/13/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI +import Pachyderm + +struct BehaviorPrefsView : View { + @Preference(\.defaultPostVisibility) var defaultPostVisibility: Status.Visibility + @Preference(\.automaticallySaveDrafts) var automaticallySaveDrafts: Bool + @Preference(\.openLinksInApps) var openLinksInApps: Bool + + var body: some View { + List { + Section { + Picker(selection: $defaultPostVisibility.binding, label: Text("Default Post Visibility")) { + ForEach(Status.Visibility.allCases.identified(by: \.self)) { visibility in + HStack { + Image(systemName: visibility.imageName) + Text(visibility.displayName) + } + .tag(visibility) + } + } + Toggle(isOn: $automaticallySaveDrafts.binding) { + Text("Automatically Save Drafts") + } + } + Section { + Toggle(isOn: $openLinksInApps.binding) { + Text("Open Links in Apps") + } + } + } + .listStyle(.grouped) + .navigationBarTitle(Text("Behavior")) + } +} + +#if DEBUG +struct BehaviorPrefsView_Previews : PreviewProvider { + static var previews: some View { + BehaviorPrefsView() + } +} +#endif diff --git a/Tusker/Screens/Preferences/PreferencesView.swift b/Tusker/Screens/Preferences/PreferencesView.swift new file mode 100644 index 00000000..4cbfea4f --- /dev/null +++ b/Tusker/Screens/Preferences/PreferencesView.swift @@ -0,0 +1,37 @@ +// PreferencesView.swift +// Tusker +// +// Created by Shadowfacts on 6/13/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI + +struct PreferencesView : View { + var body: some View { + // workaround: the navigation view is provided by MyProfileTableViewController so that it can inject the Done button +// NavigationView { + List { + NavigationButton(destination: AppearancePrefsView()) { + Text("Appearance") + } + NavigationButton(destination: BehaviorPrefsView()) { + Text("Behavior") + } + NavigationButton(destination: AdvancedPrefsView()) { + Text("Advanced") + } + } + .listStyle(.grouped) + .navigationBarTitle(Text("Preferences"), displayMode: .inline) +// } + } +} + +#if DEBUG +struct PreferencesView_Previews : PreviewProvider { + static var previews: some View { + PreferencesView() + } +} +#endif diff --git a/Tusker/Screens/Preferences/SilentActionPrefs.swift b/Tusker/Screens/Preferences/SilentActionPrefs.swift new file mode 100644 index 00000000..b45cb4a0 --- /dev/null +++ b/Tusker/Screens/Preferences/SilentActionPrefs.swift @@ -0,0 +1,74 @@ +// SilentActionPrefs.swift +// Tusker +// +// Created by Shadowfacts on 6/13/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI + +//struct SilentActionPermission: Identifiable { +// let application: String +// let permission: Preferences.Permission +// +// var id: String { +// return application +// } +// +// init(_ application: String, _ permission: Preferences.Permission) { +// self.application = application +// self.permission = permission +// } +//} + +struct SilentActionPrefs : View { +// @MappedPreference(\.silentActions, fromPref: { +// var array = [SilentActionPermission]() +// for (application, permission) in $0 { +// array.append(SilentActionPermission(application, permission)) +// } +// return array +// }) +// var silentActionPermissions: [SilentActionPermission] +// @Preference(\.silentActions) var silentActions: [String: Preferences.Permission] + @EnvironmentObject var preferences: Preferences + + var body: some View { + List(Array(preferences.silentActions.keys).identified(by: \.self)) { source in + SilentActionPermissionCell(source: source) + }.listStyle(.grouped) +// List(Array(silentActions.keys).identified(by: \.self)) { application in +// Text(application) +//// Toggle(isOn: Binding(getValue: { self.silentActions[application] == .accepted }, setValue: { self.silentActions[application] = $0 ? .accepted : .rejected }), label: Text(application)) +// }.listStyle(.grouped) + } +} + +struct SilentActionPermissionCell: View { + @EnvironmentObject var preferences: Preferences + let source: String +// var binding: Binding + + init(source: String) { + self.source = source +// self.binding = Binding(getValue: { self.preferences.silentActions[source] == .accepted }, setValue: { self.preferences.silentActions[source] = $0 ? .accepted : .rejected }) + } + + var body: some View { + Toggle(isOn: Binding(getValue: { + self.preferences.silentActions[self.source] == .accepted + }, setValue: { + self.preferences.silentActions[self.source] = $0 ? .accepted : .rejected + })) { + Text(verbatim: source) + } + } +} + +#if DEBUG +struct SilentActionPrefs_Previews : PreviewProvider { + static var previews: some View { + SilentActionPrefs().environmentObject(Preferences.shared) + } +} +#endif diff --git a/Tusker/Screens/Profile/MyProfileTableViewController.swift b/Tusker/Screens/Profile/MyProfileTableViewController.swift index 170a6d61..4f284de8 100644 --- a/Tusker/Screens/Profile/MyProfileTableViewController.swift +++ b/Tusker/Screens/Profile/MyProfileTableViewController.swift @@ -7,6 +7,7 @@ // import UIKit +import SwiftUI class MyProfileTableViewController: ProfileTableViewController { @@ -50,7 +51,15 @@ class MyProfileTableViewController: ProfileTableViewController { } @objc func preferencesPressed() { - present(PreferencesTableViewController.create(), animated: true) + let view = PreferencesView().environmentObject(Preferences.shared) + let hostingController = UIHostingController(rootView: view) + let navigationController = UINavigationController(rootViewController: hostingController) + hostingController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(closePreferences)) + present(navigationController, animated: true) + } + + @objc func closePreferences() { + dismiss(animated: true) } } diff --git a/Tusker/Screens/Utilities/UIAlertController+Visibility.swift b/Tusker/Screens/Utilities/UIAlertController+Visibility.swift index 41f5bc92..6f4d8040 100644 --- a/Tusker/Screens/Utilities/UIAlertController+Visibility.swift +++ b/Tusker/Screens/Utilities/UIAlertController+Visibility.swift @@ -21,7 +21,7 @@ extension UIAlertController { if visibility == currentVisibility { action.setValue(true, forKey: "checked") } - action.setValue(visibility.image, forKey: "image") + action.setValue(UIImage(systemName: visibility.imageName), forKey: "image") addAction(action) }