mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Revised settings views
Notes: - A lot of representable shims over UIKit view controllers. These misbehave a little. They should be re-written in SwiftUI. - Settings no longer uses VibrantTableViewCell - Changes to AppDefaults trigger objectWillSend
This commit is contained in:
@@ -860,6 +860,10 @@
|
||||
DFCE4F9228EF26F100405869 /* About.plist in Resources */ = {isa = PBXBuildFile; fileRef = DFCE4F9028EF26F000405869 /* About.plist */; };
|
||||
DFCE4F9428EF278300405869 /* Thanks.md in Resources */ = {isa = PBXBuildFile; fileRef = DFCE4F9328EF278300405869 /* Thanks.md */; };
|
||||
DFCE4F9528EF278300405869 /* Thanks.md in Resources */ = {isa = PBXBuildFile; fileRef = DFCE4F9328EF278300405869 /* Thanks.md */; };
|
||||
DFD406F5291F79C900C02962 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406F4291F79C900C02962 /* SettingsView.swift */; };
|
||||
DFD406F7291FB1A600C02962 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406F6291FB1A600C02962 /* SafariView.swift */; };
|
||||
DFD406FA291FB5E400C02962 /* SettingsRows.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406F9291FB5E400C02962 /* SettingsRows.swift */; };
|
||||
DFD406FC291FB63B00C02962 /* SettingsHelpSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406FB291FB63B00C02962 /* SettingsHelpSheets.swift */; };
|
||||
DFFB8FC2279B75E300AC21D7 /* Account in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F4A24D343A500E90810 /* Account */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
DFFC199827A0D0D7004B7AEF /* NotificationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFC199727A0D0D7004B7AEF /* NotificationsViewController.swift */; };
|
||||
DFFC199A27A0D32A004B7AEF /* NotificationsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFC199927A0D32A004B7AEF /* NotificationsTableViewCell.swift */; };
|
||||
@@ -1601,6 +1605,10 @@
|
||||
DFC14F1628EB17A800F6EE86 /* CreditsNetNewsWireView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditsNetNewsWireView.swift; sourceTree = "<group>"; };
|
||||
DFCE4F9028EF26F000405869 /* About.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = About.plist; sourceTree = "<group>"; };
|
||||
DFCE4F9328EF278300405869 /* Thanks.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Thanks.md; sourceTree = "<group>"; };
|
||||
DFD406F4291F79C900C02962 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
DFD406F6291FB1A600C02962 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
|
||||
DFD406F9291FB5E400C02962 /* SettingsRows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRows.swift; sourceTree = "<group>"; };
|
||||
DFD406FB291FB63B00C02962 /* SettingsHelpSheets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsHelpSheets.swift; sourceTree = "<group>"; };
|
||||
DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = NewsFax.nnwtheme; sourceTree = "<group>"; };
|
||||
DFFC199727A0D0D7004B7AEF /* NotificationsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsViewController.swift; sourceTree = "<group>"; };
|
||||
DFFC199927A0D32A004B7AEF /* NotificationsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsTableViewCell.swift; sourceTree = "<group>"; };
|
||||
@@ -2000,6 +2008,7 @@
|
||||
516244E2241E19F000B61C47 /* ColorPaletteTableViewController.swift */,
|
||||
519ED47924482AEB007F8E94 /* EnableExtensionPointViewController.swift */,
|
||||
51A16990235E10D600EB091F /* Settings.storyboard */,
|
||||
DFD406F8291FB5D500C02962 /* Settings View */,
|
||||
516A09382360A2AE00EAE89B /* SettingsComboTableViewCell.swift */,
|
||||
516A091D23609A3600EAE89B /* SettingsComboTableViewCell.xib */,
|
||||
516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */,
|
||||
@@ -2059,6 +2068,7 @@
|
||||
5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */,
|
||||
5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */,
|
||||
51A9A6092382FD240033AADF /* PoppableGestureRecognizerDelegate.swift */,
|
||||
DFD406F6291FB1A600C02962 /* SafariView.swift */,
|
||||
51C45250226506F400C03939 /* String-Extensions.swift */,
|
||||
5108F6D723763094001ABC45 /* TickMarkSlider.swift */,
|
||||
C5A6ED6C23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift */,
|
||||
@@ -2882,6 +2892,16 @@
|
||||
path = About;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DFD406F8291FB5D500C02962 /* Settings View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DFD406F4291F79C900C02962 /* SettingsView.swift */,
|
||||
DFD406F9291FB5E400C02962 /* SettingsRows.swift */,
|
||||
DFD406FB291FB63B00C02962 /* SettingsHelpSheets.swift */,
|
||||
);
|
||||
path = "Settings View";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -4062,6 +4082,7 @@
|
||||
51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */,
|
||||
51C452A522650A2D00C03939 /* SmallIconProvider.swift in Sources */,
|
||||
51AB8AB323B7F4C6008F147D /* WebViewController.swift in Sources */,
|
||||
DFD406F7291FB1A600C02962 /* SafariView.swift in Sources */,
|
||||
516A09392360A2AE00EAE89B /* SettingsComboTableViewCell.swift in Sources */,
|
||||
176813D22564BA5900D98635 /* WidgetDataEncoder.swift in Sources */,
|
||||
51D5948722668EFA00DFC836 /* MarkStatusCommand.swift in Sources */,
|
||||
@@ -4081,6 +4102,7 @@
|
||||
51C4526B226508F600C03939 /* MasterFeedViewController.swift in Sources */,
|
||||
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */,
|
||||
84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */,
|
||||
DFD406FA291FB5E400C02962 /* SettingsRows.swift in Sources */,
|
||||
5193CD5A245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */,
|
||||
51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */,
|
||||
51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */,
|
||||
@@ -4151,6 +4173,7 @@
|
||||
51C452A922650DC600C03939 /* ArticleRenderer.swift in Sources */,
|
||||
51C45297226509E300C03939 /* DefaultFeedsImporter.swift in Sources */,
|
||||
512E094D2268B8AB00BDCFDD /* DeleteCommand.swift in Sources */,
|
||||
DFD406FC291FB63B00C02962 /* SettingsHelpSheets.swift in Sources */,
|
||||
5110C37D2373A8D100A9C04F /* InspectorIconHeaderView.swift in Sources */,
|
||||
51F85BFB2275D85000C787DC /* Array-Extensions.swift in Sources */,
|
||||
515A5180243E90260089E588 /* TwitterFeedProvider-Extensions.swift in Sources */,
|
||||
@@ -4176,6 +4199,7 @@
|
||||
51DC370B2405BC9A0095D371 /* PreloadedWebView.swift in Sources */,
|
||||
D3555BF524664566005E48C3 /* ArticleSearchBar.swift in Sources */,
|
||||
8454C3F3263F2D8700E3F9C7 /* IconImageCache.swift in Sources */,
|
||||
DFD406F5291F79C900C02962 /* SettingsView.swift in Sources */,
|
||||
B24E9ADE245AB88400DA5718 /* NSAttributedString+NetNewsWire.swift in Sources */,
|
||||
C5A6ED5223C9AF4300AB6BE2 /* TitleActivityItemSource.swift in Sources */,
|
||||
17071EF126F8137400F5E71D /* ArticleTheme+Notifications.swift in Sources */,
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
import Combine
|
||||
|
||||
public extension Notification.Name {
|
||||
static let ArticleThemeNamesDidChangeNotification = Notification.Name("ArticleThemeNamesDidChangeNotification")
|
||||
static let CurrentArticleThemeDidChangeNotification = Notification.Name("CurrentArticleThemeDidChangeNotification")
|
||||
}
|
||||
|
||||
final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
final class ArticleThemesManager: NSObject, NSFilePresenter, Logging, ObservableObject {
|
||||
|
||||
static var shared: ArticleThemesManager!
|
||||
public let folderPath: String
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
enum UserInterfaceColorPalette: Int, CustomStringConvertible, CaseIterable {
|
||||
case automatic = 0
|
||||
@@ -26,7 +28,7 @@ enum UserInterfaceColorPalette: Int, CustomStringConvertible, CaseIterable {
|
||||
|
||||
}
|
||||
|
||||
final class AppDefaults {
|
||||
final class AppDefaults: ObservableObject {
|
||||
|
||||
static let defaultThemeName = "Default"
|
||||
|
||||
@@ -85,6 +87,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
setInt(for: Key.userInterfaceColorPalette, newValue.rawValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +97,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setString(for: Key.addWebFeedAccountID, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +107,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setString(for: Key.addWebFeedFolderName, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +117,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setString(for: Key.addFolderAccountID, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +127,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Key.activeExtensionPointIDs)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +137,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Key.hasUsedFullScreenPreviously)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +147,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.setValue(newValue, forKey: Key.useSystemBrowser)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +157,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setDate(for: Key.lastImageCacheFlushDate, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +167,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.timelineGroupByFeed, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +177,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.refreshClearsReadArticles, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,15 +187,33 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setSortDirection(for: Key.timelineSortDirection, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// This is a `Bool` wrapper for `timelineSortDirection`'s
|
||||
/// `ComparisonResult`
|
||||
var timelineSortDirectionBool: Bool {
|
||||
get {
|
||||
if AppDefaults.shared.timelineSortDirection == .orderedAscending {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
set {
|
||||
if newValue == true { timelineSortDirection = .orderedAscending } else {
|
||||
timelineSortDirection = .orderedDescending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var articleFullscreenEnabled: Bool {
|
||||
get {
|
||||
return AppDefaults.bool(for: Key.articleFullscreenEnabled)
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.articleFullscreenEnabled, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +223,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.confirmMarkAllAsRead, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +233,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setDate(for: Key.lastRefresh, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +243,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setInt(for: Key.timelineNumberOfLines, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +254,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.store.set(newValue.rawValue, forKey: Key.timelineIconDimension)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +264,7 @@ final class AppDefaults {
|
||||
}
|
||||
set {
|
||||
AppDefaults.setString(for: Key.currentThemeName, newValue)
|
||||
AppDefaults.shared.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import Articles
|
||||
import RSCore
|
||||
import RSTree
|
||||
import SafariServices
|
||||
import SwiftUI
|
||||
|
||||
protocol MainControllerIdentifiable {
|
||||
var mainControllerIdentifer: MainControllerIdentifier { get }
|
||||
@@ -1129,12 +1130,14 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
}
|
||||
|
||||
func showSettings(scrollToArticlesSection: Bool = false) {
|
||||
let settingsNavController = UIStoryboard.settings.instantiateInitialViewController() as! UINavigationController
|
||||
let settingsViewController = settingsNavController.topViewController as! SettingsViewController
|
||||
settingsViewController.scrollToArticlesSection = scrollToArticlesSection
|
||||
settingsNavController.modalPresentationStyle = .formSheet
|
||||
settingsViewController.presentingParentController = rootSplitViewController
|
||||
rootSplitViewController.present(settingsNavController, animated: true)
|
||||
// let settingsNavController = UIStoryboard.settings.instantiateInitialViewController() as! UINavigationController
|
||||
// let settingsViewController = settingsNavController.topViewController as! SettingsViewController
|
||||
// settingsViewController.scrollToArticlesSection = scrollToArticlesSection
|
||||
// settingsNavController.modalPresentationStyle = .formSheet
|
||||
// settingsViewController.presentingParentController = rootSplitViewController
|
||||
// rootSplitViewController.present(settingsNavController, animated: true)
|
||||
let hostedSettings = UIHostingController(rootView: SettingsView())
|
||||
rootSplitViewController.present(hostedSettings, animated: true)
|
||||
}
|
||||
|
||||
func showAccountInspector(for account: Account) {
|
||||
|
||||
@@ -8,8 +8,37 @@
|
||||
|
||||
import Account
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import RSCore
|
||||
|
||||
struct AddAccountViewControllerRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context: Context) -> AddAccountViewController {
|
||||
let storyboard = UIStoryboard(name: "Settings", bundle: .main)
|
||||
let controller = storyboard.instantiateViewController(withIdentifier: "AddAccountViewController") as! AddAccountViewController
|
||||
|
||||
context.coordinator.parentObserver = controller.observe(\.parent, changeHandler: { vc, _ in
|
||||
vc.parent?.title = vc.title
|
||||
vc.parent?.navigationItem.rightBarButtonItems = vc.navigationItem.rightBarButtonItems
|
||||
})
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: AddAccountViewController, context: Context) {
|
||||
//
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = AddAccountViewController
|
||||
|
||||
class Coordinator {
|
||||
var parentObserver: NSKeyValueObservation?
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Self.Coordinator { Coordinator() }
|
||||
|
||||
}
|
||||
|
||||
|
||||
protocol AddAccountDismissDelegate: UIViewController {
|
||||
func dismiss()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,36 @@ import Foundation
|
||||
import UniformTypeIdentifiers
|
||||
import RSCore
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
struct ArticleThemesViewControllerRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context: Context) -> ArticleThemesTableViewController {
|
||||
let storyboard = UIStoryboard(name: "Settings", bundle: .main)
|
||||
let controller = storyboard.instantiateViewController(withIdentifier: "ArticleThemesTableViewController") as! ArticleThemesTableViewController
|
||||
|
||||
context.coordinator.parentObserver = controller.observe(\.parent, changeHandler: { vc, _ in
|
||||
vc.parent?.title = vc.title
|
||||
vc.parent?.navigationItem.rightBarButtonItems = vc.navigationItem.rightBarButtonItems
|
||||
})
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: ArticleThemesTableViewController, context: Context) {
|
||||
//
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = ArticleThemesTableViewController
|
||||
|
||||
class Coordinator {
|
||||
var parentObserver: NSKeyValueObservation?
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Self.Coordinator { Coordinator() }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ArticleThemesTableViewController: UITableViewController, Logging {
|
||||
|
||||
|
||||
@@ -7,9 +7,38 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import Account
|
||||
import UserNotifications
|
||||
|
||||
struct NotificationsViewControllerRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context: Context) -> NotificationsViewController {
|
||||
let storyboard = UIStoryboard(name: "Settings", bundle: .main)
|
||||
let controller = storyboard.instantiateViewController(withIdentifier: "NotificationsViewController") as! NotificationsViewController
|
||||
|
||||
context.coordinator.parentObserver = controller.observe(\.parent, changeHandler: { vc, _ in
|
||||
vc.parent?.title = vc.title
|
||||
vc.parent?.navigationItem.rightBarButtonItems = vc.navigationItem.rightBarButtonItems
|
||||
})
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: NotificationsViewController, context: Context) {
|
||||
//
|
||||
}
|
||||
|
||||
typealias UIViewControllerType = NotificationsViewController
|
||||
|
||||
class Coordinator {
|
||||
var parentObserver: NSKeyValueObservation?
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Self.Coordinator { Coordinator() }
|
||||
|
||||
}
|
||||
|
||||
|
||||
class NotificationsViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var notificationsTableView: UITableView!
|
||||
@@ -89,9 +118,9 @@ class NotificationsViewController: UIViewController {
|
||||
private func reloadVisibleCells(_ notification: Notification) {
|
||||
guard let faviconURLString = notification.userInfo?["faviconURL"] as? String,
|
||||
let faviconHost = URL(string: faviconURLString)?.host else {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for cell in notificationsTableView.visibleCells {
|
||||
if let notificationCell = cell as? NotificationsTableViewCell {
|
||||
if let feedURLHost = URL(string: notificationCell.feed!.url)?.host {
|
||||
@@ -117,21 +146,21 @@ class NotificationsViewController: UIViewController {
|
||||
|
||||
|
||||
let filterMenu = UIMenu(title: "",
|
||||
image: nil,
|
||||
identifier: nil,
|
||||
options: [.displayInline],
|
||||
children: [
|
||||
UIAction(
|
||||
title: NSLocalizedString("Show Feeds with Notifications Enabled", comment: "Feeds with Notifications"),
|
||||
image: nil,
|
||||
identifier: nil,
|
||||
discoverabilityTitle: nil,
|
||||
attributes: [],
|
||||
state: newArticleNotificationFilter ? .on : .off,
|
||||
handler: { [weak self] _ in
|
||||
self?.newArticleNotificationFilter.toggle()
|
||||
self?.notificationsTableView.reloadData()
|
||||
})])
|
||||
options: [.displayInline],
|
||||
children: [
|
||||
UIAction(
|
||||
title: NSLocalizedString("Show Feeds with Notifications Enabled", comment: "Feeds with Notifications"),
|
||||
image: nil,
|
||||
identifier: nil,
|
||||
discoverabilityTitle: nil,
|
||||
attributes: [],
|
||||
state: newArticleNotificationFilter ? .on : .off,
|
||||
handler: { [weak self] _ in
|
||||
self?.newArticleNotificationFilter.toggle()
|
||||
self?.notificationsTableView.reloadData()
|
||||
})])
|
||||
|
||||
|
||||
var menus = [UIMenuElement]()
|
||||
|
||||
77
iOS/Settings/Settings View/SettingsHelpSheets.swift
Normal file
77
iOS/Settings/Settings View/SettingsHelpSheets.swift
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// SettingsHelpSheets.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 12/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum HelpSheet: CustomStringConvertible, CaseIterable {
|
||||
|
||||
case help, website, releaseNotes, howToSupport, gitHubRepository, bugTracker, technotes, slack
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .help:
|
||||
return NSLocalizedString("NetNewsWire Help", comment: "NetNewsWire Help")
|
||||
case .website:
|
||||
return NSLocalizedString("Website", comment: "Website")
|
||||
case .releaseNotes:
|
||||
return NSLocalizedString("Release Notes", comment: "Release Notes")
|
||||
case .howToSupport:
|
||||
return NSLocalizedString("How to Support NetNewsWire", comment: "How to Support")
|
||||
case .gitHubRepository:
|
||||
return NSLocalizedString("GitHub Respository", comment: "Github")
|
||||
case .bugTracker:
|
||||
return NSLocalizedString("Bug Tracker", comment: "Bug Tracker")
|
||||
case .technotes:
|
||||
return NSLocalizedString("Technotes", comment: "Technotes")
|
||||
case .slack:
|
||||
return NSLocalizedString("Slack", comment: "Slack")
|
||||
}
|
||||
}
|
||||
|
||||
var url: URL {
|
||||
switch self {
|
||||
case .help:
|
||||
return URL(string: "https://netnewswire.com/help/ios/6.1/en/")!
|
||||
case .website:
|
||||
return URL(string: "https://netnewswire.com/")!
|
||||
case .releaseNotes:
|
||||
return URL(string: URL.releaseNotes.absoluteString)!
|
||||
case .howToSupport:
|
||||
return URL(string: "https://github.com/brentsimmons/NetNewsWire/blob/main/Technotes/HowToSupportNetNewsWire.markdown")!
|
||||
case .gitHubRepository:
|
||||
return URL(string: "https://github.com/brentsimmons/NetNewsWire")!
|
||||
case .bugTracker:
|
||||
return URL(string: "https://github.com/brentsimmons/NetNewsWire/issues")!
|
||||
case .technotes:
|
||||
return URL(string: "https://github.com/brentsimmons/NetNewsWire/tree/main/Technotes")!
|
||||
case .slack:
|
||||
return URL(string: "https://netnewswire.com/slack")!
|
||||
}
|
||||
}
|
||||
|
||||
var systemImage: String {
|
||||
switch self {
|
||||
case .help:
|
||||
return "questionmark.app"
|
||||
case .website:
|
||||
return "globe"
|
||||
case .releaseNotes:
|
||||
return "quote.opening"
|
||||
case .howToSupport:
|
||||
return "person.3.fill"
|
||||
case .gitHubRepository:
|
||||
return "archivebox"
|
||||
case .bugTracker:
|
||||
return "ladybug"
|
||||
case .technotes:
|
||||
return "chevron.left.slash.chevron.right"
|
||||
case .slack:
|
||||
return "quote.bubble.fill"
|
||||
}
|
||||
}
|
||||
}
|
||||
256
iOS/Settings/Settings View/SettingsRows.swift
Normal file
256
iOS/Settings/Settings View/SettingsRows.swift
Normal file
@@ -0,0 +1,256 @@
|
||||
//
|
||||
// SettingsRows.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 12/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Account
|
||||
|
||||
// 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.
|
||||
static var OpenSystemSettings: some View {
|
||||
Label {
|
||||
Text("Open System Settings")
|
||||
} icon: {
|
||||
Image(systemName: "gear.circle.fill")
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(.gray)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
.onTapGesture {
|
||||
UIApplication.shared.open(URL(string: "\(UIApplication.openSettingsURLString)")!)
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the New Article Notifications
|
||||
/// screen in to view.
|
||||
static var ConfigureNewArticleNotifications: some View {
|
||||
NavigationLink(destination: NotificationsViewControllerRepresentable().edgesIgnoringSafeArea(.all)) {
|
||||
Label {
|
||||
Text("New Article Notifications")
|
||||
} icon: {
|
||||
Image(systemName: "bell.square.fill")
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(.red)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the the Add Account screen
|
||||
/// in to view.
|
||||
static var AddAccount: some View {
|
||||
NavigationLink(destination: AddAccountViewControllerRepresentable().edgesIgnoringSafeArea(.all)) {
|
||||
Label {
|
||||
Text("Add Account")
|
||||
} icon: {
|
||||
Image(systemName: "plus.app.fill")
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(Color(uiColor: AppAssets.primaryAccentColor))
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// in to view.
|
||||
static var AddExtension: some View {
|
||||
NavigationLink(destination: NotificationsViewControllerRepresentable()) {
|
||||
Label {
|
||||
Text("Add Extension")
|
||||
} icon: {
|
||||
Image(systemName: "puzzlepiece.extension")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the the Import subscriptions screen
|
||||
/// in to view.
|
||||
static var ImportSubscription: some View {
|
||||
Label {
|
||||
Text("Import Subscriptions")
|
||||
} icon: {
|
||||
Image(systemName: "square.and.arrow.down")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the the Export subscriptions screen
|
||||
/// in to view.
|
||||
static var ExportSubscription: some View {
|
||||
Label {
|
||||
Text("Import Subscriptions")
|
||||
} icon: {
|
||||
Image(systemName: "square.and.arrow.up")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `Toggle` which triggers changes to the user's sort order preference.
|
||||
/// - Parameter preference: `Binding<Bool>`
|
||||
/// - Returns: `Toggle`
|
||||
static func SortOldestToNewest(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle("Sort Oldest to Newest", isOn: preference)
|
||||
}
|
||||
|
||||
/// Returns a `Toggle` which triggers changes to the user's grouping preference.
|
||||
/// - Parameter preference: `Binding<Bool>`
|
||||
/// - Returns: `Toggle`
|
||||
static func GroupByFeed(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle("Group by Feed", isOn: preference)
|
||||
}
|
||||
|
||||
/// Returns a `Toggle` which triggers changes to the user's refresh to clear preferences.
|
||||
/// - Parameter preference: `Binding<Bool>`
|
||||
/// - Returns: `Toggle`
|
||||
static func RefreshToClearReadArticles(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle("Refresh To Clear Read Articles", isOn: preference)
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the the Timeline Layout screen
|
||||
/// in to view.
|
||||
static var TimelineLayout: some View {
|
||||
NavigationLink(destination: NotificationsViewControllerRepresentable()) {
|
||||
Label {
|
||||
Text("Timeline Layout")
|
||||
} icon: {
|
||||
Image(systemName: "slider.vertical.3")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static var ThemeSelection: some View {
|
||||
NavigationLink(destination: ArticleThemesViewControllerRepresentable().edgesIgnoringSafeArea(.all)) {
|
||||
Label {
|
||||
Text("Article Themes")
|
||||
} icon: {
|
||||
Image(systemName: "textformat")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func ConfirmMarkAllAsRead(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle("Confirm Mark All as Read", isOn: preference)
|
||||
}
|
||||
|
||||
static func OpenLinksInNetNewsWire(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle("Open Links in NetNewsWire", isOn: preference)
|
||||
}
|
||||
|
||||
static func EnableFullScreenArticles(_ preference: Binding<Bool>) -> some View {
|
||||
Toggle(isOn: preference) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Enable Full Screen Articles")
|
||||
Text("Tap the article top bar to enter Full Screen. Tap the top or bottom to exit.")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This row, when tapped, will push the New Article Notifications
|
||||
/// screen in to view.
|
||||
static var ConfigureAppearance: some View {
|
||||
NavigationLink(destination: NotificationsViewControllerRepresentable().edgesIgnoringSafeArea(.all)) {
|
||||
Label {
|
||||
Text("Configure Appearance")
|
||||
} icon: {
|
||||
Image(systemName: "rectangle.trailinghalf.filled")
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(.black)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the help sheet the user wishes to see.
|
||||
/// - Parameters:
|
||||
/// - sheet: The sheet provided to create the view.
|
||||
/// - selectedSheet: A `Binding` to the currently selected sheet. This is set, followed by `show`.
|
||||
/// - show: A `Binding` to `Bool` which triggers the sheet to display.
|
||||
/// - Returns: `View`
|
||||
static func ShowHelpSheet(sheet: HelpSheet, selectedSheet: Binding<HelpSheet>, _ show: Binding<Bool>) -> some View {
|
||||
Label {
|
||||
Text(sheet.description)
|
||||
} icon: {
|
||||
Image(systemName: sheet.systemImage)
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(Color(uiColor: .tertiaryLabel))
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 25.0, height: 25.0)
|
||||
}
|
||||
.onTapGesture {
|
||||
selectedSheet.wrappedValue = sheet
|
||||
show.wrappedValue.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
76
iOS/Settings/Settings View/SettingsView.swift
Normal file
76
iOS/Settings/Settings View/SettingsView.swift
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// SettingsView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 12/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Account
|
||||
|
||||
struct SettingsView: View {
|
||||
|
||||
@StateObject private var appDefaults = AppDefaults.shared
|
||||
@State private var showAddAccountView: Bool = false
|
||||
@State private var helpSheet: HelpSheet = .help
|
||||
@State private var showHelpSheet: Bool = false
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
Section("Notifications, Badge, Data, and More") {
|
||||
SettingsViewRows.OpenSystemSettings
|
||||
SettingsViewRows.ConfigureNewArticleNotifications
|
||||
}
|
||||
|
||||
Section(header: SettingsViewHeaders.AddAccountHeader($showAddAccountView)) {
|
||||
SettingsViewRows.ActiveAccounts
|
||||
}
|
||||
|
||||
Section("Extensions") {
|
||||
SettingsViewRows.AddExtension
|
||||
}
|
||||
|
||||
Section("Subscriptions") {
|
||||
SettingsViewRows.ImportSubscription
|
||||
SettingsViewRows.ExportSubscription
|
||||
}
|
||||
|
||||
Section("Timeline") {
|
||||
SettingsViewRows.SortOldestToNewest($appDefaults.timelineSortDirectionBool)
|
||||
SettingsViewRows.GroupByFeed($appDefaults.timelineGroupByFeed)
|
||||
SettingsViewRows.RefreshToClearReadArticles($appDefaults.refreshClearsReadArticles)
|
||||
SettingsViewRows.TimelineLayout
|
||||
}
|
||||
|
||||
Section("Articles") {
|
||||
SettingsViewRows.ThemeSelection
|
||||
SettingsViewRows.ConfirmMarkAllAsRead($appDefaults.confirmMarkAllAsRead)
|
||||
SettingsViewRows.OpenLinksInNetNewsWire($appDefaults.useSystemBrowser)
|
||||
SettingsViewRows.EnableFullScreenArticles($appDefaults.articleFullscreenEnabled)
|
||||
}
|
||||
|
||||
Section("Appearance") {
|
||||
SettingsViewRows.ConfigureAppearance
|
||||
}
|
||||
|
||||
Section("Help") {
|
||||
ForEach(0..<HelpSheet.allCases.count, id: \.self) { i in
|
||||
SettingsViewRows.ShowHelpSheet(sheet: HelpSheet.allCases[i], selectedSheet: $helpSheet, $showHelpSheet)
|
||||
}
|
||||
}
|
||||
}
|
||||
.tint(Color(uiColor: AppAssets.primaryAccentColor))
|
||||
.listStyle(.insetGrouped)
|
||||
.navigationTitle(Text("Settings"))
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.sheet(isPresented: $showAddAccountView) {
|
||||
AddAccountViewControllerRepresentable().edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
.sheet(isPresented: $showHelpSheet) {
|
||||
SafariView(url: helpSheet.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,20 +282,20 @@
|
||||
<tableViewSection headerTitle="Articles" id="TRr-Ew-IvU">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" id="WFP-zj-Pve" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="814" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="814" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="WFP-zj-Pve" id="DCX-wc-LSo">
|
||||
<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="343.5" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Theme" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bbw-L9-a3X">
|
||||
<rect key="frame" x="20" y="11.5" width="53" height="20.5"/>
|
||||
<rect key="frame" x="20" y="12" width="53" height="20.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Default" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DUf-DZ-3Nm">
|
||||
<rect key="frame" x="280.5" y="11.5" width="55" height="20.5"/>
|
||||
<rect key="frame" x="280.5" y="12" width="55" height="20.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -314,19 +314,19 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="SXs-NQ-y3U" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="857.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="858" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="SXs-NQ-y3U" id="BpI-Hz-KH2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="Confirm Mark All as Read" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5tY-5k-v2g">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" ambiguous="YES" text="Confirm Mark All as Read" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5tY-5k-v2g">
|
||||
<rect key="frame" x="20" y="11" width="191.5" height="21.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UOo-9z-IuL">
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UOo-9z-IuL">
|
||||
<rect key="frame" x="307" y="6.5" width="51" height="31"/>
|
||||
<color key="onTintColor" name="primaryAccentColor"/>
|
||||
<connections>
|
||||
@@ -347,19 +347,19 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="EYf-v1-lNi" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="901" width="374" height="48"/>
|
||||
<rect key="frame" x="20" y="902" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="EYf-v1-lNi" id="7nz-0Y-HaW">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="48"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="Open Links in NetNewsWire" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wm4-Y1-7nX">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" ambiguous="YES" text="Open Links in NetNewsWire" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wm4-Y1-7nX">
|
||||
<rect key="frame" x="20" y="14" width="279" height="21"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dhR-L2-PX3" userLabel="Open Links in NetNewsWire">
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dhR-L2-PX3" userLabel="Open Links in NetNewsWire">
|
||||
<rect key="frame" x="307" y="8.5" width="51" height="31"/>
|
||||
<color key="onTintColor" name="primaryAccentColor"/>
|
||||
<connections>
|
||||
@@ -385,7 +385,7 @@
|
||||
<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="1005" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="981.5" 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"/>
|
||||
@@ -421,14 +421,14 @@
|
||||
<tableViewSection headerTitle="Help" id="CS8-fJ-ghn">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="uGk-2d-oFc" style="IBUITableViewCellStyleDefault" id="Tle-IV-D40" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1063" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1101.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Tle-IV-D40" id="IJD-ZB-8Wm">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" text="NetNewsWire Help" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="uGk-2d-oFc">
|
||||
<rect key="frame" x="20" y="0.0" width="334" height="43.5"/>
|
||||
<rect key="frame" x="8" y="0.0" width="358" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
@@ -438,7 +438,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="6G3-yV-Eyh" style="IBUITableViewCellStyleDefault" id="Tbf-fE-nfx" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1148" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1145" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Tbf-fE-nfx" id="beV-vI-g3r">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -455,7 +455,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="NeD-y8-KrM" style="IBUITableViewCellStyleDefault" id="TIX-yK-rC6" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1191.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1188.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="TIX-yK-rC6" id="qr8-EN-Ofg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -472,7 +472,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="lfL-bQ-sOp" style="IBUITableViewCellStyleDefault" id="mFn-fE-zqa" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1235" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1232" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="mFn-fE-zqa" id="jTe-mf-MRj">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -489,7 +489,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="DDJ-8P-3YY" style="IBUITableViewCellStyleDefault" id="iGs-ze-4gQ" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1278.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1275.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="iGs-ze-4gQ" id="EqZ-rF-N0l">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -506,7 +506,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="DsV-Qv-X4K" style="IBUITableViewCellStyleDefault" id="taJ-sg-wnU" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1322" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1319" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="taJ-sg-wnU" id="axB-si-1KM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -523,7 +523,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="zMz-hU-UYU" style="IBUITableViewCellStyleDefault" id="OXi-cg-ab9" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1365.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1362.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="OXi-cg-ab9" id="npR-a0-9wv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -540,7 +540,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="T7x-zl-6Yf" style="IBUITableViewCellStyleDefault" id="VpI-0o-3Px" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1409" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1406" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VpI-0o-3Px" id="xRH-i4-vne">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -557,7 +557,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="76A-Ng-kfs" style="IBUITableViewCellStyleDefault" id="jK8-tv-hBD" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1452.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1449.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="jK8-tv-hBD" id="I7Q-GQ-u8Y">
|
||||
<rect key="frame" x="0.0" y="0.0" width="355.5" height="43.5"/>
|
||||
@@ -1079,10 +1079,10 @@
|
||||
<color key="backgroundColor" systemColor="systemGroupedBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="NotificationsCell" id="guK-h7-1U7" customClass="NotificationsTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="55.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="55.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="guK-h7-1U7" id="7Rd-Ur-EwD">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ggq-dZ-hv7">
|
||||
@@ -1093,7 +1093,7 @@
|
||||
<color key="onTintColor" name="AccentColor"/>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="78k-PU-gKA">
|
||||
<rect key="frame" x="58" y="11" width="241" height="21"/>
|
||||
<rect key="frame" x="58" y="11" width="241" height="21.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -1124,7 +1124,7 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="OpenSettingsCell" textLabel="5OE-bg-gWy" style="IBUITableViewCellStyleDefault" id="LXf-Fb-We7" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="99" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="99.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="LXf-Fb-We7" id="k2T-id-bci">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
|
||||
24
iOS/UIKit Extensions/SafariView.swift
Normal file
24
iOS/UIKit Extensions/SafariView.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// SafariView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 12/11/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SafariServices
|
||||
|
||||
struct SafariView: UIViewControllerRepresentable {
|
||||
|
||||
let url: URL
|
||||
|
||||
func makeUIViewController(context: UIViewControllerRepresentableContext<SafariView>) -> SFSafariViewController {
|
||||
return SFSafariViewController(url: url)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: SFSafariViewController, context: UIViewControllerRepresentableContext<SafariView>) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user