Refactors `AppDefaults` to `AppSettings`

This commit makes some assumptions:

- `AppSettings` is an `ObservableObject` that uses `@AppStorage` where possible, which sets default values.
- Each change to an property triggers an `objectWillChange.send()` call.
- `IconSize` is not used. Instead, it defaults to 40.0 with minimums and maximums of 20.0 and 60.0, controlled via Timeline settings.
This commit is contained in:
Stuart Breckenridge 2020-07-01 21:06:40 +08:00
parent c10207ecaa
commit 0e0f46fa49
7 changed files with 370 additions and 31 deletions

View File

@ -8,23 +8,7 @@
import Foundation import Foundation
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 { struct AppDefaults {

View File

@ -0,0 +1,180 @@
//
// 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")
}
}
}
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 {
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"
}
// 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
func isFirstRun() -> Bool {
if let _ = AppSettings.store.object(forKey: Key.firstRunDate) as? Date {
return false
}
firstRunDate = Date()
return true
}
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
}
}
}

View File

@ -22,6 +22,7 @@ struct SceneNavigationView: View {
#else #else
if horizontalSizeClass == .compact { if horizontalSizeClass == .compact {
CompactSidebarContainerView() CompactSidebarContainerView()
} else { } else {
RegularSidebarContainerView() RegularSidebarContainerView()
} }
@ -46,6 +47,7 @@ struct SceneNavigationView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
#endif #endif
} }
} }
} }

View File

@ -0,0 +1,72 @@
//
// AppSettings.swift
// Multiplatform iOS
//
// Created by Stuart Breckenridge on 1/7/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
enum ColorPalette: 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")
}
}
}
class AppSettings: ObservableObject {
struct Key {
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 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
}()
}

View File

