mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Converts AppDefaults to singleton
This commit is contained in:
@@ -2,290 +2,352 @@
|
||||
// AppDefaults.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 6/28/20.
|
||||
// Created by Stuart Breckenridge on 1/7/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
enum UserInterfaceColorPalette: Int, CustomStringConvertible, CaseIterable {
|
||||
case automatic = 0
|
||||
case light = 1
|
||||
case dark = 2
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .automatic:
|
||||
return NSLocalizedString("Automatic", comment: "Automatic")
|
||||
case .light:
|
||||
return NSLocalizedString("Light", comment: "Light")
|
||||
case .dark:
|
||||
return NSLocalizedString("Dark", comment: "Dark")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AppDefaults {
|
||||
enum FontSize: Int {
|
||||
case small = 0
|
||||
case medium = 1
|
||||
case large = 2
|
||||
case veryLarge = 3
|
||||
}
|
||||
|
||||
final class AppDefaults: ObservableObject {
|
||||
|
||||
#if os(macOS)
|
||||
static var shared: UserDefaults = UserDefaults.standard
|
||||
static let store: UserDefaults = UserDefaults.standard
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
static var shared: UserDefaults = {
|
||||
static let store: UserDefaults = {
|
||||
let appIdentifierPrefix = Bundle.main.object(forInfoDictionaryKey: "AppIdentifierPrefix") as! String
|
||||
let suiteName = "\(appIdentifierPrefix)group.\(Bundle.main.bundleIdentifier!)"
|
||||
return UserDefaults.init(suiteName: suiteName)!
|
||||
}()
|
||||
#endif
|
||||
|
||||
public static let shared = AppDefaults()
|
||||
private init() {}
|
||||
|
||||
struct Key {
|
||||
|
||||
// Shared Defaults
|
||||
static let refreshInterval = "refreshInterval"
|
||||
static let hideDockUnreadCount = "JustinMillerHideDockUnreadCount"
|
||||
static let userInterfaceColorPalette = "userInterfaceColorPalette"
|
||||
static let activeExtensionPointIDs = "activeExtensionPointIDs"
|
||||
static let lastImageCacheFlushDate = "lastImageCacheFlushDate"
|
||||
static let firstRunDate = "firstRunDate"
|
||||
static let timelineGroupByFeed = "timelineGroupByFeed"
|
||||
static let refreshClearsReadArticles = "refreshClearsReadArticles"
|
||||
static let timelineNumberOfLines = "timelineNumberOfLines"
|
||||
static let timelineIconSize = "timelineIconSize"
|
||||
static let timelineSortDirection = "timelineSortDirection"
|
||||
static let articleFullscreenAvailable = "articleFullscreenAvailable"
|
||||
static let articleFullscreenEnabled = "articleFullscreenEnabled"
|
||||
static let confirmMarkAllAsRead = "confirmMarkAllAsRead"
|
||||
static let lastRefresh = "lastRefresh"
|
||||
static let addWebFeedAccountID = "addWebFeedAccountID"
|
||||
static let addWebFeedFolderName = "addWebFeedFolderName"
|
||||
static let addFolderAccountID = "addFolderAccountID"
|
||||
static let timelineSortDirection = "timelineSortDirection"
|
||||
|
||||
// iOS Defaults
|
||||
static let userInterfaceColorPalette = "userInterfaceColorPalette"
|
||||
static let timelineGroupByFeed = "timelineGroupByFeed"
|
||||
static let refreshClearsReadArticles = "refreshClearsReadArticles"
|
||||
static let timelineNumberOfLines = "timelineNumberOfLines"
|
||||
static let timelineIconSize = "timelineIconSize"
|
||||
static let articleFullscreenAvailable = "articleFullscreenAvailable"
|
||||
static let articleFullscreenEnabled = "articleFullscreenEnabled"
|
||||
static let confirmMarkAllAsRead = "confirmMarkAllAsRead"
|
||||
|
||||
// macOS Defaults
|
||||
static let windowState = "windowState"
|
||||
static let sidebarFontSize = "sidebarFontSize"
|
||||
static let timelineFontSize = "timelineFontSize"
|
||||
static let detailFontSize = "detailFontSize"
|
||||
static let openInBrowserInBackground = "openInBrowserInBackground"
|
||||
static let importOPMLAccountID = "importOPMLAccountID"
|
||||
static let exportOPMLAccountID = "exportOPMLAccountID"
|
||||
static let defaultBrowserID = "defaultBrowserID"
|
||||
static let checkForUpdatesAutomatically = "checkForUpdatesAutomatically"
|
||||
static let downloadTestBuilds = "downloadTestBuild"
|
||||
static let sendCrashLogs = "sendCrashLogs"
|
||||
|
||||
// Hidden macOS Defaults
|
||||
static let showDebugMenu = "ShowDebugMenu"
|
||||
static let timelineShowsSeparators = "CorreiaSeparators"
|
||||
static let showTitleOnMainWindow = "KafasisTitleMode"
|
||||
|
||||
#if !MAC_APP_STORE
|
||||
static let webInspectorEnabled = "WebInspectorEnabled"
|
||||
static let webInspectorStartsAttached = "__WebInspectorPageGroupLevel1__.WebKit2InspectorStartsAttached"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static let isDeveloperBuild: Bool = {
|
||||
|
||||
private static let smallestFontSizeRawValue = FontSize.small.rawValue
|
||||
private static let largestFontSizeRawValue = FontSize.veryLarge.rawValue
|
||||
|
||||
// MARK: Development Builds
|
||||
let isDeveloperBuild: Bool = {
|
||||
if let dev = Bundle.main.object(forInfoDictionaryKey: "DeveloperEntitlements") as? String, dev == "-dev" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}()
|
||||
|
||||
static let isFirstRun: Bool = {
|
||||
if let _ = AppDefaults.shared.object(forKey: Key.firstRunDate) as? Date {
|
||||
return false
|
||||
}
|
||||
firstRunDate = Date()
|
||||
return true
|
||||
}()
|
||||
|
||||
static var refreshInterval: RefreshInterval {
|
||||
get {
|
||||
let rawValue = UserDefaults.standard.integer(forKey: Key.refreshInterval)
|
||||
return RefreshInterval(rawValue: rawValue) ?? RefreshInterval.everyHour
|
||||
}
|
||||
// MARK: First Run Details
|
||||
var firstRunDate: Date? {
|
||||
set {
|
||||
UserDefaults.standard.set(newValue.rawValue, forKey: Key.refreshInterval)
|
||||
AppDefaults.store.setValue(newValue, forKey: Key.firstRunDate)
|
||||
objectWillChange.send()
|
||||
}
|
||||
get {
|
||||
AppDefaults.store.object(forKey: Key.firstRunDate) as? Date
|
||||
}
|
||||
}
|
||||
|
||||
static var hideDockUnreadCount: Bool {
|
||||
return bool(for: Key.hideDockUnreadCount)
|
||||
|
||||
// MARK: Refresh Interval
|
||||
@AppStorage(wrappedValue: 4, Key.refreshInterval, store: store) var interval: Int {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static var userInterfaceColorPalette: UserInterfaceColorPalette {
|
||||
|
||||
var refreshInterval: RefreshInterval {
|
||||
RefreshInterval(rawValue: interval) ?? RefreshInterval.everyHour
|
||||
}
|
||||
|
||||
// MARK: Dock Badge
|
||||
@AppStorage(wrappedValue: false, Key.hideDockUnreadCount, store: store) var hideDockUnreadCount {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Color Palette
|
||||
var userInterfaceColorPalette: UserInterfaceColorPalette {
|
||||
get {
|
||||
if let result = UserInterfaceColorPalette(rawValue: int(for: Key.userInterfaceColorPalette)) {
|
||||
return result
|
||||
if let palette = UserInterfaceColorPalette(rawValue: AppDefaults.store.integer(forKey: Key.userInterfaceColorPalette)) {
|
||||
return palette
|
||||
}
|
||||
return .automatic
|
||||
}
|
||||
set {
|
||||
setInt(for: Key.userInterfaceColorPalette, newValue.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var addWebFeedAccountID: String? {
|
||||
get {
|
||||
return string(for: Key.addWebFeedAccountID)
|
||||
}
|
||||
set {
|
||||
setString(for: Key.addWebFeedAccountID, newValue)
|
||||
AppDefaults.store.set(newValue.rawValue, forKey: Key.userInterfaceColorPalette)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static var addWebFeedFolderName: String? {
|
||||
get {
|
||||
return string(for: Key.addWebFeedFolderName)
|
||||
}
|
||||
set {
|
||||
setString(for: Key.addWebFeedFolderName, newValue)
|
||||
}
|
||||
}
|
||||
// MARK: Feeds & Folders
|
||||
@AppStorage(Key.addWebFeedAccountID, store: store) var addWebFeedAccountID: String?
|
||||
|
||||
static var addFolderAccountID: String? {
|
||||
get {
|
||||
return string(for: Key.addFolderAccountID)
|
||||
}
|
||||
set {
|
||||
setString(for: Key.addFolderAccountID, newValue)
|
||||
}
|
||||
}
|
||||
@AppStorage(Key.addWebFeedFolderName, store: store) var addWebFeedFolderName: String?
|
||||
|
||||
static var activeExtensionPointIDs: [[AnyHashable : AnyHashable]]? {
|
||||
@AppStorage(Key.addFolderAccountID, store: store) var addFolderAccountID: String?
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.confirmMarkAllAsRead, store: store) var confirmMarkAllAsRead: Bool
|
||||
|
||||
// MARK: Extension Points
|
||||
var activeExtensionPointIDs: [[AnyHashable : AnyHashable]]? {
|
||||
get {
|
||||
return UserDefaults.standard.object(forKey: Key.activeExtensionPointIDs) as? [[AnyHashable : AnyHashable]]
|
||||
return AppDefaults.store.object(forKey: Key.activeExtensionPointIDs) as? [[AnyHashable : AnyHashable]]
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Key.activeExtensionPointIDs)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static var lastImageCacheFlushDate: Date? {
|
||||
get {
|
||||
return date(for: Key.lastImageCacheFlushDate)
|
||||
}
|
||||
// MARK: Image Cache
|
||||
var lastImageCacheFlushDate: Date? {
|
||||
set {
|
||||
setDate(for: Key.lastImageCacheFlushDate, newValue)
|
||||
AppDefaults.store.setValue(newValue, forKey: Key.lastImageCacheFlushDate)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static var timelineGroupByFeed: Bool {
|
||||
get {
|
||||
return bool(for: Key.timelineGroupByFeed)
|
||||
}
|
||||
set {
|
||||
setBool(for: Key.timelineGroupByFeed, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var refreshClearsReadArticles: Bool {
|
||||
get {
|
||||
return bool(for: Key.refreshClearsReadArticles)
|
||||
}
|
||||
set {
|
||||
setBool(for: Key.refreshClearsReadArticles, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var timelineSortDirection: ComparisonResult {
|
||||
get {
|
||||
return sortDirection(for: Key.timelineSortDirection)
|
||||
}
|
||||
set {
|
||||
setSortDirection(for: Key.timelineSortDirection, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var articleFullscreenAvailable: Bool {
|
||||
get {
|
||||
return bool(for: Key.articleFullscreenAvailable)
|
||||
}
|
||||
set {
|
||||
setBool(for: Key.articleFullscreenAvailable, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var articleFullscreenEnabled: Bool {
|
||||
get {
|
||||
return bool(for: Key.articleFullscreenEnabled)
|
||||
}
|
||||
set {
|
||||
setBool(for: Key.articleFullscreenEnabled, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var confirmMarkAllAsRead: Bool {
|
||||
get {
|
||||
return bool(for: Key.confirmMarkAllAsRead)
|
||||
}
|
||||
set {
|
||||
setBool(for: Key.confirmMarkAllAsRead, newValue)
|
||||
AppDefaults.store.object(forKey: Key.lastImageCacheFlushDate) as? Date
|
||||
}
|
||||
}
|
||||
|
||||
static var lastRefresh: Date? {
|
||||
// MARK: Timeline
|
||||
@AppStorage(wrappedValue: false, Key.timelineGroupByFeed, store: store) var timelineGroupByFeed: Bool
|
||||
|
||||
@AppStorage(wrappedValue: 3, Key.timelineNumberOfLines, store: store) var timelineNumberOfLines: Int {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: 40.0, Key.timelineIconSize, store: store) var timelineIconSize: Double {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
/// Set to `true` to sort oldest to newest, `false` for newest to oldest. Default is `false`.
|
||||
@AppStorage(wrappedValue: false, Key.timelineSortDirection, store: store) var timelineSortDirection: Bool
|
||||
|
||||
// MARK: Refresh
|
||||
@AppStorage(wrappedValue: false, Key.refreshClearsReadArticles, store: store) var refreshClearsReadArticles: Bool
|
||||
|
||||
// MARK: Articles
|
||||
@AppStorage(wrappedValue: false, Key.articleFullscreenAvailable, store: store) var articleFullscreenAvailable: Bool
|
||||
|
||||
// MARK: Refresh
|
||||
var lastRefresh: Date? {
|
||||
set {
|
||||
AppDefaults.store.setValue(newValue, forKey: Key.lastRefresh)
|
||||
objectWillChange.send()
|
||||
}
|
||||
get {
|
||||
return date(for: Key.lastRefresh)
|
||||
AppDefaults.store.object(forKey: Key.lastRefresh) as? Date
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Window State
|
||||
var windowState: [AnyHashable : Any]? {
|
||||
get {
|
||||
return AppDefaults.store.object(forKey: Key.windowState) as? [AnyHashable : Any]
|
||||
}
|
||||
set {
|
||||
setDate(for: Key.lastRefresh, newValue)
|
||||
UserDefaults.standard.set(newValue, forKey: Key.windowState)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static var timelineNumberOfLines: Int {
|
||||
@AppStorage(wrappedValue: false, Key.openInBrowserInBackground, store: store) var openInBrowserInBackground: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
var sidebarFontSize: FontSize {
|
||||
get {
|
||||
return int(for: Key.timelineNumberOfLines)
|
||||
return fontSize(for: Key.sidebarFontSize)
|
||||
}
|
||||
set {
|
||||
setInt(for: Key.timelineNumberOfLines, newValue)
|
||||
AppDefaults.store.set(newValue.rawValue, forKey: Key.sidebarFontSize)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static var timelineIconSize: IconSize {
|
||||
var timelineFontSize: FontSize {
|
||||
get {
|
||||
let rawValue = AppDefaults.shared.integer(forKey: Key.timelineIconSize)
|
||||
return IconSize(rawValue: rawValue) ?? IconSize.medium
|
||||
return fontSize(for: Key.timelineFontSize)
|
||||
}
|
||||
set {
|
||||
AppDefaults.shared.set(newValue.rawValue, forKey: Key.timelineIconSize)
|
||||
AppDefaults.store.set(newValue.rawValue, forKey: Key.timelineFontSize)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static func registerDefaults() {
|
||||
let defaults: [String : Any] = [Key.userInterfaceColorPalette: UserInterfaceColorPalette.automatic.rawValue,
|
||||
Key.timelineGroupByFeed: false,
|
||||
Key.refreshClearsReadArticles: false,
|
||||
Key.timelineNumberOfLines: 2,
|
||||
Key.timelineIconSize: IconSize.medium.rawValue,
|
||||
Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue,
|
||||
Key.articleFullscreenAvailable: false,
|
||||
Key.articleFullscreenEnabled: false,
|
||||
Key.confirmMarkAllAsRead: true]
|
||||
AppDefaults.shared.register(defaults: defaults)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private extension AppDefaults {
|
||||
|
||||
static var firstRunDate: Date? {
|
||||
var detailFontSize: FontSize {
|
||||
get {
|
||||
return date(for: Key.firstRunDate)
|
||||
return fontSize(for: Key.detailFontSize)
|
||||
}
|
||||
set {
|
||||
setDate(for: Key.firstRunDate, newValue)
|
||||
AppDefaults.store.set(newValue.rawValue, forKey: Key.detailFontSize)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
static func string(for key: String) -> String? {
|
||||
return AppDefaults.shared.string(forKey: key)
|
||||
}
|
||||
|
||||
static func setString(for key: String, _ value: String?) {
|
||||
AppDefaults.shared.set(value, forKey: key)
|
||||
}
|
||||
|
||||
static func bool(for key: String) -> Bool {
|
||||
return AppDefaults.shared.bool(forKey: key)
|
||||
}
|
||||
|
||||
static func setBool(for key: String, _ flag: Bool) {
|
||||
AppDefaults.shared.set(flag, forKey: key)
|
||||
}
|
||||
|
||||
static func int(for key: String) -> Int {
|
||||
return AppDefaults.shared.integer(forKey: key)
|
||||
}
|
||||
|
||||
static func setInt(for key: String, _ x: Int) {
|
||||
AppDefaults.shared.set(x, forKey: key)
|
||||
}
|
||||
|
||||
static func date(for key: String) -> Date? {
|
||||
return AppDefaults.shared.object(forKey: key) as? Date
|
||||
}
|
||||
|
||||
static func setDate(for key: String, _ date: Date?) {
|
||||
AppDefaults.shared.set(date, forKey: key)
|
||||
}
|
||||
|
||||
static func sortDirection(for key:String) -> ComparisonResult {
|
||||
let rawInt = int(for: key)
|
||||
if rawInt == ComparisonResult.orderedAscending.rawValue {
|
||||
return .orderedAscending
|
||||
@AppStorage(Key.importOPMLAccountID, store: store) var importOPMLAccountID: String? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
return .orderedDescending
|
||||
}
|
||||
|
||||
static func setSortDirection(for key: String, _ value: ComparisonResult) {
|
||||
if value == .orderedAscending {
|
||||
setInt(for: key, ComparisonResult.orderedAscending.rawValue)
|
||||
|
||||
@AppStorage(Key.exportOPMLAccountID, store: store) var exportOPMLAccountID: String? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
else {
|
||||
setInt(for: key, ComparisonResult.orderedDescending.rawValue)
|
||||
}
|
||||
|
||||
@AppStorage(Key.defaultBrowserID, store: store) var defaultBrowserID: String? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(Key.showTitleOnMainWindow, store: store) var showTitleOnMainWindow: Bool? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.showDebugMenu, store: store) var showDebugMenu: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.timelineShowsSeparators, store: store) var timelineShowsSeparators: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
#if !MAC_APP_STORE
|
||||
@AppStorage(wrappedValue: false, Key.webInspectorEnabled, store: store) var webInspectorEnabled: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.webInspectorStartsAttached, store: store) var webInspectorStartsAttached: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@AppStorage(wrappedValue: true, Key.checkForUpdatesAutomatically, store: store) var checkForUpdatesAutomatically: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.downloadTestBuilds, store: store) var downloadTestBuilds: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: true, Key.sendCrashLogs, store: store) var sendCrashLogs: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension AppDefaults {
|
||||
|
||||
func isFirstRun() -> Bool {
|
||||
if let _ = AppDefaults.store.object(forKey: Key.firstRunDate) as? Date {
|
||||
return false
|
||||
}
|
||||
firstRunDate = Date()
|
||||
return true
|
||||
}
|
||||
|
||||
func fontSize(for key: String) -> FontSize {
|
||||
// Punted till after 1.0.
|
||||
return .medium
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,321 +0,0 @@
|
||||
//
|
||||
// AppSettings.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Stuart Breckenridge on 1/7/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
enum UserInterfaceColorPalette: Int, CustomStringConvertible, CaseIterable {
|
||||
case automatic = 0
|
||||
case light = 1
|
||||
case dark = 2
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .automatic:
|
||||
return NSLocalizedString("Automatic", comment: "Automatic")
|
||||
case .light:
|
||||
return NSLocalizedString("Light", comment: "Light")
|
||||
case .dark:
|
||||
return NSLocalizedString("Dark", comment: "Dark")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum FontSize: Int {
|
||||
case small = 0
|
||||
case medium = 1
|
||||
case large = 2
|
||||
case veryLarge = 3
|
||||
}
|
||||
|
||||
final class AppSettings: ObservableObject {
|
||||
|
||||
#if os(macOS)
|
||||
static let store: UserDefaults = UserDefaults.standard
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
static let store: UserDefaults = {
|
||||
let appIdentifierPrefix = Bundle.main.object(forInfoDictionaryKey: "AppIdentifierPrefix") as! String
|
||||
let suiteName = "\(appIdentifierPrefix)group.\(Bundle.main.bundleIdentifier!)"
|
||||
return UserDefaults.init(suiteName: suiteName)!
|
||||
}()
|
||||
#endif
|
||||
|
||||
public static let shared = AppSettings()
|
||||
private init() {}
|
||||
|
||||
struct Key {
|
||||
|
||||
// Shared Defaults
|
||||
static let refreshInterval = "refreshInterval"
|
||||
static let hideDockUnreadCount = "JustinMillerHideDockUnreadCount"
|
||||
static let activeExtensionPointIDs = "activeExtensionPointIDs"
|
||||
static let lastImageCacheFlushDate = "lastImageCacheFlushDate"
|
||||
static let firstRunDate = "firstRunDate"
|
||||
static let lastRefresh = "lastRefresh"
|
||||
static let addWebFeedAccountID = "addWebFeedAccountID"
|
||||
static let addWebFeedFolderName = "addWebFeedFolderName"
|
||||
static let addFolderAccountID = "addFolderAccountID"
|
||||
static let timelineSortDirection = "timelineSortDirection"
|
||||
|
||||
// iOS Defaults
|
||||
static let userInterfaceColorPalette = "userInterfaceColorPalette"
|
||||
static let timelineGroupByFeed = "timelineGroupByFeed"
|
||||
static let refreshClearsReadArticles = "refreshClearsReadArticles"
|
||||
static let timelineNumberOfLines = "timelineNumberOfLines"
|
||||
static let timelineIconSize = "timelineIconSize"
|
||||
static let articleFullscreenAvailable = "articleFullscreenAvailable"
|
||||
static let articleFullscreenEnabled = "articleFullscreenEnabled"
|
||||
static let confirmMarkAllAsRead = "confirmMarkAllAsRead"
|
||||
|
||||
// macOS Defaults
|
||||
static let windowState = "windowState"
|
||||
static let sidebarFontSize = "sidebarFontSize"
|
||||
static let timelineFontSize = "timelineFontSize"
|
||||
static let detailFontSize = "detailFontSize"
|
||||
static let openInBrowserInBackground = "openInBrowserInBackground"
|
||||
static let importOPMLAccountID = "importOPMLAccountID"
|
||||
static let exportOPMLAccountID = "exportOPMLAccountID"
|
||||
static let defaultBrowserID = "defaultBrowserID"
|
||||
|
||||
// Hidden macOS Defaults
|
||||
static let showDebugMenu = "ShowDebugMenu"
|
||||
static let timelineShowsSeparators = "CorreiaSeparators"
|
||||
static let showTitleOnMainWindow = "KafasisTitleMode"
|
||||
|
||||
#if !MAC_APP_STORE
|
||||
static let webInspectorEnabled = "WebInspectorEnabled"
|
||||
static let webInspectorStartsAttached = "__WebInspectorPageGroupLevel1__.WebKit2InspectorStartsAttached"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
private static let smallestFontSizeRawValue = FontSize.small.rawValue
|
||||
private static let largestFontSizeRawValue = FontSize.veryLarge.rawValue
|
||||
|
||||
// MARK: Development Builds
|
||||
let isDeveloperBuild: Bool = {
|
||||
if let dev = Bundle.main.object(forInfoDictionaryKey: "DeveloperEntitlements") as? String, dev == "-dev" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}()
|
||||
|
||||
// MARK: First Run Details
|
||||
var firstRunDate: Date? {
|
||||
set {
|
||||
AppSettings.store.setValue(newValue, forKey: Key.firstRunDate)
|
||||
objectWillChange.send()
|
||||
}
|
||||
get {
|
||||
AppSettings.store.object(forKey: Key.firstRunDate) as? Date
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Refresh Timings
|
||||
@AppStorage(wrappedValue: RefreshInterval.everyHour, Key.refreshInterval, store: store) var refreshInterval: RefreshInterval
|
||||
|
||||
// MARK: Dock Badge
|
||||
@AppStorage(wrappedValue: false, Key.hideDockUnreadCount, store: store) var hideDockUnreadCount
|
||||
|
||||
// MARK: Color Palette
|
||||
var userInterfaceColorPalette: UserInterfaceColorPalette {
|
||||
get {
|
||||
if let palette = UserInterfaceColorPalette(rawValue: AppSettings.store.integer(forKey: Key.userInterfaceColorPalette)) {
|
||||
return palette
|
||||
}
|
||||
return .automatic
|
||||
}
|
||||
set {
|
||||
AppSettings.store.set(newValue.rawValue, forKey: Key.userInterfaceColorPalette)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Feeds & Folders
|
||||
@AppStorage(Key.addWebFeedAccountID, store: store) var addWebFeedAccountID: String?
|
||||
|
||||
@AppStorage(Key.addWebFeedFolderName, store: store) var addWebFeedFolderName: String?
|
||||
|
||||
@AppStorage(Key.addFolderAccountID, store: store) var addFolderAccountID: String?
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.confirmMarkAllAsRead, store: store) var confirmMarkAllAsRead: Bool
|
||||
|
||||
// MARK: Extension Points
|
||||
var activeExtensionPointIDs: [[AnyHashable : AnyHashable]]? {
|
||||
get {
|
||||
return AppSettings.store.object(forKey: Key.activeExtensionPointIDs) as? [[AnyHashable : AnyHashable]]
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Key.activeExtensionPointIDs)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Image Cache
|
||||
var lastImageCacheFlushDate: Date? {
|
||||
set {
|
||||
AppSettings.store.setValue(newValue, forKey: Key.lastImageCacheFlushDate)
|
||||
objectWillChange.send()
|
||||
}
|
||||
get {
|
||||
AppSettings.store.object(forKey: Key.lastImageCacheFlushDate) as? Date
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Timeline
|
||||
@AppStorage(wrappedValue: false, Key.timelineGroupByFeed, store: store) var timelineGroupByFeed: Bool
|
||||
|
||||
@AppStorage(wrappedValue: 3, Key.timelineNumberOfLines, store: store) var timelineNumberOfLines: Int {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: 40.0, Key.timelineIconSize, store: store) var timelineIconSize: Double {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
/// Set to `true` to sort oldest to newest, `false` for newest to oldest. Default is `false`.
|
||||
@AppStorage(wrappedValue: false, Key.timelineSortDirection, store: store) var timelineSortDirection: Bool
|
||||
|
||||
// MARK: Refresh
|
||||
@AppStorage(wrappedValue: false, Key.refreshClearsReadArticles, store: store) var refreshClearsReadArticles: Bool
|
||||
|
||||
// MARK: Articles
|
||||
@AppStorage(wrappedValue: false, Key.articleFullscreenAvailable, store: store) var articleFullscreenAvailable: Bool
|
||||
|
||||
// MARK: Refresh
|
||||
var lastRefresh: Date? {
|
||||
set {
|
||||
AppSettings.store.setValue(newValue, forKey: Key.lastRefresh)
|
||||
objectWillChange.send()
|
||||
}
|
||||
get {
|
||||
AppSettings.store.object(forKey: Key.lastRefresh) as? Date
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Window State
|
||||
var windowState: [AnyHashable : Any]? {
|
||||
get {
|
||||
return AppSettings.store.object(forKey: Key.windowState) as? [AnyHashable : Any]
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Key.windowState)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.openInBrowserInBackground, store: store) var openInBrowserInBackground: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
var sidebarFontSize: FontSize {
|
||||
get {
|
||||
return fontSize(for: Key.sidebarFontSize)
|
||||
}
|
||||
set {
|
||||
AppSettings.store.set(newValue.rawValue, forKey: Key.sidebarFontSize)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
var timelineFontSize: FontSize {
|
||||
get {
|
||||
return fontSize(for: Key.timelineFontSize)
|
||||
}
|
||||
set {
|
||||
AppSettings.store.set(newValue.rawValue, forKey: Key.timelineFontSize)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
var detailFontSize: FontSize {
|
||||
get {
|
||||
return fontSize(for: Key.detailFontSize)
|
||||
}
|
||||
set {
|
||||
AppSettings.store.set(newValue.rawValue, forKey: Key.detailFontSize)
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(Key.importOPMLAccountID, store: store) var importOPMLAccountID: String? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(Key.exportOPMLAccountID, store: store) var exportOPMLAccountID: String? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(Key.defaultBrowserID, store: store) var defaultBrowserID: String? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(Key.showTitleOnMainWindow, store: store) var showTitleOnMainWindow: Bool? {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.showDebugMenu, store: store) var showDebugMenu: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.timelineShowsSeparators, store: store) var timelineShowsSeparators: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
#if !MAC_APP_STORE
|
||||
@AppStorage(wrappedValue: false, Key.webInspectorEnabled, store: store) var webInspectorEnabled: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage(wrappedValue: false, Key.webInspectorStartsAttached, store: store) var webInspectorStartsAttached: Bool {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension AppSettings {
|
||||
|
||||
func isFirstRun() -> Bool {
|
||||
if let _ = AppSettings.store.object(forKey: Key.firstRunDate) as? Date {
|
||||
return false
|
||||
}
|
||||
firstRunDate = Date()
|
||||
return true
|
||||
}
|
||||
|
||||
func fontSize(for key: String) -> FontSize {
|
||||
// Punted till after 1.0.
|
||||
return .medium
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,13 @@ struct MainApp: App {
|
||||
|
||||
#if os(macOS)
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
||||
let preferences = MacPreferences()
|
||||
#endif
|
||||
#if os(iOS)
|
||||
@UIApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
||||
#endif
|
||||
|
||||
@StateObject private var sceneModel = SceneModel()
|
||||
@StateObject private var defaults = AppDefaults.shared
|
||||
|
||||
@SceneBuilder var body: some Scene {
|
||||
#if os(macOS)
|
||||
@@ -134,7 +134,7 @@ struct MainApp: App {
|
||||
.padding()
|
||||
.frame(width: 500)
|
||||
.navigationTitle("Preferences")
|
||||
.environmentObject(preferences)
|
||||
.environmentObject(defaults)
|
||||
}
|
||||
.windowToolbarStyle(UnifiedWindowToolbarStyle())
|
||||
|
||||
|
||||
@@ -71,9 +71,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
AppDefaults.registerDefaults()
|
||||
//AppDefaults.registerDefaults()
|
||||
|
||||
let isFirstRun = AppDefaults.isFirstRun
|
||||
let isFirstRun = AppDefaults.shared.isFirstRun()
|
||||
if isFirstRun {
|
||||
os_log("Is first run.", log: log, type: .info)
|
||||
}
|
||||
@@ -139,7 +139,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
}
|
||||
|
||||
@objc func accountRefreshDidFinish(_ note: Notification) {
|
||||
AppDefaults.lastRefresh = Date()
|
||||
AppDefaults.shared.lastRefresh = Date()
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
@@ -163,7 +163,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
// extensionFeedAddRequestFile.resume()
|
||||
syncTimer?.update()
|
||||
|
||||
if let lastRefresh = AppDefaults.lastRefresh {
|
||||
if let lastRefresh = AppDefaults.shared.lastRefresh {
|
||||
if Date() > lastRefresh.addingTimeInterval(15 * 60) {
|
||||
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.log)
|
||||
} else {
|
||||
|
||||
@@ -57,7 +57,7 @@ struct SettingsView: View {
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
|
||||
@StateObject private var viewModel = SettingsViewModel()
|
||||
@StateObject private var settings = AppSettings.shared
|
||||
@StateObject private var settings = AppDefaults.shared
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
|
||||
@@ -10,7 +10,7 @@ import SwiftUI
|
||||
|
||||
struct TimelineLayoutView: View {
|
||||
|
||||
@EnvironmentObject private var appSettings: AppSettings
|
||||
@EnvironmentObject private var appSettings: AppDefaults
|
||||
|
||||
private let sampleTitle = "Lorem dolor sed viverra ipsum. Gravida rutrum quisque non tellus. Rutrum tellus pellentesque eu tincidunt tortor. Sed blandit libero volutpat sed cras ornare. Et netus et malesuada fames ac. Ultrices eros in cursus turpis massa tincidunt dui ut ornare. Lacus sed viverra tellus in. Sollicitudin ac orci phasellus egestas. Purus in mollis nunc sed. Sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque. Interdum consectetur libero id faucibus nisl tincidunt eget."
|
||||
|
||||
@@ -33,7 +33,7 @@ struct TimelineLayoutView: View {
|
||||
}
|
||||
|
||||
var iconSize: some View {
|
||||
Slider(value: $appSettings.timelineIconSize, in: 20...60, minimumValueLabel: Text("Small"), maximumValueLabel: Text("Large"), label: {
|
||||
Slider(value: $appSettings.timelineIconSize, in: 20...60, step: 10, minimumValueLabel: Text("Small"), maximumValueLabel: Text("Large"), label: {
|
||||
Text(String(appSettings.timelineIconSize))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
}
|
||||
#endif
|
||||
|
||||
AppDefaults.registerDefaults()
|
||||
let isFirstRun = AppDefaults.isFirstRun
|
||||
//AppDefaults.registerDefaults()
|
||||
let isFirstRun = AppDefaults.shared.isFirstRun()
|
||||
if isFirstRun {
|
||||
os_log(.debug, log: log, "Is first run.")
|
||||
}
|
||||
@@ -245,7 +245,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
|
||||
// MARK: - Dock Badge
|
||||
@objc func updateDockBadge() {
|
||||
let label = unreadCount > 0 && !AppDefaults.hideDockUnreadCount ? "\(unreadCount)" : ""
|
||||
let label = unreadCount > 0 && !AppDefaults.shared.hideDockUnreadCount ? "\(unreadCount)" : ""
|
||||
NSApplication.shared.dockTile.badgeLabel = label
|
||||
}
|
||||
|
||||
|
||||
@@ -32,19 +32,19 @@ struct MacPreferenceViewModel {
|
||||
|
||||
struct MacPreferencesView: View {
|
||||
|
||||
@EnvironmentObject var preferences: MacPreferences
|
||||
@EnvironmentObject var defaults: AppDefaults
|
||||
@State private var viewModel = MacPreferenceViewModel()
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if viewModel.currentPreferencePane == .general {
|
||||
AnyView(GeneralPreferencesView())
|
||||
AnyView(GeneralPreferencesView().environmentObject(defaults))
|
||||
}
|
||||
else if viewModel.currentPreferencePane == .accounts {
|
||||
AnyView(AccountsPreferencesView())
|
||||
AnyView(AccountsPreferencesView().environmentObject(defaults))
|
||||
}
|
||||
else {
|
||||
AnyView(AdvancedPreferencesView(preferences: preferences))
|
||||
AnyView(AdvancedPreferencesView().environmentObject(defaults))
|
||||
}
|
||||
}
|
||||
.toolbar {
|
||||
@@ -1,96 +0,0 @@
|
||||
//
|
||||
// MacPreferences.swift
|
||||
// macOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 27/6/20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
enum FontSize: Int {
|
||||
case small = 0
|
||||
case medium = 1
|
||||
case large = 2
|
||||
case veryLarge = 3
|
||||
}
|
||||
|
||||
/// The `MacPreferences` object stores all macOS specific user preferences.
|
||||
class MacPreferences: ObservableObject {
|
||||
|
||||
private struct AppKeys {
|
||||
static let refreshInterval = "refreshInterval"
|
||||
static let openInBackground = "openInBrowserInBackground"
|
||||
static let showUnreadCountInDock = "showUnreadCountInDock"
|
||||
static let checkForUpdatesAutomatically = "checkForAppUpdates"
|
||||
static let downloadTestBuilds = "downloadTestBuilds"
|
||||
static let sendCrashLogs = "sendCrashLogs"
|
||||
}
|
||||
|
||||
// Refresh Interval
|
||||
public let refreshIntervals:[String] = RefreshFrequencies.allCases.map({ $0.description })
|
||||
@AppStorage(wrappedValue: 0, AppKeys.refreshInterval) var refreshFrequency {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// Open in background
|
||||
@AppStorage(wrappedValue: false, AppKeys.openInBackground) var openInBackground {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// Unread Count in Dock
|
||||
@AppStorage(wrappedValue: true, AppKeys.showUnreadCountInDock) var showUnreadCountInDock {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// Check for App Updates
|
||||
@AppStorage(wrappedValue: true, AppKeys.checkForUpdatesAutomatically) var checkForUpdatesAutomatically {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// Test builds
|
||||
@AppStorage(wrappedValue: false, AppKeys.downloadTestBuilds) var downloadTestBuilds {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
// Crash Logs
|
||||
@AppStorage(wrappedValue: false, AppKeys.sendCrashLogs) var sendCrashLogs {
|
||||
didSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum RefreshFrequencies: CaseIterable, CustomStringConvertible {
|
||||
|
||||
case refreshEvery10Mins, refreshEvery20Mins, refreshHourly, refreshEvery2Hours, refreshEvery4Hours, refreshEvery8Hours, none
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .refreshEvery10Mins:
|
||||
return "Every 10 minutes"
|
||||
case .refreshEvery20Mins:
|
||||
return "Every 20 minutes"
|
||||
case .refreshHourly:
|
||||
return "Every hour"
|
||||
case .refreshEvery2Hours:
|
||||
return "Every 2 hours"
|
||||
case .refreshEvery4Hours:
|
||||
return "Every 4 hours"
|
||||
case .refreshEvery8Hours:
|
||||
return "Every 8 hours"
|
||||
case .none:
|
||||
return "Manually"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import SwiftUI
|
||||
|
||||
struct AdvancedPreferencesView: View {
|
||||
|
||||
@StateObject var preferences: MacPreferences
|
||||
@EnvironmentObject private var preferences: AppDefaults
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// GeneralPreferencesView.swift
|
||||
// macOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 27/6/20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GeneralPreferencesView: View {
|
||||
|
||||
@EnvironmentObject private var defaults: AppDefaults
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Form {
|
||||
Picker("Refresh Feeds",
|
||||
selection: $defaults.interval,
|
||||
content: {
|
||||
ForEach(RefreshInterval.allCases, content: { interval in
|
||||
Text(interval.description()).tag(interval.rawValue)
|
||||
})
|
||||
}).frame(width: 300, alignment: .center)
|
||||
|
||||
Toggle("Open webpages in background in browser", isOn: $defaults.openInBrowserInBackground)
|
||||
|
||||
Toggle("Hide Unread Count in Dock", isOn: $defaults.hideDockUnreadCount)
|
||||
}
|
||||
Spacer()
|
||||
}.frame(width: 300, alignment: .center)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
//
|
||||
// GeneralPreferencesView.swift
|
||||
// macOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 27/6/20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GeneralPreferencesView: View {
|
||||
|
||||
@ObservedObject private var preferences = MacPreferences()
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Form {
|
||||
Picker("Refresh Feeds",
|
||||
selection: $preferences.refreshFrequency,
|
||||
content: {
|
||||
ForEach(0..<preferences.refreshIntervals.count, content: {
|
||||
Text(preferences.refreshIntervals[$0])
|
||||
})
|
||||
}).frame(width: 300, alignment: .center)
|
||||
|
||||
Toggle("Open webpages in background in browser", isOn: $preferences.openInBackground)
|
||||
|
||||
Toggle("Show Unread Count in Dock", isOn: $preferences.showUnreadCountInDock)
|
||||
}
|
||||
Spacer()
|
||||
}.frame(width: 300, alignment: .center)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,15 +11,16 @@
|
||||
172199ED24AB2E0100A31D04 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172199EC24AB2E0100A31D04 /* SafariView.swift */; };
|
||||
172199EF24AB372D00A31D04 /* VisualEffectBlur.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172199EE24AB372D00A31D04 /* VisualEffectBlur.swift */; };
|
||||
172199F124AB716900A31D04 /* SidebarToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172199F024AB716900A31D04 /* SidebarToolbar.swift */; };
|
||||
1729528E24AA1A4900D65E66 /* MacPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729526C24AA1A4900D65E66 /* MacPreferences.swift */; };
|
||||
1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529024AA1CAA00D65E66 /* AccountsPreferencesView.swift */; };
|
||||
1729529424AA1CAA00D65E66 /* AdvancedPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529124AA1CAA00D65E66 /* AdvancedPreferencesView.swift */; };
|
||||
1729529524AA1CAA00D65E66 /* GeneralPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529224AA1CAA00D65E66 /* GeneralPreferencesView.swift */; };
|
||||
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529624AA1CD000D65E66 /* MacPreferencesView.swift */; };
|
||||
1729529B24AA1FD200D65E66 /* MacSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529A24AA1FD200D65E66 /* MacSearchField.swift */; };
|
||||
172952B024AA287100D65E66 /* CompactSidebarContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */; };
|
||||
1776E88E24AC5F8A00E78166 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppSettings.swift */; };
|
||||
1776E88F24AC5F8A00E78166 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppSettings.swift */; };
|
||||
175942AA24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
||||
1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
||||
179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
|
||||
179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
|
||||
17B223DC24AC24D2001E4592 /* TimelineLayoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */; };
|
||||
@@ -489,8 +490,6 @@
|
||||
51E4992424A8098400B667CB /* SmartFeedPasteboardWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AD1EB92031649C00BC20B7 /* SmartFeedPasteboardWriter.swift */; };
|
||||
51E4992624A80AAB00B667CB /* AppAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4992524A80AAB00B667CB /* AppAssets.swift */; };
|
||||
51E4992724A80AAB00B667CB /* AppAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4992524A80AAB00B667CB /* AppAssets.swift */; };
|
||||
51E4992924A866F000B667CB /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4992824A866F000B667CB /* AppDefaults.swift */; };
|
||||
51E4992A24A866F000B667CB /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4992824A866F000B667CB /* AppDefaults.swift */; };
|
||||
51E4992B24A8676300B667CB /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; };
|
||||
51E4992C24A8676300B667CB /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
||||
51E4992D24A8676300B667CB /* FetchRequestOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCAE22BC8C35007694F0 /* FetchRequestOperation.swift */; };
|
||||
@@ -511,9 +510,7 @@
|
||||
51E4993E24A870F900B667CB /* UserNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FE10022345529D0056195D /* UserNotificationManager.swift */; };
|
||||
51E4993F24A8713B00B667CB /* ArticleStatusSyncTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */; };
|
||||
51E4994024A8713B00B667CB /* AccountRefreshTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */; };
|
||||
51E4994124A8713B00B667CB /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||
51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */; };
|
||||
51E4994424A8713C00B667CB /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||
51E4994524A872AD00B667CB /* org.sparkle-project.Downloader.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 65ED42BC235E71B40081F399 /* org.sparkle-project.Downloader.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
51E4994624A872AD00B667CB /* org.sparkle-project.InstallerConnection.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 65ED42B8235E71B40081F399 /* org.sparkle-project.InstallerConnection.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
51E4994724A872AD00B667CB /* org.sparkle-project.InstallerLauncher.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 65ED42B6235E71B40081F399 /* org.sparkle-project.InstallerLauncher.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
@@ -1697,14 +1694,13 @@
|
||||
172199EC24AB2E0100A31D04 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
|
||||
172199EE24AB372D00A31D04 /* VisualEffectBlur.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VisualEffectBlur.swift; sourceTree = "<group>"; };
|
||||
172199F024AB716900A31D04 /* SidebarToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarToolbar.swift; sourceTree = "<group>"; };
|
||||
1729526C24AA1A4900D65E66 /* MacPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacPreferences.swift; sourceTree = "<group>"; };
|
||||
1729529024AA1CAA00D65E66 /* AccountsPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsPreferencesView.swift; sourceTree = "<group>"; };
|
||||
1729529124AA1CAA00D65E66 /* AdvancedPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedPreferencesView.swift; sourceTree = "<group>"; };
|
||||
1729529224AA1CAA00D65E66 /* GeneralPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneralPreferencesView.swift; sourceTree = "<group>"; };
|
||||
1729529624AA1CD000D65E66 /* MacPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacPreferencesView.swift; sourceTree = "<group>"; };
|
||||
1729529A24AA1FD200D65E66 /* MacSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacSearchField.swift; sourceTree = "<group>"; };
|
||||
172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactSidebarContainerView.swift; sourceTree = "<group>"; };
|
||||
1776E88D24AC5F8A00E78166 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
|
||||
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
|
||||
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = "<group>"; };
|
||||
17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineLayoutView.swift; sourceTree = "<group>"; };
|
||||
3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -1922,7 +1918,6 @@
|
||||
51E4989824A8067000B667CB /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
51E498B224A806AA00B667CB /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
|
||||
51E4992524A80AAB00B667CB /* AppAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAssets.swift; sourceTree = "<group>"; };
|
||||
51E4992824A866F000B667CB /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
|
||||
51E4993924A8708800B667CB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
51E4993B24A8709900B667CB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
51E4995824A873F900B667CB /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = "<group>"; };
|
||||
@@ -2359,29 +2354,20 @@
|
||||
1729528F24AA1A4F00D65E66 /* Preferences */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1729529824AA1CD900D65E66 /* Model */,
|
||||
1729529924AA1CE100D65E66 /* Views */,
|
||||
1729529624AA1CD000D65E66 /* MacPreferencesView.swift */,
|
||||
1729529924AA1CE100D65E66 /* View */,
|
||||
);
|
||||
path = Preferences;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1729529824AA1CD900D65E66 /* Model */ = {
|
||||
1729529924AA1CE100D65E66 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1729526C24AA1A4900D65E66 /* MacPreferences.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1729529924AA1CE100D65E66 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1729529624AA1CD000D65E66 /* MacPreferencesView.swift */,
|
||||
1729529024AA1CAA00D65E66 /* AccountsPreferencesView.swift */,
|
||||
1729529124AA1CAA00D65E66 /* AdvancedPreferencesView.swift */,
|
||||
1729529224AA1CAA00D65E66 /* GeneralPreferencesView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
17B223B924AC24A8001E4592 /* Submenus */ = {
|
||||
@@ -2703,8 +2689,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51E4992524A80AAB00B667CB /* AppAssets.swift */,
|
||||
51E4992824A866F000B667CB /* AppDefaults.swift */,
|
||||
1776E88D24AC5F8A00E78166 /* AppSettings.swift */,
|
||||
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */,
|
||||
51E4995824A873F900B667CB /* ErrorHandler.swift */,
|
||||
51C0513624A77DF700194D5E /* MainApp.swift */,
|
||||
51E499D724A912C200B667CB /* SceneModel.swift */,
|
||||
@@ -4732,7 +4717,6 @@
|
||||
51E4995924A873F900B667CB /* ErrorHandler.swift in Sources */,
|
||||
51392D1B24AC19A000BE0D35 /* SidebarExpandedContainers.swift in Sources */,
|
||||
51E4992F24A8676400B667CB /* ArticleArray.swift in Sources */,
|
||||
51E4994424A8713C00B667CB /* RefreshInterval.swift in Sources */,
|
||||
51E498F824A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
||||
51E4996A24A8762D00B667CB /* ExtractedArticle.swift in Sources */,
|
||||
51919FF124AB864A00541E64 /* TimelineModel.swift in Sources */,
|
||||
@@ -4780,7 +4764,6 @@
|
||||
51E4993124A8676400B667CB /* FetchRequestOperation.swift in Sources */,
|
||||
51E4992624A80AAB00B667CB /* AppAssets.swift in Sources */,
|
||||
51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
|
||||
51E4992924A866F000B667CB /* AppDefaults.swift in Sources */,
|
||||
51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */,
|
||||
51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */,
|
||||
51E4997124A8764C00B667CB /* ActivityType.swift in Sources */,
|
||||
@@ -4800,6 +4783,7 @@
|
||||
51919FAC24AA8CCA00541E64 /* UnreadCountView.swift in Sources */,
|
||||
51E4991924A8090A00B667CB /* CacheCleaner.swift in Sources */,
|
||||
51E498F724A8085D00B667CB /* SearchTimelineFeedDelegate.swift in Sources */,
|
||||
175942AA24AD533200585066 /* RefreshInterval.swift in Sources */,
|
||||
51E4993524A867E800B667CB /* AppNotifications.swift in Sources */,
|
||||
51C0515E24A77DF800194D5E /* MainApp.swift in Sources */,
|
||||
51919FF724AB8B7700541E64 /* TimelineView.swift in Sources */,
|
||||
@@ -4807,7 +4791,7 @@
|
||||
51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
||||
51919FEE24AB85E400541E64 /* TimelineContainerView.swift in Sources */,
|
||||
51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */,
|
||||
1776E88E24AC5F8A00E78166 /* AppSettings.swift in Sources */,
|
||||
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */,
|
||||
51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -4849,12 +4833,11 @@
|
||||
51E49A0124A91FC100B667CB /* RegularSidebarContainerView.swift in Sources */,
|
||||
51E4995B24A875D500B667CB /* ArticlePasteboardWriter.swift in Sources */,
|
||||
51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */,
|
||||
1776E88F24AC5F8A00E78166 /* AppSettings.swift in Sources */,
|
||||
1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */,
|
||||
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */,
|
||||
51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
||||
1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */,
|
||||
51919FAD24AA8CCA00541E64 /* UnreadCountView.swift in Sources */,
|
||||
51E4994124A8713B00B667CB /* RefreshInterval.swift in Sources */,
|
||||
51E498C924A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
||||
51E498FC24A808BA00B667CB /* FaviconURLFinder.swift in Sources */,
|
||||
51E4991C24A8092000B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
||||
@@ -4866,6 +4849,7 @@
|
||||
51E49A0424A91FF600B667CB /* SceneNavigationView.swift in Sources */,
|
||||
51E498CC24A8085D00B667CB /* SearchFeedDelegate.swift in Sources */,
|
||||
51E498C824A8085D00B667CB /* SmartFeedsController.swift in Sources */,
|
||||
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */,
|
||||
51E4992C24A8676300B667CB /* ArticleSorter.swift in Sources */,
|
||||
51E4995024A8734C00B667CB /* ExtensionPoint.swift in Sources */,
|
||||
51E4990E24A808CC00B667CB /* HTMLMetadataDownloader.swift in Sources */,
|
||||
@@ -4877,7 +4861,6 @@
|
||||
51E4995A24A873F900B667CB /* ErrorHandler.swift in Sources */,
|
||||
51E4991F24A8094300B667CB /* RSImage-AppIcons.swift in Sources */,
|
||||
51E4991224A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */,
|
||||
1729528E24AA1A4900D65E66 /* MacPreferences.swift in Sources */,
|
||||
51E4993E24A870F900B667CB /* UserNotificationManager.swift in Sources */,
|
||||
51E4992E24A8676300B667CB /* FetchRequestQueue.swift in Sources */,
|
||||
51E498CF24A8085D00B667CB /* SmartFeed.swift in Sources */,
|
||||
@@ -4889,7 +4872,6 @@
|
||||
51E498FE24A808BA00B667CB /* FaviconDownloader.swift in Sources */,
|
||||
51919FA724AA64B000541E64 /* SidebarView.swift in Sources */,
|
||||
51E498FD24A808BA00B667CB /* ColorHash.swift in Sources */,
|
||||
51E4992A24A866F000B667CB /* AppDefaults.swift in Sources */,
|
||||
51E4991824A8090A00B667CB /* CacheCleaner.swift in Sources */,
|
||||
51E498CD24A8085D00B667CB /* SearchTimelineFeedDelegate.swift in Sources */,
|
||||
51E4996124A875F400B667CB /* ArticleRenderer.swift in Sources */,
|
||||
|
||||
@@ -38,7 +38,7 @@ final class ExtensionPointManager: FeedProviderManagerDelegate {
|
||||
let activeExtensionPointTypes = activeExtensionPoints.keys.compactMap({ ObjectIdentifier($0.extensionPointType) })
|
||||
var available = [ExtensionPoint.Type]()
|
||||
for possibleExtensionPointType in possibleExtensionPointTypes {
|
||||
if !(AppDefaults.isDeveloperBuild && possibleExtensionPointType.isDeveloperBuildRestricted) {
|
||||
if !(AppDefaults.shared.isDeveloperBuild && possibleExtensionPointType.isDeveloperBuildRestricted) {
|
||||
if possibleExtensionPointType.isSinglton {
|
||||
if !activeExtensionPointTypes.contains(ObjectIdentifier(possibleExtensionPointType)) {
|
||||
available.append(possibleExtensionPointType)
|
||||
@@ -109,7 +109,7 @@ final class ExtensionPointManager: FeedProviderManagerDelegate {
|
||||
private extension ExtensionPointManager {
|
||||
|
||||
func loadExtensionPoints() {
|
||||
if let extensionPointUserInfos = AppDefaults.activeExtensionPointIDs {
|
||||
if let extensionPointUserInfos = AppDefaults.shared.activeExtensionPointIDs {
|
||||
for extensionPointUserInfo in extensionPointUserInfos {
|
||||
if let extensionPointID = ExtensionPointIdentifer(userInfo: extensionPointUserInfo) {
|
||||
activeExtensionPoints[extensionPointID] = extensionPoint(for: extensionPointID)
|
||||
@@ -119,7 +119,7 @@ private extension ExtensionPointManager {
|
||||
}
|
||||
|
||||
func saveExtensionPointIDs() {
|
||||
AppDefaults.activeExtensionPointIDs = activeExtensionPoints.keys.map({ $0.userInfo })
|
||||
AppDefaults.shared.activeExtensionPointIDs = activeExtensionPoints.keys.map({ $0.userInfo })
|
||||
NotificationCenter.default.post(name: .ActiveExtensionPointsDidChange, object: nil, userInfo: nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ struct AddWebFeedDefaultContainer {
|
||||
|
||||
static var defaultContainer: Container? {
|
||||
|
||||
if let accountID = AppDefaults.addWebFeedAccountID, let account = AccountManager.shared.activeAccounts.first(where: { $0.accountID == accountID }) {
|
||||
if let folderName = AppDefaults.addWebFeedFolderName, let folder = account.existingFolder(withDisplayName: folderName) {
|
||||
if let accountID = AppDefaults.shared.addWebFeedAccountID, let account = AccountManager.shared.activeAccounts.first(where: { $0.accountID == accountID }) {
|
||||
if let folderName = AppDefaults.shared.addWebFeedFolderName, let folder = account.existingFolder(withDisplayName: folderName) {
|
||||
return folder
|
||||
} else {
|
||||
return substituteContainerIfNeeded(account: account)
|
||||
@@ -28,11 +28,11 @@ struct AddWebFeedDefaultContainer {
|
||||
}
|
||||
|
||||
static func saveDefaultContainer(_ container: Container) {
|
||||
AppDefaults.addWebFeedAccountID = container.account?.accountID
|
||||
AppDefaults.shared.addWebFeedAccountID = container.account?.accountID
|
||||
if let folder = container as? Folder {
|
||||
AppDefaults.addWebFeedFolderName = folder.nameForDisplay
|
||||
AppDefaults.shared.addWebFeedFolderName = folder.nameForDisplay
|
||||
} else {
|
||||
AppDefaults.addWebFeedFolderName = nil
|
||||
AppDefaults.shared.addWebFeedFolderName = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ struct CacheCleaner {
|
||||
|
||||
static func purgeIfNecessary() {
|
||||
|
||||
guard let flushDate = AppDefaults.lastImageCacheFlushDate else {
|
||||
AppDefaults.lastImageCacheFlushDate = Date()
|
||||
guard let flushDate = AppDefaults.shared.lastImageCacheFlushDate else {
|
||||
AppDefaults.shared.lastImageCacheFlushDate = Date()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ struct CacheCleaner {
|
||||
}
|
||||
}
|
||||
|
||||
AppDefaults.lastImageCacheFlushDate = Date()
|
||||
AppDefaults.shared.lastImageCacheFlushDate = Date()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class AccountRefreshTimer {
|
||||
func fireOldTimer() {
|
||||
if let timer = internalTimer {
|
||||
if timer.fireDate < Date() {
|
||||
if AppDefaults.refreshInterval != .manually {
|
||||
if AppDefaults.shared.refreshInterval != .manually {
|
||||
timedRefresh(nil)
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ class AccountRefreshTimer {
|
||||
return
|
||||
}
|
||||
|
||||
let refreshInterval = AppDefaults.refreshInterval
|
||||
let refreshInterval = AppDefaults.shared.refreshInterval
|
||||
if refreshInterval == .manually {
|
||||
invalidate()
|
||||
return
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum RefreshInterval: Int, CaseIterable {
|
||||
enum RefreshInterval: Int, CaseIterable, Identifiable {
|
||||
case manually = 1
|
||||
case every10Minutes = 2
|
||||
case every30Minutes = 3
|
||||
@@ -36,6 +36,8 @@ enum RefreshInterval: Int, CaseIterable {
|
||||
}
|
||||
}
|
||||
|
||||
var id: String { description() }
|
||||
|
||||
func description() -> String {
|
||||
switch self {
|
||||
case .manually:
|
||||
|
||||
Reference in New Issue
Block a user