Merge branch 'swiftui' into swiftui-color-palette

* swiftui:
  Register AppDefaults.  Issue #2190
  Removed obsolete AppDefaults values
  Revert to using List for timeline and use infinite scrolling technique to speed up timeline loads
  Add action sheet for adding feed resources
  Stub out Article code
  Delete dead code
  Fix bad merge where we were missing a file reference

# Conflicts:
#	NetNewsWire.xcodeproj/project.pbxproj
This commit is contained in:
Rizwan Mohamed Ibrahim 2020-07-03 13:45:03 +05:30
commit 7cc71eac95
No known key found for this signature in database
GPG Key ID: D5BEE468D448BCC5
15 changed files with 200 additions and 146 deletions

View File

@ -26,13 +26,6 @@ enum UserInterfaceColorPalette: Int, CustomStringConvertible, CaseIterable {
} }
} }
enum FontSize: Int {
case small = 0
case medium = 1
case large = 2
case veryLarge = 3
}
final class AppDefaults: ObservableObject { final class AppDefaults: ObservableObject {
#if os(macOS) #if os(macOS)
@ -62,26 +55,21 @@ final class AppDefaults: ObservableObject {
static let addWebFeedAccountID = "addWebFeedAccountID" static let addWebFeedAccountID = "addWebFeedAccountID"
static let addWebFeedFolderName = "addWebFeedFolderName" static let addWebFeedFolderName = "addWebFeedFolderName"
static let addFolderAccountID = "addFolderAccountID" static let addFolderAccountID = "addFolderAccountID"
static let userInterfaceColorPalette = "userInterfaceColorPalette"
static let timelineSortDirection = "timelineSortDirection" static let timelineSortDirection = "timelineSortDirection"
static let timelineGroupByFeed = "timelineGroupByFeed"
static let timelineIconDimensions = "timelineIconDimensions"
static let timelineNumberOfLines = "timelineNumberOfLines"
// iOS Defaults // iOS Defaults
static let userInterfaceColorPalette = "userInterfaceColorPalette"
static let timelineGroupByFeed = "timelineGroupByFeed"
static let refreshClearsReadArticles = "refreshClearsReadArticles" static let refreshClearsReadArticles = "refreshClearsReadArticles"
static let timelineNumberOfLines = "timelineNumberOfLines"
static let timelineIconSize = "timelineIconSize"
static let articleFullscreenAvailable = "articleFullscreenAvailable" static let articleFullscreenAvailable = "articleFullscreenAvailable"
static let articleFullscreenEnabled = "articleFullscreenEnabled" static let articleFullscreenEnabled = "articleFullscreenEnabled"
static let confirmMarkAllAsRead = "confirmMarkAllAsRead" static let confirmMarkAllAsRead = "confirmMarkAllAsRead"
// macOS Defaults // macOS Defaults
static let windowState = "windowState"
static let sidebarFontSize = "sidebarFontSize"
static let timelineFontSize = "timelineFontSize"
static let detailFontSize = "detailFontSize"
static let openInBrowserInBackground = "openInBrowserInBackground" static let openInBrowserInBackground = "openInBrowserInBackground"
static let importOPMLAccountID = "importOPMLAccountID"
static let exportOPMLAccountID = "exportOPMLAccountID"
static let defaultBrowserID = "defaultBrowserID" static let defaultBrowserID = "defaultBrowserID"
static let checkForUpdatesAutomatically = "checkForUpdatesAutomatically" static let checkForUpdatesAutomatically = "checkForUpdatesAutomatically"
static let downloadTestBuilds = "downloadTestBuild" static let downloadTestBuilds = "downloadTestBuild"
@ -99,9 +87,6 @@ final class AppDefaults: ObservableObject {
} }
private static let smallestFontSizeRawValue = FontSize.small.rawValue
private static let largestFontSizeRawValue = FontSize.veryLarge.rawValue
// MARK: Development Builds // MARK: Development Builds
let isDeveloperBuild: Bool = { let isDeveloperBuild: Bool = {
if let dev = Bundle.main.object(forInfoDictionaryKey: "DeveloperEntitlements") as? String, dev == "-dev" { if let dev = Bundle.main.object(forInfoDictionaryKey: "DeveloperEntitlements") as? String, dev == "-dev" {
@ -193,7 +178,7 @@ final class AppDefaults: ObservableObject {
} }
} }
@AppStorage(wrappedValue: 40.0, Key.timelineIconSize, store: store) var timelineIconSize: Double { @AppStorage(wrappedValue: 40.0, Key.timelineIconDimensions, store: store) var timelineIconDimensions: Double {
didSet { didSet {
objectWillChange.send() objectWillChange.send()
} }
@ -220,64 +205,12 @@ final class AppDefaults: ObservableObject {
} }
// MARK: Window State // MARK: Window State
var windowState: [AnyHashable : Any]? {
get {
return AppDefaults.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 { @AppStorage(wrappedValue: false, Key.openInBrowserInBackground, store: store) var openInBrowserInBackground: Bool {
didSet { didSet {
objectWillChange.send() objectWillChange.send()
} }
} }
var sidebarFontSize: FontSize {
get {
return fontSize(for: Key.sidebarFontSize)
}
set {
AppDefaults.store.set(newValue.rawValue, forKey: Key.sidebarFontSize)
objectWillChange.send()
}
}
var timelineFontSize: FontSize {
get {
return fontSize(for: Key.timelineFontSize)
}
set {
AppDefaults.store.set(newValue.rawValue, forKey: Key.timelineFontSize)
objectWillChange.send()
}
}
var detailFontSize: FontSize {
get {
return fontSize(for: Key.detailFontSize)
}
set {
AppDefaults.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? { @AppStorage(Key.defaultBrowserID, store: store) var defaultBrowserID: String? {
didSet { didSet {
objectWillChange.send() objectWillChange.send()
@ -334,6 +267,21 @@ final class AppDefaults: ObservableObject {
} }
} }
static func registerDefaults() {
let defaults: [String : Any] = [Key.userInterfaceColorPalette: UserInterfaceColorPalette.automatic.rawValue,
Key.timelineGroupByFeed: false,
Key.refreshClearsReadArticles: false,
Key.timelineNumberOfLines: 2,
Key.timelineIconDimensions: 40,
Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue,
Key.articleFullscreenAvailable: false,
Key.articleFullscreenEnabled: false,
Key.confirmMarkAllAsRead: true,
"NSScrollViewShouldScrollUnderTitlebar": false,
Key.refreshInterval: RefreshInterval.everyHour.rawValue]
AppDefaults.store.register(defaults: defaults)
}
} }
extension AppDefaults { extension AppDefaults {
@ -346,8 +294,4 @@ extension AppDefaults {
return true return true
} }
func fontSize(for key: String) -> FontSize {
// Punted till after 1.0.
return .medium
}
} }

View File

@ -0,0 +1,31 @@
//
// ArticleContainerView.swift
// NetNewsWire
//
// Created by Maurice Parker on 7/2/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import SwiftUI
import Articles
struct ArticleContainerView: View {
@EnvironmentObject private var sceneModel: SceneModel
@StateObject private var articleModel = ArticleModel()
var article: Article? = nil
@ViewBuilder var body: some View {
if let article = article {
ArticleView()
.environmentObject(articleModel)
.onAppear {
sceneModel.articleModel = articleModel
articleModel.delegate = sceneModel
}
} else {
EmptyView()
}
}
}

View File

@ -0,0 +1,25 @@
//
// ArticleModel.swift
// NetNewsWire
//
// Created by Maurice Parker on 7/2/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
import Foundation
import RSCore
import Account
import Articles
protocol ArticleModelDelegate: class {
func timelineRequestedWebFeedSelection(_: TimelineModel, webFeed: WebFeed)
}
class ArticleModel: ObservableObject {
weak var delegate: ArticleModelDelegate?
}

View File

@ -0,0 +1,21 @@
//
// ArticleView.swift
// NetNewsWire
//
// Created by Maurice Parker on 7/2/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import SwiftUI
struct ArticleView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
struct ArticleView_Previews: PreviewProvider {
static var previews: some View {
ArticleView()
}
}

View File

@ -13,6 +13,7 @@ final class SceneModel: ObservableObject {
var sidebarModel: SidebarModel? var sidebarModel: SidebarModel?
var timelineModel: TimelineModel? var timelineModel: TimelineModel?
var articleModel: ArticleModel?
} }
@ -35,3 +36,10 @@ extension SceneModel: TimelineModelDelegate {
} }
} }
// MARK: ArticleModelDelegate
extension SceneModel: ArticleModelDelegate {
}

View File

@ -30,38 +30,6 @@ struct CompactSidebarContainerView: View {
},alignment: .bottom) },alignment: .bottom)
} }
var compactToolBar: some View {
VStack {
Divider()
HStack(alignment: .center) {
Button(action: {
showSettings = true
}, label: {
Image(systemName: "gear")
.font(.title3)
.foregroundColor(.accentColor)
}).help("Settings")
Spacer()
Text("Last updated")
.font(.caption)
.foregroundColor(.secondary)
Spacer()
Button(action: {}, label: {
Image(systemName: "plus")
.font(.title3)
.foregroundColor(.accentColor)
}).help("Add")
}
.padding(.horizontal, 16)
.padding(.bottom, 12)
.padding(.top, 4)
}
.background(VisualEffectBlur(blurStyle: .systemChromeMaterial).edgesIgnoringSafeArea(.bottom))
}
} }
struct CompactSidebarContainerView_Previews: PreviewProvider { struct CompactSidebarContainerView_Previews: PreviewProvider {

View File

@ -12,6 +12,11 @@ struct SidebarToolbar: View {
@EnvironmentObject private var appSettings: AppDefaults @EnvironmentObject private var appSettings: AppDefaults
@State private var showSettings: Bool = false @State private var showSettings: Bool = false
@State private var showAddSheet: Bool = false
var addActionSheetButtons = [
Button(action: {}, label: { Text("Add Feed") })
]
var body: some View { var body: some View {
VStack { VStack {
@ -29,11 +34,23 @@ struct SidebarToolbar: View {
.font(.caption) .font(.caption)
.foregroundColor(.secondary) .foregroundColor(.secondary)
Spacer() Spacer()
Button(action: {}, label: { Button(action: {
showAddSheet = true
}, label: {
Image(systemName: "plus") Image(systemName: "plus")
.font(.title3) .font(.title3)
.foregroundColor(.accentColor) .foregroundColor(.accentColor)
}).help("Add") })
.help("Add")
.actionSheet(isPresented: $showAddSheet) {
ActionSheet(title: Text("Add"), buttons: [
.cancel(),
.default(Text("Add Web Feed")),
.default(Text("Add Twitter Feed")),
.default(Text("Add Reddit Feed")),
.default(Text("Add Folder"))
])
}
} }
.padding(.horizontal, 16) .padding(.horizontal, 16)
.padding(.bottom, 12) .padding(.bottom, 12)

View File

@ -21,7 +21,7 @@ struct TimelineItemView: View {
TimelineItemStatusView(status: timelineItem.status) TimelineItemStatusView(status: timelineItem.status)
if let image = articleIconImageLoader.image { if let image = articleIconImageLoader.image {
IconImageView(iconImage: image) IconImageView(iconImage: image)
.frame(width: CGFloat(defaults.timelineIconSize), height: CGFloat(defaults.timelineIconSize), alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) .frame(width: CGFloat(defaults.timelineIconDimensions), height: CGFloat(defaults.timelineIconDimensions), alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
} }
VStack { VStack {
Text(verbatim: timelineItem.article.title ?? "N/A") Text(verbatim: timelineItem.article.title ?? "N/A")
@ -45,7 +45,6 @@ struct TimelineItemView: View {
} }
} }
} }
Divider()
} }
.onAppear { .onAppear {
articleIconImageLoader.loadImage(for: timelineItem.article) articleIconImageLoader.loadImage(for: timelineItem.article)

View File

@ -55,6 +55,14 @@ class TimelineModel: ObservableObject {
fetchAndReplaceArticlesAsync() fetchAndReplaceArticlesAsync()
} }
// TODO: Replace this with ScrollViewReader if we have to keep it
func loadMoreTimelineItemsIfNecessary(_ timelineItem: TimelineItem) {
let thresholdIndex = timelineItems.index(timelineItems.endIndex, offsetBy: -10)
if timelineItems.firstIndex(where: { $0.id == timelineItem.id }) == thresholdIndex {
nextBatch()
}
}
} }
// MARK: Private // MARK: Private
@ -112,11 +120,18 @@ private extension TimelineModel {
func replaceArticles(with unsortedArticles: Set<Article>) { func replaceArticles(with unsortedArticles: Set<Article>) {
articles = Array(unsortedArticles).sortedByDate(sortDirection ? .orderedDescending : .orderedAscending, groupByFeed: groupByFeed) articles = Array(unsortedArticles).sortedByDate(sortDirection ? .orderedDescending : .orderedAscending, groupByFeed: groupByFeed)
timelineItems = articles.map { TimelineItem(article: $0) } timelineItems = [TimelineItem]()
nextBatch()
// TODO: Update unread counts and other item done in didSet on AppKit // TODO: Update unread counts and other item done in didSet on AppKit
} }
func nextBatch() {
let rangeEndIndex = timelineItems.endIndex + 50 > articles.endIndex ? articles.endIndex : timelineItems.endIndex + 50
let range = timelineItems.endIndex..<rangeEndIndex
for i in range {
timelineItems.append(TimelineItem(article: articles[i]))
}
}
// MARK: - Notifications // MARK: - Notifications

View File

@ -13,12 +13,11 @@ struct TimelineView: View {
@EnvironmentObject private var timelineModel: TimelineModel @EnvironmentObject private var timelineModel: TimelineModel
var body: some View { var body: some View {
ScrollView { List(timelineModel.timelineItems) { timelineItem in
LazyVStack() { TimelineItemView(timelineItem: timelineItem)
ForEach(timelineModel.timelineItems) { timelineItem in .onAppear {
TimelineItemView(timelineItem: timelineItem) timelineModel.loadMoreTimelineItemsIfNecessary(timelineItem)
} }
}
} }
} }

View File

@ -71,7 +71,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
} }
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//AppDefaults.registerDefaults() AppDefaults.registerDefaults()
let isFirstRun = AppDefaults.shared.isFirstRun() let isFirstRun = AppDefaults.shared.isFirstRun()
if isFirstRun { if isFirstRun {

View File

@ -33,8 +33,8 @@ struct TimelineLayoutView: View {
} }
var iconSize: some View { var iconSize: some View {
Slider(value: $appSettings.timelineIconSize, in: 20...60, step: 10, minimumValueLabel: Text("Small"), maximumValueLabel: Text("Large"), label: { Slider(value: $appSettings.timelineIconDimensions, in: 20...60, step: 10, minimumValueLabel: Text("Small"), maximumValueLabel: Text("Large"), label: {
Text(String(appSettings.timelineIconSize)) Text(String(appSettings.timelineIconDimensions))
}) })
} }
@ -54,7 +54,7 @@ struct TimelineLayoutView: View {
Image(systemName: "paperplane.circle") Image(systemName: "paperplane.circle")
.resizable() .resizable()
.frame(width: CGFloat(appSettings.timelineIconSize), height: CGFloat(appSettings.timelineIconSize), alignment: .top) .frame(width: CGFloat(appSettings.timelineIconDimensions), height: CGFloat(appSettings.timelineIconDimensions), alignment: .top)
.foregroundColor(.accentColor) .foregroundColor(.accentColor)
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {

View File

@ -133,7 +133,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
} }
#endif #endif
//AppDefaults.registerDefaults() AppDefaults.registerDefaults()
let isFirstRun = AppDefaults.shared.isFirstRun() let isFirstRun = AppDefaults.shared.isFirstRun()
if isFirstRun { if isFirstRun {
os_log(.debug, log: log, "Is first run.") os_log(.debug, log: log, "Is first run.")

View File

@ -79,6 +79,7 @@
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */; }; 511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */; };
511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511D4410231FC02D00FB1562 /* KeyboardManager.swift */; }; 511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511D4410231FC02D00FB1562 /* KeyboardManager.swift */; };
51236339236915B100951F16 /* RoundedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512363372369155100951F16 /* RoundedProgressView.swift */; }; 51236339236915B100951F16 /* RoundedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512363372369155100951F16 /* RoundedProgressView.swift */; };
5125E6CA24AE461D002A7562 /* TimelineLayoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */; };
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */; }; 5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */; };
5127B238222B4849006D641D /* DetailKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */; }; 5127B238222B4849006D641D /* DetailKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */; };
5127B23A222B4849006D641D /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; }; 5127B23A222B4849006D641D /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; };
@ -264,6 +265,12 @@
51A1699D235E10D700EB091F /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16993235E10D600EB091F /* SettingsViewController.swift */; }; 51A1699D235E10D700EB091F /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16993235E10D600EB091F /* SettingsViewController.swift */; };
51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16995235E10D600EB091F /* AboutViewController.swift */; }; 51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16995235E10D600EB091F /* AboutViewController.swift */; };
51A169A0235E10D700EB091F /* FeedbinAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */; }; 51A169A0235E10D700EB091F /* FeedbinAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */; };
51A5769624AE617200078888 /* ArticleContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A5769524AE617200078888 /* ArticleContainerView.swift */; };
51A5769724AE617200078888 /* ArticleContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A5769524AE617200078888 /* ArticleContainerView.swift */; };
51A576BB24AE621800078888 /* ArticleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A576BA24AE621800078888 /* ArticleModel.swift */; };
51A576BC24AE621800078888 /* ArticleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A576BA24AE621800078888 /* ArticleModel.swift */; };
51A576BE24AE637400078888 /* ArticleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A576BD24AE637400078888 /* ArticleView.swift */; };
51A576BF24AE637400078888 /* ArticleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A576BD24AE637400078888 /* ArticleView.swift */; };
51A66685238075AE00CB272D /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; }; 51A66685238075AE00CB272D /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
51A9A5E12380C4FE0033AADF /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45255226507D200C03939 /* AppDefaults.swift */; }; 51A9A5E12380C4FE0033AADF /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45255226507D200C03939 /* AppDefaults.swift */; };
51A9A5E42380C8880033AADF /* ShareFolderPickerAccountCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51A9A5E32380C8870033AADF /* ShareFolderPickerAccountCell.xib */; }; 51A9A5E42380C8880033AADF /* ShareFolderPickerAccountCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51A9A5E32380C8870033AADF /* ShareFolderPickerAccountCell.xib */; };
@ -1866,6 +1873,9 @@
51A16993235E10D600EB091F /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; }; 51A16993235E10D600EB091F /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
51A16995235E10D600EB091F /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; }; 51A16995235E10D600EB091F /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbinAccountViewController.swift; sourceTree = "<group>"; }; 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbinAccountViewController.swift; sourceTree = "<group>"; };
51A5769524AE617200078888 /* ArticleContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleContainerView.swift; sourceTree = "<group>"; };
51A576BA24AE621800078888 /* ArticleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleModel.swift; sourceTree = "<group>"; };
51A576BD24AE637400078888 /* ArticleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleView.swift; sourceTree = "<group>"; };
51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedDefaultContainer.swift; sourceTree = "<group>"; }; 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedDefaultContainer.swift; sourceTree = "<group>"; };
51A9A5E32380C8870033AADF /* ShareFolderPickerAccountCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareFolderPickerAccountCell.xib; sourceTree = "<group>"; }; 51A9A5E32380C8870033AADF /* ShareFolderPickerAccountCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareFolderPickerAccountCell.xib; sourceTree = "<group>"; };
51A9A5E52380C8B20033AADF /* ShareFolderPickerFolderCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareFolderPickerFolderCell.xib; sourceTree = "<group>"; }; 51A9A5E52380C8B20033AADF /* ShareFolderPickerFolderCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareFolderPickerFolderCell.xib; sourceTree = "<group>"; };
@ -2674,6 +2684,16 @@
path = Activity; path = Activity;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
51A576B924AE617B00078888 /* Article */ = {
isa = PBXGroup;
children = (
51A5769524AE617200078888 /* ArticleContainerView.swift */,
51A576BA24AE621800078888 /* ArticleModel.swift */,
51A576BD24AE637400078888 /* ArticleView.swift */,
);
path = Article;
sourceTree = "<group>";
};
51B5C85A23F22A7A00032075 /* CommonExtension */ = { 51B5C85A23F22A7A00032075 /* CommonExtension */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -2732,6 +2752,7 @@
51E499D724A912C200B667CB /* SceneModel.swift */, 51E499D724A912C200B667CB /* SceneModel.swift */,
51E49A0224A91FF600B667CB /* SceneNavigationView.swift */, 51E49A0224A91FF600B667CB /* SceneNavigationView.swift */,
51C0513824A77DF800194D5E /* Assets.xcassets */, 51C0513824A77DF800194D5E /* Assets.xcassets */,
51A576B924AE617B00078888 /* Article */,
51919FB124AAB95300541E64 /* Images */, 51919FB124AAB95300541E64 /* Images */,
514E6BFD24AD252400AC6F6E /* Previews */, 514E6BFD24AD252400AC6F6E /* Previews */,
51E499FB24A9135A00B667CB /* Sidebar */, 51E499FB24A9135A00B667CB /* Sidebar */,
@ -3928,46 +3949,46 @@
TargetAttributes = { TargetAttributes = {
51314636235A7BBE00387FDC = { 51314636235A7BBE00387FDC = {
CreatedOnToolsVersion = 11.2; CreatedOnToolsVersion = 11.2;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
LastSwiftMigration = 1120; LastSwiftMigration = 1120;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
513C5CE5232571C2003D4054 = { 513C5CE5232571C2003D4054 = {
CreatedOnToolsVersion = 11.0; CreatedOnToolsVersion = 11.0;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
518B2ED12351B3DD00400001 = { 518B2ED12351B3DD00400001 = {
CreatedOnToolsVersion = 11.2; CreatedOnToolsVersion = 11.2;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
TestTargetID = 840D617B2029031C009BC708; TestTargetID = 840D617B2029031C009BC708;
}; };
51C0513C24A77DF800194D5E = { 51C0513C24A77DF800194D5E = {
CreatedOnToolsVersion = 12.0; CreatedOnToolsVersion = 12.0;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
51C0514324A77DF800194D5E = { 51C0514324A77DF800194D5E = {
CreatedOnToolsVersion = 12.0; CreatedOnToolsVersion = 12.0;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
6581C73220CED60000F4AD34 = { 6581C73220CED60000F4AD34 = {
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
65ED3FA2235DEF6C0081F399 = { 65ED3FA2235DEF6C0081F399 = {
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
65ED4090235DEF770081F399 = { 65ED4090235DEF770081F399 = {
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
}; };
840D617B2029031C009BC708 = { 840D617B2029031C009BC708 = {
CreatedOnToolsVersion = 9.3; CreatedOnToolsVersion = 9.3;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
SystemCapabilities = { SystemCapabilities = {
com.apple.BackgroundModes = { com.apple.BackgroundModes = {
@ -3977,7 +3998,7 @@
}; };
849C645F1ED37A5D003D8FC0 = { 849C645F1ED37A5D003D8FC0 = {
CreatedOnToolsVersion = 8.2.1; CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
SystemCapabilities = { SystemCapabilities = {
com.apple.HardenedRuntime = { com.apple.HardenedRuntime = {
@ -3987,7 +4008,7 @@
}; };
849C64701ED37A5D003D8FC0 = { 849C64701ED37A5D003D8FC0 = {
CreatedOnToolsVersion = 8.2.1; CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = FQLBNX3GP7; DevelopmentTeam = SHJK2V3AJG;
ProvisioningStyle = Automatic; ProvisioningStyle = Automatic;
TestTargetID = 849C645F1ED37A5D003D8FC0; TestTargetID = 849C645F1ED37A5D003D8FC0;
}; };
@ -4791,11 +4812,13 @@
51E4995424A8734D00B667CB /* ExtensionPointIdentifer.swift in Sources */, 51E4995424A8734D00B667CB /* ExtensionPointIdentifer.swift in Sources */,
51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */, 51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */,
51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */, 51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */,
51A5769624AE617200078888 /* ArticleContainerView.swift in Sources */,
51E4996B24A8762D00B667CB /* ArticleExtractor.swift in Sources */, 51E4996B24A8762D00B667CB /* ArticleExtractor.swift in Sources */,
51E49A0324A91FF600B667CB /* SceneNavigationView.swift in Sources */, 51E49A0324A91FF600B667CB /* SceneNavigationView.swift in Sources */,
51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */, 51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */,
51E4991D24A8092100B667CB /* NSAttributedString+NetNewsWire.swift in Sources */, 51E4991D24A8092100B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
51E499FD24A9137600B667CB /* SidebarModel.swift in Sources */, 51E499FD24A9137600B667CB /* SidebarModel.swift in Sources */,
51A576BE24AE637400078888 /* ArticleView.swift in Sources */,
51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */, 51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
172199C924AB228900A31D04 /* SettingsView.swift in Sources */, 172199C924AB228900A31D04 /* SettingsView.swift in Sources */,
51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */, 51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */,
@ -4809,17 +4832,18 @@
51E4992624A80AAB00B667CB /* AppAssets.swift in Sources */, 51E4992624A80AAB00B667CB /* AppAssets.swift in Sources */,
514E6C0624AD2B5F00AC6F6E /* Image-Extensions.swift in Sources */, 514E6C0624AD2B5F00AC6F6E /* Image-Extensions.swift in Sources */,
51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */, 51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
65CBAD3624AE02D50006DD91 /* TimelineLayoutView.swift in Sources */, 5125E6CA24AE461D002A7562 /* TimelineLayoutView.swift in Sources */,
51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */, 51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */,
51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */, 51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */,
51E4997124A8764C00B667CB /* ActivityType.swift in Sources */, 51E4997124A8764C00B667CB /* ActivityType.swift in Sources */,
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 /* FeedIconImageLoader.swift in Sources */,
51919FB324AAB97900541E64 /* FeedIconImageLoader.swift in Sources */, 51919FB324AAB97900541E64 /* FeedIconImageLoader.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 */,
51A576BB24AE621800078888 /* ArticleModel.swift in Sources */,
51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */, 51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */,
51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */, 51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */,
51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */, 51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */,
@ -4892,6 +4916,7 @@
51919FB424AAB97900541E64 /* FeedIconImageLoader.swift in Sources */, 51919FB424AAB97900541E64 /* FeedIconImageLoader.swift in Sources */,
51E4994A24A8734C00B667CB /* ExtensionPointManager.swift in Sources */, 51E4994A24A8734C00B667CB /* ExtensionPointManager.swift in Sources */,
514E6C0324AD29A300AC6F6E /* TimelineItemStatusView.swift in Sources */, 514E6C0324AD29A300AC6F6E /* TimelineItemStatusView.swift in Sources */,
51A576BC24AE621800078888 /* ArticleModel.swift in Sources */,
51E4996D24A8762D00B667CB /* ArticleExtractor.swift in Sources */, 51E4996D24A8762D00B667CB /* ArticleExtractor.swift in Sources */,
51E4994024A8713B00B667CB /* AccountRefreshTimer.swift in Sources */, 51E4994024A8713B00B667CB /* AccountRefreshTimer.swift in Sources */,
51E49A0424A91FF600B667CB /* SceneNavigationView.swift in Sources */, 51E49A0424A91FF600B667CB /* SceneNavigationView.swift in Sources */,
@ -4910,6 +4935,7 @@
51E4996E24A8764C00B667CB /* ActivityManager.swift in Sources */, 51E4996E24A8764C00B667CB /* ActivityManager.swift in Sources */,
51E4995A24A873F900B667CB /* ErrorHandler.swift in Sources */, 51E4995A24A873F900B667CB /* ErrorHandler.swift in Sources */,
51E4991F24A8094300B667CB /* RSImage-AppIcons.swift in Sources */, 51E4991F24A8094300B667CB /* RSImage-AppIcons.swift in Sources */,
51A5769724AE617200078888 /* ArticleContainerView.swift in Sources */,
51E4991224A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */, 51E4991224A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */,
51E4993E24A870F900B667CB /* UserNotificationManager.swift in Sources */, 51E4993E24A870F900B667CB /* UserNotificationManager.swift in Sources */,
51E4992E24A8676300B667CB /* FetchRequestQueue.swift in Sources */, 51E4992E24A8676300B667CB /* FetchRequestQueue.swift in Sources */,
@ -4933,6 +4959,7 @@
51E4992D24A8676300B667CB /* FetchRequestOperation.swift in Sources */, 51E4992D24A8676300B667CB /* FetchRequestOperation.swift in Sources */,
51E4992424A8098400B667CB /* SmartFeedPasteboardWriter.swift in Sources */, 51E4992424A8098400B667CB /* SmartFeedPasteboardWriter.swift in Sources */,
51E4991424A808FF00B667CB /* ArticleStringFormatter.swift in Sources */, 51E4991424A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
51A576BF24AE637400078888 /* ArticleView.swift in Sources */,
51E4991024A808DE00B667CB /* SmallIconProvider.swift in Sources */, 51E4991024A808DE00B667CB /* SmallIconProvider.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -45,7 +45,7 @@ final class AppDefaults {
static let timelineGroupByFeed = "timelineGroupByFeed" static let timelineGroupByFeed = "timelineGroupByFeed"
static let refreshClearsReadArticles = "refreshClearsReadArticles" static let refreshClearsReadArticles = "refreshClearsReadArticles"
static let timelineNumberOfLines = "timelineNumberOfLines" static let timelineNumberOfLines = "timelineNumberOfLines"
static let timelineIconSize = "timelineIconSize" static let timelineIconDimension = "timelineIconSize"
static let timelineSortDirection = "timelineSortDirection" static let timelineSortDirection = "timelineSortDirection"
static let articleFullscreenAvailable = "articleFullscreenAvailable" static let articleFullscreenAvailable = "articleFullscreenAvailable"
static let articleFullscreenEnabled = "articleFullscreenEnabled" static let articleFullscreenEnabled = "articleFullscreenEnabled"
@ -202,11 +202,11 @@ final class AppDefaults {
var timelineIconSize: IconSize { var timelineIconSize: IconSize {
get { get {
let rawValue = AppDefaults.store.integer(forKey: Key.timelineIconSize) let rawValue = AppDefaults.store.integer(forKey: Key.timelineIconDimension)
return IconSize(rawValue: rawValue) ?? IconSize.medium return IconSize(rawValue: rawValue) ?? IconSize.medium
} }
set { set {
AppDefaults.store.set(newValue.rawValue, forKey: Key.timelineIconSize) AppDefaults.store.set(newValue.rawValue, forKey: Key.timelineIconDimension)
} }
} }
@ -215,7 +215,7 @@ final class AppDefaults {
Key.timelineGroupByFeed: false, Key.timelineGroupByFeed: false,
Key.refreshClearsReadArticles: false, Key.refreshClearsReadArticles: false,
Key.timelineNumberOfLines: 2, Key.timelineNumberOfLines: 2,
Key.timelineIconSize: IconSize.medium.rawValue, Key.timelineIconDimension: IconSize.medium.rawValue,
Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue, Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue,
Key.articleFullscreenAvailable: false, Key.articleFullscreenAvailable: false,
Key.articleFullscreenEnabled: false, Key.articleFullscreenEnabled: false,