diff --git a/Multiplatform/Shared/Add/Add Account Models/AddFeedlyViewModel.swift b/Multiplatform/Shared/Add/Add Account Models/AddFeedlyViewModel.swift index e2e784459..7312b2f61 100644 --- a/Multiplatform/Shared/Add/Add Account Models/AddFeedlyViewModel.swift +++ b/Multiplatform/Shared/Add/Add Account Models/AddFeedlyViewModel.swift @@ -25,6 +25,8 @@ class AddFeedlyViewModel: ObservableObject, OAuthAccountAuthorizationOperationDe addAccount.delegate = self #if os(macOS) addAccount.presentationAnchor = NSApplication.shared.windows.last + #else + addAccount.presentationAnchor = UIApplication.shared.windows.last #endif MainThreadOperationQueue.shared.add(addAccount) } diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddCloudKitAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddCloudKitAccountView.swift index 2db283e5b..b7ee03318 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddCloudKitAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddCloudKitAccountView.swift @@ -18,7 +18,9 @@ struct AddCloudKitAccountView: View { #if os(macOS) macBody #else - iosBody + NavigationView { + iosBody + } #endif } @@ -26,29 +28,28 @@ struct AddCloudKitAccountView: View { #if os(iOS) var iosBody: some View { List { - Section(header: formHeader, content: { + Section(header: formHeader, footer: formFooter, content: { Button(action: { _ = AccountManager.shared.createAccount(type: .cloudKit) presentationMode.wrappedValue.dismiss() }, label: { - Text("Add") - }) + HStack { + Spacer() + Text("Add Account") + Spacer() + } + }).disabled(AccountManager.shared.activeAccounts.filter({ $0.type == .cloudKit }).count > 0) }) }.navigationBarItems(leading: Button(action: { presentationMode.wrappedValue.dismiss() }, label: { - Text("Dismiss") - }) - - , trailing: - Button(action: { - _ = AccountManager.shared.createAccount(type: .cloudKit) - presentationMode.wrappedValue.dismiss() - }, label: { - Text("Add") + Text("Cancel") }) ) + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Text(AccountType.cloudKit.localizedAccountName())) + .listStyle(InsetGroupedListStyle()) } #endif @@ -102,20 +103,27 @@ struct AddCloudKitAccountView: View { var formHeader: some View { HStack { + Spacer() VStack(alignment: .center) { AccountType.cloudKit.image() .resizable() .frame(width: 50, height: 50) - Text("Sign in to your iCloud account.") - .font(.headline) - - Text("This account syncs across your Mac and iOS devices using your iCloud account.") - .foregroundColor(.secondary) - .font(.callout) - .lineLimit(2) - .padding(.top, 4) } - } + Spacer() + }.padding(.vertical) + } + + var formFooter: some View { + HStack { + Spacer() + VStack(spacing: 8) { + Text("This account syncs across your Mac and iOS devices using your iCloud account.").foregroundColor(.secondary) + } + .multilineTextAlignment(.center) + .font(.caption) + Spacer() + + }.padding(.vertical) } } diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddFeedWranglerAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddFeedWranglerAccountView.swift index 7ec1390ab..5fa2a4e11 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddFeedWranglerAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddFeedWranglerAccountView.swift @@ -22,7 +22,9 @@ struct AddFeedWranglerAccountView: View { #if os(macOS) macBody #else - iosBody + NavigationView { + iosBody + } #endif } @@ -30,10 +32,8 @@ struct AddFeedWranglerAccountView: View { #if os(iOS) var iosBody: some View { List { - Section(header: formHeader, footer: ProgressView() - .scaleEffect(CGSize(width: 0.5, height: 0.5)) - .hidden(!model.isAuthenticating) , content: { - TextField("me@email.com", text: $model.username) + Section(header: formHeader, content: { + TextField("Email", text: $model.username) if model.showPassword == false { ZStack { HStack { @@ -60,20 +60,39 @@ struct AddFeedWranglerAccountView: View { } } } + }) - }.navigationBarItems(leading: + + Section(footer: formFooter, content: { + Button(action: { + model.authenticateFeedWrangler() + }, label: { + HStack { + Spacer() + Text("Sign In") + Spacer() + } + }).disabled(model.username.isEmpty || model.password.isEmpty) + }) + + } + .navigationBarItems(leading: Button(action: { presentationMode.wrappedValue.dismiss() }, label: { - Text("Dismiss") - }) - , trailing: - Button(action: { - model.authenticateFeedWrangler() - }, label: { - Text("Add") - }).disabled(model.username.isEmpty || model.password.isEmpty) - ) + Text("Cancel") + })) + .listStyle(InsetGroupedListStyle()) + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Text("Feed Wrangler")) + .alert(isPresented: $model.showError, content: { + Alert(title: Text("Sign In Error"), message: Text(model.accountUpdateError.description), dismissButton: .cancel(Text("Dismiss"))) + }) + .onReceive(model.$canDismiss, perform: { value in + if value == true { + presentationMode.wrappedValue.dismiss() + } + }) } #endif @@ -158,20 +177,34 @@ struct AddFeedWranglerAccountView: View { var formHeader: some View { HStack { + Spacer() VStack(alignment: .center) { - AccountType.newsBlur.image() + AccountType.feedWrangler.image() .resizable() .frame(width: 50, height: 50) - Text("Sign in to your Feed Wrangler account.") - .font(.headline) - - Text("This account syncs across your subscriptions across devices.") - .foregroundColor(.secondary) - .font(.callout) - .lineLimit(2) - .padding(.top, 4) } - } + Spacer() + }.padding(.vertical) + } + + var formFooter: some View { + HStack { + Spacer() + VStack(spacing: 8) { + Text("Sign in to your Feed Wrangler account and sync your subscriptions across your devices. Your username and password and password will be encrypted and stored in Keychain.").foregroundColor(.secondary) + Text("Don't have a Feed Wrangler account?").foregroundColor(.secondary) + Button(action: { + model.presentSignUpOption(.feedWrangler) + }, label: { + Text("Sign Up Here").foregroundColor(.blue).multilineTextAlignment(.center) + }) + ProgressView().hidden(!model.isAuthenticating) + } + .multilineTextAlignment(.center) + .font(.caption2) + Spacer() + + }.padding(.vertical) } } diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddFeedbinAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddFeedbinAccountView.swift index d6dda8d5c..7b037c968 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddFeedbinAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddFeedbinAccountView.swift @@ -74,7 +74,7 @@ struct AddFeedbinAccountView: View { Button(action: { presentationMode.wrappedValue.dismiss() }, label: { - Text("Dismiss") + Text("Cancel") })) .listStyle(InsetGroupedListStyle()) .navigationBarTitleDisplayMode(.inline) diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddFeedlyAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddFeedlyAccountView.swift index fff4103da..9dbd38a39 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddFeedlyAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddFeedlyAccountView.swift @@ -32,7 +32,29 @@ struct AddFeedlyAccountView: View { #if os(iOS) var iosBody: some View { - Text("TBC") + List { + Section(header: formHeader, footer: formFooter, content: { + Button(action: { + model.authenticateFeedly() + }, label: { + HStack { + Spacer() + Text("Add Account") + Spacer() + } + }) + }) + }.navigationBarItems(leading: + Button(action: { + presentationMode.wrappedValue.dismiss() + }, label: { + Text("Cancel") + }) + ) + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Text(AccountType.feedly.localizedAccountName())) + .listStyle(InsetGroupedListStyle()) + } #endif @@ -90,6 +112,35 @@ struct AddFeedlyAccountView: View { } #endif + var formHeader: some View { + HStack { + Spacer() + VStack(alignment: .center) { + AccountType.feedly.image() + .resizable() + .frame(width: 50, height: 50) + } + Spacer() + }.padding(.vertical) + } + + var formFooter: some View { + HStack { + Spacer() + VStack(spacing: 8) { + Text("Sign in to your Feedly account and sync your subscriptions across your devices. Your username and password will be encrypted and stored in Keychain.\n\nDon't have an Feedly account?").foregroundColor(.secondary) + Button(action: { + model.presentSignUpOption(.feedly) + }, label: { + Text("Sign Up Here").foregroundColor(.blue).multilineTextAlignment(.center) + }) + } + .multilineTextAlignment(.center) + .font(.caption) + Spacer() + + }.padding(.vertical) + } } diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddLocalAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddLocalAccountView.swift index a0101a5d4..034ca07d3 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddLocalAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddLocalAccountView.swift @@ -19,7 +19,9 @@ struct AddLocalAccountView: View { #if os(macOS) macBody #else - iosBody + NavigationView { + iosBody + } #endif } @@ -29,22 +31,30 @@ struct AddLocalAccountView: View { Section(header: formHeader, content: { TextField("Account Name", text: $newAccountName) }) + + Section(footer: formFooter, content: { + Button(action: { + let newAccount = AccountManager.shared.createAccount(type: .onMyMac) + newAccount.name = newAccountName + presentationMode.wrappedValue.dismiss() + }, label: { + HStack { + Spacer() + Text("Add Account") + Spacer() + } + }) + }) }.navigationBarItems(leading: Button(action: { presentationMode.wrappedValue.dismiss() }, label: { - Text("Dismiss") - }) - - , trailing: - Button(action: { - let newAccount = AccountManager.shared.createAccount(type: .onMyMac) - newAccount.name = newAccountName - presentationMode.wrappedValue.dismiss() - }, label: { - Text("Add") + Text("Cancel") }) ) + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Text(AccountType.onMyMac.localizedAccountName())) + .listStyle(InsetGroupedListStyle()) } #endif @@ -98,17 +108,27 @@ struct AddLocalAccountView: View { var formHeader: some View { HStack { + Spacer() VStack(alignment: .center) { AccountType.onMyMac.image() .resizable() .frame(width: 50, height: 50) - Text("Create a local account on your Mac.") - .font(.headline) - Text("Local accounts store their data on your Mac. They do not sync across your devices.") - .font(.callout) - .foregroundColor(.secondary) } - } + Spacer() + }.padding(.vertical) + } + + var formFooter: some View { + HStack { + Spacer() + VStack(spacing: 8) { + Text("Local accounts do not sync your subscriptions across devices.").foregroundColor(.secondary) + } + .multilineTextAlignment(.center) + .font(.caption) + Spacer() + + }.padding(.vertical) } } diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddNewsBlurAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddNewsBlurAccountView.swift index f6b25df25..7f2123fb0 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddNewsBlurAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddNewsBlurAccountView.swift @@ -21,17 +21,17 @@ struct AddNewsBlurAccountView: View { #if os(macOS) macBody #else - iosBody + NavigationView { + iosBody + } #endif } #if os(iOS) var iosBody: some View { List { - Section(header: formHeader, footer: ProgressView() - .scaleEffect(CGSize(width: 0.5, height: 0.5)) - .hidden(!model.isAuthenticating) , content: { - TextField("me@email.com", text: $model.username) + Section(header: formHeader, content: { + TextField("Email", text: $model.username) if model.showPassword == false { ZStack { HStack { @@ -58,20 +58,39 @@ struct AddNewsBlurAccountView: View { } } } + }) - }.navigationBarItems(leading: + + Section(footer: formFooter, content: { + Button(action: { + model.authenticateNewsBlur() + }, label: { + HStack { + Spacer() + Text("Sign In") + Spacer() + } + }).disabled(model.username.isEmpty || model.password.isEmpty) + }) + + } + .navigationBarItems(leading: Button(action: { presentationMode.wrappedValue.dismiss() }, label: { - Text("Dismiss") - }) - , trailing: - Button(action: { - model.authenticateNewsBlur() - }, label: { - Text("Add") - }).disabled(model.username.isEmpty || model.password.isEmpty) - ) + Text("Cancel") + })) + .listStyle(InsetGroupedListStyle()) + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Text("NewsBlur")) + .alert(isPresented: $model.showError, content: { + Alert(title: Text("Sign In Error"), message: Text(model.accountUpdateError.description), dismissButton: .cancel(Text("Dismiss"))) + }) + .onReceive(model.$canDismiss, perform: { value in + if value == true { + presentationMode.wrappedValue.dismiss() + } + }) } #endif @@ -155,20 +174,34 @@ struct AddNewsBlurAccountView: View { var formHeader: some View { HStack { + Spacer() VStack(alignment: .center) { AccountType.newsBlur.image() .resizable() .frame(width: 50, height: 50) - Text("Sign in to your NewsBlur account.") - .font(.headline) - - Text("This account syncs across your subscriptions across devices.") - .foregroundColor(.secondary) - .font(.callout) - .lineLimit(2) - .padding(.top, 4) } - } + Spacer() + }.padding(.vertical) + } + + var formFooter: some View { + HStack { + Spacer() + VStack(spacing: 8) { + Text("Sign in to your NewsBlur account and sync your subscriptions across your devices. Your username and password and password will be encrypted and stored in Keychain.").foregroundColor(.secondary) + Text("Don't have a NewsBlur account?").foregroundColor(.secondary) + Button(action: { + model.presentSignUpOption(.newsBlur) + }, label: { + Text("Sign Up Here").foregroundColor(.blue).multilineTextAlignment(.center) + }) + ProgressView().hidden(!model.isAuthenticating) + } + .multilineTextAlignment(.center) + .font(.caption2) + Spacer() + + }.padding(.vertical) } } diff --git a/Multiplatform/Shared/Add/Add Account Sheets/AddReaderAPIAccountView.swift b/Multiplatform/Shared/Add/Add Account Sheets/AddReaderAPIAccountView.swift index f95de67bf..bb5c545ea 100644 --- a/Multiplatform/Shared/Add/Add Account Sheets/AddReaderAPIAccountView.swift +++ b/Multiplatform/Shared/Add/Add Account Sheets/AddReaderAPIAccountView.swift @@ -22,13 +22,79 @@ struct AddReaderAPIAccountView: View { #if os(macOS) macBody #else - iosBody + NavigationView { + iosBody + } #endif } #if os(iOS) var iosBody: some View { - Text("TBC") + List { + Section(header: formHeader, content: { + TextField("Email", text: $model.username) + if model.showPassword == false { + ZStack { + HStack { + SecureField("Password", text: $model.password) + Spacer() + Image(systemName: "eye.fill") + .foregroundColor(.accentColor) + .onTapGesture { + model.showPassword = true + } + } + } + } + else { + ZStack { + HStack { + TextField("Password", text: $model.password) + Spacer() + Image(systemName: "eye.slash.fill") + .foregroundColor(.accentColor) + .onTapGesture { + model.showPassword = false + } + } + } + } + if accountType == .freshRSS { + TextField("API URL", text: $model.apiUrl) + } + + }) + + Section(footer: formFooter, content: { + Button(action: { + model.authenticateReaderAccount(accountType) + }, label: { + HStack { + Spacer() + Text("Sign In") + Spacer() + } + }).disabled(createDisabled()) + }) + + } + .navigationBarItems(leading: + Button(action: { + presentationMode.wrappedValue.dismiss() + }, label: { + Text("Cancel") + })) + .listStyle(InsetGroupedListStyle()) + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Text(accountType.localizedAccountName())) + .alert(isPresented: $model.showError, content: { + Alert(title: Text("Sign In Error"), message: Text(model.accountUpdateError.description), dismissButton: .cancel(Text("Dismiss"))) + }) + .onReceive(model.$canDismiss, perform: { value in + if value == true { + presentationMode.wrappedValue.dismiss() + } + }) } #endif @@ -138,10 +204,44 @@ struct AddReaderAPIAccountView: View { } return 230 } + + var formHeader: some View { + HStack { + Spacer() + VStack(alignment: .center) { + accountType.image() + .resizable() + .frame(width: 50, height: 50) + } + Spacer() + }.padding(.vertical) + } + + var formFooter: some View { + HStack { + Spacer() + VStack(spacing: 8) { + Text("Sign in to your \(accountType.localizedAccountName()) account and sync your subscriptions across your devices. Your username and password and password will be encrypted and stored in Keychain.").foregroundColor(.secondary) + Text("Don't have a \(accountType.localizedAccountName()) instance?").foregroundColor(.secondary) + Button(action: { + model.presentSignUpOption(accountType) + }, label: { + Text("Sign Up Here").foregroundColor(.blue).multilineTextAlignment(.center) + }) + ProgressView().hidden(!model.isAuthenticating) + } + .multilineTextAlignment(.center) + .font(.caption2) + Spacer() + + }.padding(.vertical) + } + } struct AddReaderAPIAccountView_Previews: PreviewProvider { static var previews: some View { AddReaderAPIAccountView(accountType: .freshRSS) + //AddReaderAPIAccountView(accountType: .inoreader) } } diff --git a/Shared/AccountType+Helpers.swift b/Shared/AccountType+Helpers.swift index fe61b9043..67c262978 100644 --- a/Shared/AccountType+Helpers.swift +++ b/Shared/AccountType+Helpers.swift @@ -59,6 +59,9 @@ extension AccountType { func image() -> Image { switch self { case .onMyMac: + // If it's the multiplatform app, the asset catalog contains assets for + + return Image("accountLocal") case .bazQux: return Image("accountBazQux")