@ -57,6 +57,7 @@ struct SettingsView: View {
@Environment(\.presentationMode) var presentationMode @Environment(\.presentationMode) var presentationMode
@StateObject private var viewModel = SettingsViewModel() @StateObject private var viewModel = SettingsViewModel()
@StateObject private var settings = AppSettings.shared
var body: some View { var body: some View {
NavigationView { NavigationView {
@ -128,11 +129,11 @@ struct SettingsView: View {
var timeline: some View { var timeline: some View {
Section(header: Text("Timeline"), content: { Section(header: Text("Timeline"), content: {
Toggle("Sort Oldest to Newest", isOn: .constant(true)) Toggle("Sort Oldest to Newest", isOn: $settings.timelineSortDirection)
Toggle("Group by Feed", isOn: .constant(true)) Toggle("Group by Feed", isOn: $settings.timelineGroupByFeed)
Toggle("Refresh to Clear Read Articles", isOn: .constant(true)) Toggle("Refresh to Clear Read Articles", isOn: $settings.refreshClearsReadArticles)
NavigationLink( NavigationLink(
destination: EmptyView(), destination: TimelineLayoutView().environmentObject(settings),
label: { label: {
Text("Timeline Layout") Text("Timeline Layout")
}) })

View File

@ -0,0 +1,82 @@
//
// TimelineLayoutView.swift
// Multiplatform iOS
//
// Created by Stuart Breckenridge on 1/7/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import SwiftUI
struct TimelineLayoutView: View {
@EnvironmentObject private var appSettings: AppSettings
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."
var body: some View {
VStack(spacing: 0) {
List {
Section(header: Text("Icon Size"), content: {
iconSize
})
Section(header: Text("Number of Lines"), content: {
numberOfLines
}) }
.listStyle(InsetGroupedListStyle())
Divider()
timelineRowPreview.padding()
Divider()
}
.navigationBarTitle("Timeline Layout")
}
var iconSize: some View {
Slider(value: $appSettings.timelineIconSize, in: 20...60, minimumValueLabel: Text("Small"), maximumValueLabel: Text("Large"), label: {
Text(String(appSettings.timelineIconSize))
})
}
var numberOfLines: some View {
Stepper(value: $appSettings.timelineNumberOfLines, in: 1...5, label: {
Text("Title")
})
}
var timelineRowPreview: some View {
HStack(alignment: .top) {
Image(systemName: "circle.fill")
.resizable()
.frame(width: 10, height: 10, alignment: .top)
.foregroundColor(.accentColor)
Image(systemName: "paperplane.circle")
.resizable()
.frame(width: CGFloat(appSettings.timelineIconSize), height: CGFloat(appSettings.timelineIconSize), alignment: .top)
.foregroundColor(.accentColor)
VStack(alignment: .leading, spacing: 4) {
Text(sampleTitle)
.font(.headline)
.lineLimit(appSettings.timelineNumberOfLines)
HStack {
Text("Feed Name")
.foregroundColor(.secondary)
.font(.footnote)
Spacer()
Text("10:31")
.font(.footnote)
.foregroundColor(.secondary)
}
}
}
}
}
struct TimelineLayout_Previews: PreviewProvider {
static var previews: some View {
TimelineLayoutView()
}
}

View File

@ -18,8 +18,11 @@
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529624AA1CD000D65E66 /* MacPreferencesView.swift */; }; 1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529624AA1CD000D65E66 /* MacPreferencesView.swift */; };
1729529B24AA1FD200D65E66 /* MacSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529A24AA1FD200D65E66 /* MacSearchField.swift */; }; 1729529B24AA1FD200D65E66 /* MacSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529A24AA1FD200D65E66 /* MacSearchField.swift */; };
172952B024AA287100D65E66 /* CompactSidebarContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172952AF24AA287100D65E66 /* CompactSidebarContainerView.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 */; };
179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; }; 179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
179DB3CE822BFCC2D774D9F4 /* 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 */; };
3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; }; 3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; };
3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */; }; 3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */; };
3B826DCC2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */; }; 3B826DCC2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */; };
@ -1701,7 +1704,9 @@
1729529624AA1CD000D65E66 /* MacPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacPreferencesView.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>"; }; 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>"; }; 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>"; };
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.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>"; }; 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountViewController.swift; sourceTree = "<group>"; };
3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsFeedWrangler.xib; sourceTree = "<group>"; }; 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsFeedWrangler.xib; sourceTree = "<group>"; };
3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsFeedWranglerWindowController.swift; sourceTree = "<group>"; }; 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsFeedWranglerWindowController.swift; sourceTree = "<group>"; };
@ -2346,6 +2351,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
172199C824AB228900A31D04 /* SettingsView.swift */, 172199C824AB228900A31D04 /* SettingsView.swift */,
17B223B924AC24A8001E4592 /* Submenus */,
); );
path = Settings; path = Settings;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2378,6 +2384,14 @@
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
17B223B924AC24A8001E4592 /* Submenus */ = {
isa = PBXGroup;
children = (
17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */,
);
path = Submenus;
sourceTree = "<group>";
};
510289CE2451BA1E00426DDF /* Twitter */ = { 510289CE2451BA1E00426DDF /* Twitter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -2690,6 +2704,7 @@
children = ( children = (
51E4992524A80AAB00B667CB /* AppAssets.swift */, 51E4992524A80AAB00B667CB /* AppAssets.swift */,
51E4992824A866F000B667CB /* AppDefaults.swift */, 51E4992824A866F000B667CB /* AppDefaults.swift */,
1776E88D24AC5F8A00E78166 /* AppSettings.swift */,
51E4995824A873F900B667CB /* ErrorHandler.swift */, 51E4995824A873F900B667CB /* ErrorHandler.swift */,
51C0513624A77DF700194D5E /* MainApp.swift */, 51C0513624A77DF700194D5E /* MainApp.swift */,
51E499D724A912C200B667CB /* SceneModel.swift */, 51E499D724A912C200B667CB /* SceneModel.swift */,
@ -3889,46 +3904,46 @@
TargetAttributes = { TargetAttributes = {
51314636235A7BBE00387FDC = { 51314636235A7BBE00387FDC = {
CreatedOnToolsVersion = 11.2; CreatedOnToolsVersion = 11.2;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
LastSwiftMigration = 1120; LastSwiftMigration = 1120;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
513C5CE5232571C2003D4054 = { 513C5CE5232571C2003D4054 = {
CreatedOnToolsVersion = 11.0; CreatedOnToolsVersion = 11.0;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
518B2ED12351B3DD00400001 = { 518B2ED12351B3DD00400001 = {
CreatedOnToolsVersion = 11.2; CreatedOnToolsVersion = 11.2;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
TestTargetID = 840D617B2029031C009BC708; TestTargetID = 840D617B2029031C009BC708;
}; };
51C0513C24A77DF800194D5E = { 51C0513C24A77DF800194D5E = {
CreatedOnToolsVersion = 12.0; CreatedOnToolsVersion = 12.0;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
51C0514324A77DF800194D5E = { 51C0514324A77DF800194D5E = {
CreatedOnToolsVersion = 12.0; CreatedOnToolsVersion = 12.0;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
6581C73220CED60000F4AD34 = { 6581C73220CED60000F4AD34 = {
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
65ED3FA2235DEF6C0081F399 = { 65ED3FA2235DEF6C0081F399 = {
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
65ED4090235DEF770081F399 = { 65ED4090235DEF770081F399 = {
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
840D617B2029031C009BC708 = { 840D617B2029031C009BC708 = {
CreatedOnToolsVersion = 9.3; CreatedOnToolsVersion = 9.3;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
SystemCapabilities = { SystemCapabilities = {
com.apple.BackgroundModes = { com.apple.BackgroundModes = {
@ -3938,7 +3953,7 @@
}; };
849C645F1ED37A5D003D8FC0 = { 849C645F1ED37A5D003D8FC0 = {
CreatedOnToolsVersion = 8.2.1; CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
SystemCapabilities = { SystemCapabilities = {
com.apple.HardenedRuntime = { com.apple.HardenedRuntime = {
@ -3948,7 +3963,7 @@
}; };
849C64701ED37A5D003D8FC0 = { 849C64701ED37A5D003D8FC0 = {
CreatedOnToolsVersion = 8.2.1; CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = SHJK2V3AJG; DevelopmentTeam = FQLBNX3GP7;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
TestTargetID = 849C645F1ED37A5D003D8FC0; TestTargetID = 849C645F1ED37A5D003D8FC0;
}; };
@ -4772,6 +4787,7 @@
51E4991E24A8094300B667CB /* RSImage-AppIcons.swift in Sources */, 51E4991E24A8094300B667CB /* RSImage-AppIcons.swift in Sources */,
51E499D824A912C200B667CB /* SceneModel.swift in Sources */, 51E499D824A912C200B667CB /* SceneModel.swift in Sources */,
51919FB324AAB97900541E64 /* FeedImageLoader.swift in Sources */, 51919FB324AAB97900541E64 /* FeedImageLoader.swift in Sources */,
17B223DC24AC24D2001E4592 /* TimelineLayoutView.swift in Sources */,
51E4991324A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */, 51E4991324A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */,
51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */, 51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */,
51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */, 51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */,
@ -4791,6 +4807,7 @@
51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */, 51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
51919FEE24AB85E400541E64 /* TimelineContainerView.swift in Sources */, 51919FEE24AB85E400541E64 /* TimelineContainerView.swift in Sources */,
51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */, 51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */,
1776E88E24AC5F8A00E78166 /* AppSettings.swift in Sources */,
51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */, 51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -4832,6 +4849,7 @@
51E49A0124A91FC100B667CB /* RegularSidebarContainerView.swift in Sources */, 51E49A0124A91FC100B667CB /* RegularSidebarContainerView.swift in Sources */,
51E4995B24A875D500B667CB /* ArticlePasteboardWriter.swift in Sources */, 51E4995B24A875D500B667CB /* ArticlePasteboardWriter.swift in Sources */,
51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */, 51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */,
1776E88F24AC5F8A00E78166 /* AppSettings.swift in Sources */,
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */, 1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */,
51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */, 51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */, 1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */,