diff --git a/Multiplatform/iOS/Settings/Accounts/SettingsDetailAccountModel.swift b/Multiplatform/iOS/Settings/Accounts/SettingsDetailAccountModel.swift new file mode 100644 index 000000000..de4965ec5 --- /dev/null +++ b/Multiplatform/iOS/Settings/Accounts/SettingsDetailAccountModel.swift @@ -0,0 +1,55 @@ +// +// SettingsDetailAccountModel.swift +// Multiplatform iOS +// +// Created by Rizwan on 08/07/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI +import Account +import RSCore + +class SettingsDetailAccountModel: ObservableObject { + let account: Account + @Published var name: String { + didSet { + account.name = name.isEmpty ? nil : name + } + } + @Published var isActive: Bool { + didSet { + account.isActive = isActive + } + } + + init(_ account: Account) { + self.account = account + self.name = account.name ?? "" + self.isActive = account.isActive + } + + var defaultName: String { + account.defaultName + } + + var nameForDisplay: String { + account.nameForDisplay + } + + var accountImage: RSImage { + AppAssets.image(for: account.type)! + } + + var isCredentialsAvailable: Bool { + return account.type != .onMyMac + } + + var isDeletable: Bool { + return AccountManager.shared.defaultAccount != account + } + + func delete() { + AccountManager.shared.deleteAccount(account) + } +} diff --git a/Multiplatform/iOS/Settings/Accounts/SettingsDetailAccountView.swift b/Multiplatform/iOS/Settings/Accounts/SettingsDetailAccountView.swift new file mode 100644 index 000000000..c28c787e6 --- /dev/null +++ b/Multiplatform/iOS/Settings/Accounts/SettingsDetailAccountView.swift @@ -0,0 +1,94 @@ +// +// SettingsDetailAccountView.swift +// Multiplatform iOS +// +// Created by Rizwan on 08/07/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI +import Combine +import Account +import RSWeb +import RSCore + +struct SettingsDetailAccountView: View { + @Environment(\.presentationMode) var presentationMode + @ObservedObject var settingsModel: SettingsDetailAccountModel + @State private var isFeedbinCredentialsPresented = false + @State private var isDeleteAlertPresented = false + + init(_ account: Account) { + settingsModel = SettingsDetailAccountModel.init(account) + } + + var body: some View { + List { + Section(header:AccountHeaderImageView(image: settingsModel.accountImage)) { + HStack { + TextField(settingsModel.defaultName, text: $settingsModel.name) + } + Toggle(isOn: $settingsModel.isActive) { + Text("Active") + } + } + if settingsModel.isCredentialsAvailable { + Section { + HStack { + Spacer() + Button(action: { + self.isFeedbinCredentialsPresented.toggle() + }) { + Text("Credentials") + } + Spacer() + } + } + .sheet(isPresented: $isFeedbinCredentialsPresented) { + self.settingsFeedbinAccountView + } + } + if settingsModel.isDeletable { + Section { + HStack { + Spacer() + Button(action: { + self.isDeleteAlertPresented.toggle() + }) { + Text("Delete Account").foregroundColor(.red) + } + Spacer() + } + .alert(isPresented: $isDeleteAlertPresented) { + Alert( + title: Text("Are you sure you want to delete \"\(settingsModel.nameForDisplay)\"?"), + primaryButton: Alert.Button.default( + Text("Delete"), + action: { + self.settingsModel.delete() + self.dismiss() + }), + secondaryButton: Alert.Button.cancel() + ) + } + } + } + } + .listStyle(InsetGroupedListStyle()) + .navigationBarTitle(Text(verbatim: settingsModel.nameForDisplay), displayMode: .inline) + } + + var settingsFeedbinAccountView: SettingsFeedbinAccountView { + return SettingsFeedbinAccountView(account: settingsModel.account) + } + + func dismiss() { + presentationMode.wrappedValue.dismiss() + } +} + +struct SettingsDetailAccountView_Previews: PreviewProvider { + static var previews: some View { + return SettingsDetailAccountView(AccountManager.shared.defaultAccount) + } +} diff --git a/Multiplatform/iOS/Settings/Accounts/SettingsFeedbinAccountView.swift b/Multiplatform/iOS/Settings/Accounts/SettingsFeedbinAccountView.swift index 8d9f236ff..884e26eed 100644 --- a/Multiplatform/iOS/Settings/Accounts/SettingsFeedbinAccountView.swift +++ b/Multiplatform/iOS/Settings/Accounts/SettingsFeedbinAccountView.swift @@ -14,7 +14,16 @@ import Secrets struct SettingsFeedbinAccountView: View { @Environment(\.presentationMode) var presentationMode - @StateObject var settingsModel = SettingsFeedbinAccountModel() + @ObservedObject var settingsModel: SettingsFeedbinAccountModel + + init(account: Account? = nil) { + if let account = account { + self.settingsModel = SettingsFeedbinAccountModel(account: account) + } + else { + self.settingsModel = SettingsFeedbinAccountModel() + } + } var body: some View { NavigationView { diff --git a/Multiplatform/iOS/Settings/SettingsModel.swift b/Multiplatform/iOS/Settings/SettingsModel.swift index ef37b7f16..a8229118d 100644 --- a/Multiplatform/iOS/Settings/SettingsModel.swift +++ b/Multiplatform/iOS/Settings/SettingsModel.swift @@ -7,6 +7,7 @@ // import Foundation +import Account class SettingsModel: ObservableObject { @@ -36,6 +37,23 @@ class SettingsModel: ObservableObject { } @Published var presentSheet: Bool = false + var accounts: [Account] { + get { + AccountManager.shared.sortedAccounts + } + set { + + } + } + + // MARK: Init + + init() { + NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange), name: .DisplayNameDidChange, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(userDidAddAccount), name: .UserDidAddAccount, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(userDidDeleteAccount), name: .UserDidDeleteAccount, object: nil) + } + var selectedWebsite: HelpSites = .none { didSet { if selectedWebsite == .none { @@ -45,5 +63,22 @@ class SettingsModel: ObservableObject { } } } - + + func refreshAccounts() { + objectWillChange.self.send() + } + + // MARK:- Notifications + + @objc func displayNameDidChange() { + refreshAccounts() + } + + @objc func userDidAddAccount() { + refreshAccounts() + } + + @objc func userDidDeleteAccount() { + refreshAccounts() + } } diff --git a/Multiplatform/iOS/Settings/SettingsView.swift b/Multiplatform/iOS/Settings/SettingsView.swift index 8f501dec0..1c1ee1fa3 100644 --- a/Multiplatform/iOS/Settings/SettingsView.swift +++ b/Multiplatform/iOS/Settings/SettingsView.swift @@ -12,7 +12,6 @@ import UniformTypeIdentifiers struct SettingsView: View { - let sortedAccounts = AccountManager.shared.sortedAccounts @Environment(\.presentationMode) var presentationMode @Environment(\.exportFiles) var exportAction @Environment(\.importFiles) var importAction @@ -59,11 +58,11 @@ struct SettingsView: View { var accounts: some View { Section(header: Text("Accounts"), content: { - ForEach(0.. ActionSheet { - var buttons = sortedAccounts.map { (account) -> ActionSheet.Button in + var buttons = viewModel.accounts.map { (account) -> ActionSheet.Button in ActionSheet.Button.default(Text(account.nameForDisplay)) { importOPML(account: account) } @@ -116,7 +115,7 @@ struct SettingsView: View { } private func exportActionSheet() -> ActionSheet { - var buttons = sortedAccounts.map { (account) -> ActionSheet.Button in + var buttons = viewModel.accounts.map { (account) -> ActionSheet.Button in ActionSheet.Button.default(Text(account.nameForDisplay)) { exportOPML(account: account) } diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 36b3086de..a800c8515 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -677,8 +677,10 @@ 6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */; }; 6581C74020CED60100F4AD34 /* netnewswire-subscribe-to-feed.js in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73F20CED60100F4AD34 /* netnewswire-subscribe-to-feed.js */; }; 6581C74220CED60100F4AD34 /* ToolbarItemIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 6581C74120CED60100F4AD34 /* ToolbarItemIcon.pdf */; }; + 6586A5F724B632F8002BCF4F /* SettingsDetailAccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6586A5F624B632F8002BCF4F /* SettingsDetailAccountModel.swift */; }; 6591720E24B59C5100B638E8 /* SettingsFeedbinAccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6591720D24B59C5100B638E8 /* SettingsFeedbinAccountModel.swift */; }; 6591723124B5C35400B638E8 /* AccountHeaderImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6591723024B5C35400B638E8 /* AccountHeaderImageView.swift */; }; + 6591727F24B5D19500B638E8 /* SettingsDetailAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6591727E24B5D19500B638E8 /* SettingsDetailAccountView.swift */; }; 6594CA3B24AF6F2A005C7D7C /* OPMLExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8444C8F11FED81840051386C /* OPMLExporter.swift */; }; 65ACE48424B4779B003AE06A /* SettingsAddAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65ACE48324B4779B003AE06A /* SettingsAddAccountView.swift */; }; 65ACE48624B477C9003AE06A /* SettingsAccountLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65ACE48524B477C9003AE06A /* SettingsAccountLabelView.swift */; }; @@ -2096,8 +2098,10 @@ 6581C73F20CED60100F4AD34 /* netnewswire-subscribe-to-feed.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "netnewswire-subscribe-to-feed.js"; sourceTree = ""; }; 6581C74120CED60100F4AD34 /* ToolbarItemIcon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ToolbarItemIcon.pdf; sourceTree = ""; }; 6581C74320CED60100F4AD34 /* Subscribe_to_Feed.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Subscribe_to_Feed.entitlements; sourceTree = ""; }; + 6586A5F624B632F8002BCF4F /* SettingsDetailAccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDetailAccountModel.swift; sourceTree = ""; }; 6591720D24B59C5100B638E8 /* SettingsFeedbinAccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFeedbinAccountModel.swift; sourceTree = ""; }; 6591723024B5C35400B638E8 /* AccountHeaderImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountHeaderImageView.swift; sourceTree = ""; }; + 6591727E24B5D19500B638E8 /* SettingsDetailAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDetailAccountView.swift; sourceTree = ""; }; 65ACE48324B4779B003AE06A /* SettingsAddAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAddAccountView.swift; sourceTree = ""; }; 65ACE48524B477C9003AE06A /* SettingsAccountLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAccountLabelView.swift; sourceTree = ""; }; 65ACE48724B48020003AE06A /* SettingsLocalAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsLocalAccountView.swift; sourceTree = ""; }; @@ -3162,6 +3166,8 @@ 65ACE48924B4C2D8003AE06A /* SettingsFeedbinAccountView.swift */, 6591720D24B59C5100B638E8 /* SettingsFeedbinAccountModel.swift */, 6591723024B5C35400B638E8 /* AccountHeaderImageView.swift */, + 6591727E24B5D19500B638E8 /* SettingsDetailAccountView.swift */, + 6586A5F624B632F8002BCF4F /* SettingsDetailAccountModel.swift */, ); path = Accounts; sourceTree = ""; @@ -5044,6 +5050,7 @@ 17D232A824AFF10A0005F075 /* AddWebFeedModel.swift in Sources */, 51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */, 51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */, + 6586A5F724B632F8002BCF4F /* SettingsDetailAccountModel.swift in Sources */, 51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */, 51919FB624AABCA100541E64 /* IconImageView.swift in Sources */, 51919FA624AA64B000541E64 /* SidebarView.swift in Sources */, @@ -5069,6 +5076,7 @@ 51919FB324AAB97900541E64 /* FeedIconImageLoader.swift in Sources */, 51E4991324A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */, 51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */, + 6591727F24B5D19500B638E8 /* SettingsDetailAccountView.swift in Sources */, 51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */, 51A576BB24AE621800078888 /* ArticleModel.swift in Sources */, 65ACE48824B48020003AE06A /* SettingsLocalAccountView.swift in Sources */,