mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
More settings work
This commit is contained in:
@@ -9,6 +9,26 @@
|
||||
import UIKit
|
||||
import SafariServices
|
||||
import Account
|
||||
import SwiftUI
|
||||
|
||||
struct AccountInspectorWrapper: UIViewControllerRepresentable {
|
||||
|
||||
var account: Account
|
||||
|
||||
func makeUIViewController(context: Context) -> AccountInspectorViewController {
|
||||
let controller = UIStoryboard.inspector.instantiateViewController(withIdentifier: "AccountInspectorViewController") as! AccountInspectorViewController
|
||||
controller.account = account
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: AccountInspectorViewController, context: Context) {
|
||||
//
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = AccountInspectorViewController
|
||||
|
||||
}
|
||||
|
||||
|
||||
class AccountInspectorViewController: UITableViewController {
|
||||
|
||||
|
||||
@@ -7,6 +7,27 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
struct ExtensionPointInspectorWrapper: UIViewControllerRepresentable {
|
||||
|
||||
var extensionPoint: ExtensionPoint?
|
||||
|
||||
func makeUIViewController(context: Context) -> ExtensionPointInspectorViewController {
|
||||
let controller = UIStoryboard.inspector.instantiateViewController(withIdentifier: "ExtensionPointInspectorViewController") as! ExtensionPointInspectorViewController
|
||||
controller.extensionPoint = extensionPoint
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: ExtensionPointInspectorViewController, context: Context) {
|
||||
//
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = ExtensionPointInspectorViewController
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class ExtensionPointInspectorViewController: UITableViewController {
|
||||
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
//
|
||||
// AccountsManagementView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 13/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Account
|
||||
import Combine
|
||||
|
||||
struct AccountsManagementView: View {
|
||||
|
||||
@State private var showAddAccountSheet: Bool = false
|
||||
var cancellables = Set<AnyCancellable>()
|
||||
@State private var sortedAccounts = [Account]()
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
ForEach(sortedAccounts, id: \.self) { account in
|
||||
Section(header: Text("")) {
|
||||
accountRow(account)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(Text("Accounts"))
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.tint(Color(uiColor: AppAssets.primaryAccentColor))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
//
|
||||
} label: {
|
||||
Image(systemName: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .AccountStateDidChange)) { _ in
|
||||
sortedAccounts = AccountManager.shared.sortedAccounts
|
||||
}
|
||||
.onAppear {
|
||||
sortedAccounts = AccountManager.shared.sortedAccounts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var addAccountButton: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("Add Account")
|
||||
.padding(8)
|
||||
.overlay(NavigationLink { AddAccountViewControllerRepresentable() } label: { EmptyView() }.opacity(0.0))
|
||||
.background(Color(uiColor: AppAssets.primaryAccentColor))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 6))
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
func accountFooterText(_ account: Account) -> some View {
|
||||
if account.type == .cloudKit {
|
||||
return Text("iCloud Syncing Limitations & Solutions")
|
||||
} else {
|
||||
return Text("")
|
||||
}
|
||||
}
|
||||
|
||||
func accountRow(_ account: Account) -> some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Image(uiImage: account.smallIcon!.image)
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25)
|
||||
TextField(text: Binding(get: { account.nameForDisplay }, set: { account.name = $0 })) {
|
||||
Text(account.nameForDisplay)
|
||||
}.foregroundColor(.secondary)
|
||||
Spacer()
|
||||
Toggle(isOn: Binding<Bool>(
|
||||
get: { account.isActive },
|
||||
set: { account.isActive = $0 }
|
||||
)) {
|
||||
Text("")
|
||||
}
|
||||
}
|
||||
if account.type != .onMyMac {
|
||||
Divider()
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
HStack {
|
||||
Spacer()
|
||||
Button {
|
||||
// Remove account
|
||||
} label: {
|
||||
Text("Remove Account")
|
||||
.foregroundColor(.red)
|
||||
.bold()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var inactiveFooterText: some View {
|
||||
if AccountManager.shared.sortedAccounts.filter({ $0.isActive == false }).count == 0 {
|
||||
return Text("There are no inactive accounts.")
|
||||
} else {
|
||||
return Text("")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct AddAccountView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AccountsManagementView()
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,25 @@ import AuthenticationServices
|
||||
import Account
|
||||
import OAuthSwift
|
||||
import Secrets
|
||||
import SwiftUI
|
||||
|
||||
struct EnableExtensionPointViewWrapper: UIViewControllerRepresentable {
|
||||
|
||||
var extensionPoint: ExtensionPoint.Type?
|
||||
|
||||
func makeUIViewController(context: Context) -> EnableExtensionPointViewController {
|
||||
let controller = UIStoryboard.settings.instantiateViewController(withIdentifier: "EnableExtensionPointViewController") as! EnableExtensionPointViewController
|
||||
controller.extensionPointType = extensionPoint
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: EnableExtensionPointViewController, context: Context) {
|
||||
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = EnableExtensionPointViewController
|
||||
|
||||
}
|
||||
|
||||
class EnableExtensionPointViewController: UITableViewController {
|
||||
|
||||
|
||||
@@ -385,10 +385,10 @@
|
||||
<tableViewSection headerTitle="Appearance" id="TkH-4v-yhk">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" id="EvG-yE-gDF" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="981.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1002" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="EvG-yE-gDF" id="wBN-zJ-6pN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="343.5" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="355.5" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Color Palette" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2Fp-li-dGP">
|
||||
@@ -1185,7 +1185,7 @@
|
||||
<!--Extension-->
|
||||
<scene sceneID="sHq-4g-bAA">
|
||||
<objects>
|
||||
<tableViewController id="8Eu-UD-eCa" customClass="EnableExtensionPointViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableViewController storyboardIdentifier="EnableExtensionPointViewController" id="8Eu-UD-eCa" customClass="EnableExtensionPointViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="hqD-G5-jzC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// AccountsManagementView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 13/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Account
|
||||
import Combine
|
||||
|
||||
struct AddAccountWrapper: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context: Context) -> AddAccountViewController {
|
||||
let controller = UIStoryboard.settings.instantiateViewController(withIdentifier: "AddAccountViewController") as! AddAccountViewController
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: AddAccountViewController, context: Context) {
|
||||
//
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = AddAccountViewController
|
||||
|
||||
}
|
||||
|
||||
struct AccountsManagementView: View {
|
||||
|
||||
@State private var showAddAccountSheet: Bool = false
|
||||
var cancellables = Set<AnyCancellable>()
|
||||
@State private var sortedAccounts = [Account]()
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
ForEach(sortedAccounts, id: \.self) { account in
|
||||
accountRow(account)
|
||||
}
|
||||
}
|
||||
.navigationTitle(Text("Accounts"))
|
||||
.tint(Color(uiColor: AppAssets.primaryAccentColor))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
showAddAccountSheet = true
|
||||
} label: {
|
||||
Image(systemName: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .AccountStateDidChange)) { _ in
|
||||
refreshAccounts()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .UserDidAddAccount)) { _ in
|
||||
refreshAccounts()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .UserDidDeleteAccount)) { _ in
|
||||
refreshAccounts()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .DisplayNameDidChange)) { _ in
|
||||
refreshAccounts()
|
||||
}
|
||||
.task(priority: .userInitiated) {
|
||||
refreshAccounts()
|
||||
}
|
||||
.sheet(isPresented: $showAddAccountSheet) {
|
||||
NavigationView {
|
||||
AddAccountWrapper()
|
||||
.navigationTitle("Add Account")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshAccounts() {
|
||||
sortedAccounts = []
|
||||
sortedAccounts = AccountManager.shared.sortedAccounts
|
||||
}
|
||||
|
||||
func accountRow(_ account: Account) -> some View {
|
||||
NavigationLink {
|
||||
AccountInspectorWrapper(account: account)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
} label: {
|
||||
Image(uiImage: account.smallIcon!.image)
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25)
|
||||
Text(account.nameForDisplay)
|
||||
}
|
||||
}
|
||||
|
||||
var inactiveFooterText: some View {
|
||||
if AccountManager.shared.sortedAccounts.filter({ $0.isActive == false }).count == 0 {
|
||||
return Text("There are no inactive accounts.")
|
||||
} else {
|
||||
return Text("")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct AddAccountView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AccountsManagementView()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// ExtensionsManagementView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 30/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Account
|
||||
|
||||
struct ExtensionsManagementView: View {
|
||||
|
||||
@State private var availableExtensionPointTypes = ExtensionPointManager.shared.availableExtensionPointTypes.sorted(by: { $0.title < $1.title })
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section(header: Text("Add Extension"), footer: Text("Extensions allow you to subscribe to some pages as if they were RSS feeds.")) {
|
||||
ForEach(0..<availableExtensionPointTypes.count, id: \.self) { i in
|
||||
NavigationLink {
|
||||
EnableExtensionPointViewWrapper(extensionPoint: availableExtensionPointTypes[i])
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
} label: {
|
||||
Image(uiImage: availableExtensionPointTypes[i].image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25, height: 25)
|
||||
|
||||
Text("\(availableExtensionPointTypes[i].title)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Active Extensions")) {
|
||||
ForEach(0..<ExtensionPointManager.shared.activeExtensionPoints.count, id: \.self) { i in
|
||||
let point = Array(ExtensionPointManager.shared.activeExtensionPoints)[i]
|
||||
NavigationLink {
|
||||
ExtensionPointInspectorWrapper(extensionPoint: point.value)
|
||||
.navigationBarTitle(Text(point.value.title))
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
} label: {
|
||||
Image(uiImage: point.value.image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25, height: 25)
|
||||
Text(point.value.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(Text("Manage Extensions"))
|
||||
}
|
||||
}
|
||||
|
||||
struct ExtensionsManagementView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ExtensionsManagementView()
|
||||
}
|
||||
}
|
||||
@@ -11,38 +11,11 @@ import Account
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: - Headers
|
||||
|
||||
struct SettingsViewHeaders {
|
||||
|
||||
static func AddAccountHeader(_ showAddAccount: Binding<Bool>) -> some View {
|
||||
HStack {
|
||||
//Text("Accounts")
|
||||
Spacer()
|
||||
Button {
|
||||
showAddAccount.wrappedValue.toggle()
|
||||
} label: {
|
||||
Text("Add")
|
||||
.font(.caption)
|
||||
.bold()
|
||||
Image(systemName: "plus")
|
||||
.font(.caption)
|
||||
}
|
||||
.buttonBorderShape(.capsule)
|
||||
.buttonStyle(.bordered)
|
||||
.padding(.trailing, -15) // moves to trailing edge
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Rows
|
||||
|
||||
struct SettingsViewRows {
|
||||
|
||||
/// This row, when tapped, will open system settings.
|
||||
/// This row, when tapped, will open iOS System Settings.
|
||||
static var OpenSystemSettings: some View {
|
||||
Label {
|
||||
Text("Open System Settings")
|
||||
@@ -88,26 +61,10 @@ struct SettingsViewRows {
|
||||
}
|
||||
}
|
||||
|
||||
/// This `view` creates a `Label` for each active `Account`.
|
||||
/// Each `Label`, when tapped, will present the configurator for
|
||||
/// the `Account`.
|
||||
static var ActiveAccounts: some View {
|
||||
ForEach(AccountManager.shared.sortedActiveAccounts, id: \.self) { account in
|
||||
Label {
|
||||
Text(account.nameForDisplay)
|
||||
} icon: {
|
||||
Image(uiImage: AppAssets.image(for: account.type)!)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the the Add Extension screen
|
||||
/// This row, when tapped, will push the the Manage Extension screen
|
||||
/// in to view.
|
||||
static var AddExtension: some View {
|
||||
NavigationLink(destination: NotificationsViewControllerRepresentable()) {
|
||||
static var ManageExtensions: some View {
|
||||
NavigationLink(destination: ExtensionsManagementView()) {
|
||||
Label {
|
||||
Text("Manage Extensions")
|
||||
} icon: {
|
||||
@@ -199,6 +156,8 @@ struct SettingsViewRows {
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the the Theme Selector screen
|
||||
/// in to view.
|
||||
static var ThemeSelection: some View {
|
||||
NavigationLink(destination: ArticleThemesViewControllerRepresentable().edgesIgnoringSafeArea(.all)) {
|
||||
HStack {
|
||||
@@ -220,7 +179,6 @@ struct SettingsViewRows {
|
||||
}
|
||||
|
||||
// TODO: Add Reader Mode Defaults here. See #3684.
|
||||
|
||||
static func EnableFullScreenArticles(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle(isOn: preference) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
@@ -28,7 +28,7 @@ struct SettingsView: View {
|
||||
// Account/Extensions/OPML Management
|
||||
Section(header: Text("Accounts & Extensions"), footer: Text("Add, delete, enable, or disable accounts and extensions.")) {
|
||||
SettingsViewRows.AddAccount
|
||||
SettingsViewRows.AddExtension
|
||||
SettingsViewRows.ManageExtensions
|
||||
SettingsViewRows.ImportExportOPML(showImportView: $viewModel.showImportView, showExportView: $viewModel.showExportView, importAccount: $viewModel.importAccount, exportDocument: $viewModel.exportDocument)
|
||||
}
|
||||
|
||||
@@ -28,6 +28,5 @@ public final class SettingsViewModel: ObservableObject {
|
||||
@Published public var showImportSuccess: Bool = false
|
||||
@Published public var showExportSuccess: Bool = false
|
||||
@Published public var exportDocument: OPMLDocument?
|
||||
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public enum HelpSheet: CustomStringConvertible, CaseIterable {
|
||||
case .help:
|
||||
return NSLocalizedString("NetNewsWire Help", comment: "NetNewsWire Help")
|
||||
case .website:
|
||||
return NSLocalizedString("Website", comment: "Website")
|
||||
return NSLocalizedString("NetNewsWire Website", comment: "NetNewsWire Website")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ struct NewArticleNotificationsView: View {
|
||||
activeAccounts = AccountManager.shared.sortedActiveAccounts
|
||||
}
|
||||
}
|
||||
.tint(Color(uiColor: AppAssets.primaryAccentColor))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user