Add FreshRSS add account back into settings
This commit is contained in:
parent
5c59427e90
commit
157bd57c5e
|
@ -7,6 +7,7 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
510BD15D232D765D002692E4 /* SettingsReaderAPIAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557EE1A522B6F4E1004206FA /* SettingsReaderAPIAccountView.swift */; };
|
||||||
51126DA4225FDE2F00722696 /* RSImage-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */; };
|
51126DA4225FDE2F00722696 /* RSImage-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */; };
|
||||||
5115CAF42266301400B21BCE /* AddContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51121B5A22661FEF00BC0EC1 /* AddContainerViewController.swift */; };
|
5115CAF42266301400B21BCE /* AddContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51121B5A22661FEF00BC0EC1 /* AddContainerViewController.swift */; };
|
||||||
511D43CF231FA62200FB1562 /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; };
|
511D43CF231FA62200FB1562 /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; };
|
||||||
|
@ -2651,6 +2652,7 @@
|
||||||
514B7C8323205EFB00BAC947 /* RootSplitViewController.swift in Sources */,
|
514B7C8323205EFB00BAC947 /* RootSplitViewController.swift in Sources */,
|
||||||
5152E0F923248F6200E5C7AD /* SettingsLocalAccountView.swift in Sources */,
|
5152E0F923248F6200E5C7AD /* SettingsLocalAccountView.swift in Sources */,
|
||||||
FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */,
|
FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */,
|
||||||
|
510BD15D232D765D002692E4 /* SettingsReaderAPIAccountView.swift in Sources */,
|
||||||
51C4525C226508DF00C03939 /* String-Extensions.swift in Sources */,
|
51C4525C226508DF00C03939 /* String-Extensions.swift in Sources */,
|
||||||
51C452792265091600C03939 /* MasterTimelineTableViewCell.swift in Sources */,
|
51C452792265091600C03939 /* MasterTimelineTableViewCell.swift in Sources */,
|
||||||
51C452852265093600C03939 /* FlattenedAccountFolderPickerData.swift in Sources */,
|
51C452852265093600C03939 /* FlattenedAccountFolderPickerData.swift in Sources */,
|
||||||
|
|
|
@ -20,6 +20,9 @@ struct SettingsAddAccountView : View {
|
||||||
NavigationLink(destination: SettingsFeedbinAccountView(viewModel: SettingsFeedbinAccountView.ViewModel())) {
|
NavigationLink(destination: SettingsFeedbinAccountView(viewModel: SettingsFeedbinAccountView.ViewModel())) {
|
||||||
SettingsAccountLabelView(accountImage: "accountFeedbin", accountLabel: "Feedbin")
|
SettingsAccountLabelView(accountImage: "accountFeedbin", accountLabel: "Feedbin")
|
||||||
}
|
}
|
||||||
|
NavigationLink(destination: SettingsReaderAPIAccountView(viewModel: SettingsReaderAPIAccountView.ViewModel(accountType: .freshRSS))) {
|
||||||
|
SettingsAccountLabelView(accountImage: "accountFreshRSS", accountLabel: "Fresh RSS")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitle(Text("Add Account"), displayMode: .inline)
|
.navigationBarTitle(Text("Add Account"), displayMode: .inline)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import RSWeb
|
||||||
struct SettingsDetailAccountView : View {
|
struct SettingsDetailAccountView : View {
|
||||||
@Environment(\.presentationMode) var presentation
|
@Environment(\.presentationMode) var presentation
|
||||||
@ObservedObject var viewModel: ViewModel
|
@ObservedObject var viewModel: ViewModel
|
||||||
@State private var isFeedbinCredentialsPresented = false
|
@State private var accountType: AccountType = nil
|
||||||
@State private var isDeleteAlertPresented = false
|
@State private var isDeleteAlertPresented = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -32,15 +32,20 @@ struct SettingsDetailAccountView : View {
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.isFeedbinCredentialsPresented.toggle()
|
self.accountType = self.viewModel.account.type
|
||||||
}) {
|
}) {
|
||||||
Text("Credentials")
|
Text("Credentials")
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $isFeedbinCredentialsPresented) {
|
.sheet(item: $accountType) { type in
|
||||||
self.settingsFeedbinAccountView
|
if type == .feedbin {
|
||||||
|
self.settingsFeedbinAccountView
|
||||||
|
}
|
||||||
|
if type == .freshRSS {
|
||||||
|
self.settingsReaderAPIAccountView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if viewModel.isDeletable {
|
if viewModel.isDeletable {
|
||||||
|
@ -74,6 +79,11 @@ struct SettingsDetailAccountView : View {
|
||||||
return SettingsFeedbinAccountView(viewModel: feedbinViewModel)
|
return SettingsFeedbinAccountView(viewModel: feedbinViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var settingsReaderAPIAccountView: SettingsReaderAPIAccountView {
|
||||||
|
let readerAPIModel = SettingsReaderAPIAccountView.ViewModel(account: viewModel.account)
|
||||||
|
return SettingsReaderAPIAccountView(viewModel: readerAPIModel)
|
||||||
|
}
|
||||||
|
|
||||||
class ViewModel: ObservableObject {
|
class ViewModel: ObservableObject {
|
||||||
|
|
||||||
let objectWillChange = ObservableObjectPublisher()
|
let objectWillChange = ObservableObjectPublisher()
|
||||||
|
|
|
@ -12,74 +12,61 @@ import Account
|
||||||
import RSWeb
|
import RSWeb
|
||||||
|
|
||||||
struct SettingsReaderAPIAccountView : View {
|
struct SettingsReaderAPIAccountView : View {
|
||||||
@Environment(\.isPresented) private var isPresented
|
@Environment(\.presentationMode) var presentation
|
||||||
@ObjectBinding var viewModel: ViewModel
|
@ObservedObject var viewModel: ViewModel
|
||||||
|
|
||||||
@State var busy: Bool = false
|
@State var busy: Bool = false
|
||||||
@State var error: Text = Text("")
|
@State var error: String = ""
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
Form {
|
||||||
List {
|
Section(header:
|
||||||
Section(header:
|
HStack {
|
||||||
SettingsAccountLabelView(accountImage: "accountFreshRSS", accountLabel: "FreshRSS").padding()
|
Spacer()
|
||||||
) {
|
SettingsAccountLabelView(accountImage: "accountFreshRSS", accountLabel: "FreshRSS")
|
||||||
HStack {
|
.padding()
|
||||||
Text("Email:")
|
.layoutPriority(1.0)
|
||||||
Divider()
|
Spacer()
|
||||||
TextField($viewModel.email)
|
|
||||||
.textContentType(.username)
|
|
||||||
}
|
|
||||||
HStack {
|
|
||||||
Text("Password:")
|
|
||||||
Divider()
|
|
||||||
SecureField($viewModel.password)
|
|
||||||
}
|
|
||||||
HStack {
|
|
||||||
Text("API URL:")
|
|
||||||
Divider()
|
|
||||||
TextField($viewModel.apiURL)
|
|
||||||
.textContentType(.URL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Section(footer:
|
) {
|
||||||
HStack {
|
TextField("Email", text: $viewModel.email).textContentType(.username)
|
||||||
Spacer()
|
SecureField("Password", text: $viewModel.password)
|
||||||
error.color(.red)
|
TextField("API URL:", text: $viewModel.apiURL).textContentType(.URL)
|
||||||
Spacer()
|
}
|
||||||
}
|
|
||||||
) {
|
Section(footer:
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Button(action: { self.addAccount() }) {
|
Text(verbatim: error).foregroundColor(.red)
|
||||||
if viewModel.isUpdate {
|
Spacer()
|
||||||
Text("Update Account")
|
}
|
||||||
} else {
|
) {
|
||||||
Text("Add Account")
|
HStack {
|
||||||
}
|
Spacer()
|
||||||
|
Button(action: { self.addAccount() }) {
|
||||||
|
if viewModel.isUpdate {
|
||||||
|
Text("Update Account")
|
||||||
|
} else {
|
||||||
|
Text("Add Account")
|
||||||
}
|
}
|
||||||
.disabled(!viewModel.isValid)
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
|
.disabled(!viewModel.isValid)
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disabled(busy)
|
|
||||||
.listStyle(.grouped)
|
|
||||||
.navigationBarTitle(Text(""), displayMode: .inline)
|
|
||||||
.navigationBarItems(leading:
|
|
||||||
Button(action: { self.dismiss() }) { Text("Cancel") }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
// .disabled(busy)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addAccount() {
|
private func addAccount() {
|
||||||
|
|
||||||
busy = true
|
busy = true
|
||||||
error = Text("")
|
error = ""
|
||||||
|
|
||||||
let emailAddress = viewModel.email.trimmingCharacters(in: .whitespaces)
|
let emailAddress = viewModel.email.trimmingCharacters(in: .whitespaces)
|
||||||
let credentials = Credentials.readerAPIBasicLogin(username: emailAddress, password: viewModel.password)
|
let credentials = Credentials.readerAPIBasicLogin(username: emailAddress, password: viewModel.password)
|
||||||
guard let apiURL = URL(string: viewModel.apiURL) else {
|
guard let apiURL = URL(string: viewModel.apiURL) else {
|
||||||
self.error = Text("Invalide API URL.")
|
self.error = "Invalid API URL."
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,15 +105,15 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
self.dismiss()
|
self.dismiss()
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
self.error = Text("Keychain error while storing credentials.")
|
self.error = "Keychain error while storing credentials."
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
self.error = Text("Invalid email/password combination.")
|
self.error = "Invalid email/password combination."
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure:
|
case .failure:
|
||||||
self.error = Text("Network error. Try again later.")
|
self.error = "Network error. Try again later."
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -134,11 +121,12 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dismiss() {
|
private func dismiss() {
|
||||||
isPresented?.value = false
|
presentation.wrappedValue.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewModel: BindableObject {
|
class ViewModel: ObservableObject {
|
||||||
let didChange = PassthroughSubject<ViewModel, Never>()
|
|
||||||
|
let objectWillChange = ObservableObjectPublisher()
|
||||||
var accountType: AccountType
|
var accountType: AccountType
|
||||||
var account: Account? = nil
|
var account: Account? = nil
|
||||||
|
|
||||||
|
@ -146,28 +134,29 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
self.accountType = accountType
|
self.accountType = accountType
|
||||||
}
|
}
|
||||||
|
|
||||||
init(accountType: AccountType, account: Account) {
|
init(account: Account) {
|
||||||
self.account = account
|
self.account = account
|
||||||
self.accountType = accountType
|
self.accountType = account.type
|
||||||
if case .basic(let username, let password) = try? account.retrieveCredentials() {
|
if case .readerAPIBasicLogin(let username, let password) = try? account.retrieveCredentials() {
|
||||||
self.email = username
|
self.email = username
|
||||||
self.password = password
|
self.password = password
|
||||||
|
self.apiURL = account.endpointURL?.absoluteString ?? ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var email: String = "" {
|
var email: String = "" {
|
||||||
didSet {
|
willSet {
|
||||||
didChange.send(self)
|
objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var password: String = "" {
|
var password: String = "" {
|
||||||
didSet {
|
willSet {
|
||||||
didChange.send(self)
|
objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var apiURL: String = "" {
|
var apiURL: String = "" {
|
||||||
didSet {
|
willSet {
|
||||||
didChange.send(self)
|
objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var isUpdate: Bool {
|
var isUpdate: Bool {
|
||||||
|
|
Loading…
Reference in New Issue