Make multiplatform compile shared app resources
This commit is contained in:
parent
7ceaa305e7
commit
67c0e00957
|
@ -125,6 +125,10 @@ struct AppAssets {
|
|||
return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!)
|
||||
}()
|
||||
|
||||
static var smartFeedImage: RSImage = {
|
||||
return RSImage(named: NSImage.smartBadgeTemplateName)!
|
||||
}()
|
||||
|
||||
static var starredFeedImage: IconImage = {
|
||||
return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!)
|
||||
}()
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// AppAssets.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 6/27/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import RSCore
|
||||
import Account
|
||||
|
||||
struct AppAssets {
|
||||
|
||||
static var accountLocalMacImage: RSImage! = {
|
||||
return RSImage(named: "accountLocalMac")
|
||||
}()
|
||||
|
||||
static var accountLocalPadImage: RSImage = {
|
||||
return RSImage(named: "accountLocalPad")!
|
||||
}()
|
||||
|
||||
static var accountLocalPhoneImage: RSImage = {
|
||||
return RSImage(named: "accountLocalPhone")!
|
||||
}()
|
||||
|
||||
static var accountCloudKitImage: RSImage = {
|
||||
return RSImage(named: "accountCloudKit")!
|
||||
}()
|
||||
|
||||
static var accountFeedbinImage: RSImage = {
|
||||
return RSImage(named: "accountFeedbin")!
|
||||
}()
|
||||
|
||||
static var accountFeedlyImage: RSImage = {
|
||||
return RSImage(named: "accountFeedly")!
|
||||
}()
|
||||
|
||||
static var accountFeedWranglerImage: RSImage = {
|
||||
return RSImage(named: "accountFeedWrangler")!
|
||||
}()
|
||||
|
||||
static var accountFreshRSSImage: RSImage = {
|
||||
return RSImage(named: "accountFreshRSS")!
|
||||
}()
|
||||
|
||||
static var accountNewsBlurImage: RSImage = {
|
||||
return RSImage(named: "accountNewsBlur")!
|
||||
}()
|
||||
|
||||
static var extensionPointMarsEdit: RSImage = {
|
||||
return RSImage(named: "extensionPointMarsEdit")!
|
||||
}()
|
||||
|
||||
static var extensionPointMicroblog: RSImage = {
|
||||
return RSImage(named: "extensionPointMicroblog")!
|
||||
}()
|
||||
|
||||
static var extensionPointReddit: RSImage = {
|
||||
return RSImage(named: "extensionPointReddit")!
|
||||
}()
|
||||
|
||||
static var extensionPointTwitter: RSImage = {
|
||||
return RSImage(named: "extensionPointTwitter")!
|
||||
}()
|
||||
|
||||
static var faviconTemplateImage: RSImage = {
|
||||
return RSImage(named: "faviconTemplateImage")!
|
||||
}()
|
||||
|
||||
static var masterFolderImage: IconImage = {
|
||||
#if os(macOS)
|
||||
return IconImage(NSImage(systemSymbolName: "folder.fill", accessibilityDescription: nil)!)
|
||||
#endif
|
||||
#if os(iOS)
|
||||
return IconImage(UIImage(systemName: "folder.fill")!)
|
||||
#endif
|
||||
}()
|
||||
|
||||
static var searchFeedImage: IconImage = {
|
||||
#if os(macOS)
|
||||
return IconImage(NSImage(systemSymbolName: "magnifyingglass", accessibilityDescription: nil)!)
|
||||
#endif
|
||||
#if os(iOS)
|
||||
return IconImage(UIImage(systemName: "magnifyingglass")!)
|
||||
#endif
|
||||
}()
|
||||
|
||||
static var smartFeedImage: RSImage = {
|
||||
#if os(macOS)
|
||||
return NSImage(systemSymbolName: "gear", accessibilityDescription: nil)!
|
||||
#endif
|
||||
#if os(iOS)
|
||||
return UIImage(systemName: "gear")!
|
||||
#endif
|
||||
}()
|
||||
|
||||
static var starredFeedImage: IconImage = {
|
||||
#if os(macOS)
|
||||
return IconImage(NSImage(systemSymbolName: "star.fill", accessibilityDescription: nil)!)
|
||||
#endif
|
||||
#if os(iOS)
|
||||
return IconImage(UIImage(systemName: "star.fill")!)
|
||||
#endif
|
||||
}()
|
||||
|
||||
static var todayFeedImage: IconImage = {
|
||||
#if os(macOS)
|
||||
return IconImage(NSImage(systemSymbolName: "sun.max.fill", accessibilityDescription: nil)!)
|
||||
#endif
|
||||
#if os(iOS)
|
||||
return IconImage(UIImage(systemName: "sun.max.fill")!)
|
||||
#endif
|
||||
}()
|
||||
|
||||
static var unreadFeedImage: IconImage = {
|
||||
#if os(macOS)
|
||||
return IconImage(NSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: nil)!)
|
||||
#endif
|
||||
#if os(iOS)
|
||||
return IconImage(UIImage(systemName: "largecircle.fill.circle")!)
|
||||
#endif
|
||||
}()
|
||||
|
||||
static func image(for accountType: AccountType) -> RSImage? {
|
||||
switch accountType {
|
||||
case .onMyMac:
|
||||
#if os(macOS)
|
||||
return AppAssets.accountLocalMacImage
|
||||
#endif
|
||||
#if os(iOS)
|
||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
||||
return AppAssets.accountLocalPadImage
|
||||
} else {
|
||||
return AppAssets.accountLocalPhoneImage
|
||||
}
|
||||
#endif
|
||||
case .cloudKit:
|
||||
return AppAssets.accountCloudKitImage
|
||||
case .feedbin:
|
||||
return AppAssets.accountFeedbinImage
|
||||
case .feedly:
|
||||
return AppAssets.accountFeedlyImage
|
||||
case .feedWrangler:
|
||||
return AppAssets.accountFeedWranglerImage
|
||||
case .freshRSS:
|
||||
return AppAssets.accountFreshRSSImage
|
||||
case .newsBlur:
|
||||
return AppAssets.accountNewsBlurImage
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
//
|
||||
// AppDefaults.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 6/28/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
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 {
|
||||
|
||||
#if os(macOS)
|
||||
static var shared: UserDefaults = UserDefaults.standard
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
static var shared: UserDefaults = {
|
||||
let appIdentifierPrefix = Bundle.main.object(forInfoDictionaryKey: "AppIdentifierPrefix") as! String
|
||||
let suiteName = "\(appIdentifierPrefix)group.\(Bundle.main.bundleIdentifier!)"
|
||||
return UserDefaults.init(suiteName: suiteName)!
|
||||
}()
|
||||
#endif
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
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
|
||||
}()
|
||||
|
||||
static var refreshInterval: RefreshInterval {
|
||||
get {
|
||||
let rawValue = UserDefaults.standard.integer(forKey: Key.refreshInterval)
|
||||
return RefreshInterval(rawValue: rawValue) ?? RefreshInterval.everyHour
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue.rawValue, forKey: Key.refreshInterval)
|
||||
}
|
||||
}
|
||||
|
||||
static var hideDockUnreadCount: Bool {
|
||||
return bool(for: Key.hideDockUnreadCount)
|
||||
}
|
||||
|
||||
static var userInterfaceColorPalette: UserInterfaceColorPalette {
|
||||
get {
|
||||
if let result = UserInterfaceColorPalette(rawValue: int(for: Key.userInterfaceColorPalette)) {
|
||||
return result
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
static var addWebFeedFolderName: String? {
|
||||
get {
|
||||
return string(for: Key.addWebFeedFolderName)
|
||||
}
|
||||
set {
|
||||
setString(for: Key.addWebFeedFolderName, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var addFolderAccountID: String? {
|
||||
get {
|
||||
return string(for: Key.addFolderAccountID)
|
||||
}
|
||||
set {
|
||||
setString(for: Key.addFolderAccountID, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var activeExtensionPointIDs: [[AnyHashable : AnyHashable]]? {
|
||||
get {
|
||||
return UserDefaults.standard.object(forKey: Key.activeExtensionPointIDs) as? [[AnyHashable : AnyHashable]]
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Key.activeExtensionPointIDs)
|
||||
}
|
||||
}
|
||||
|
||||
static var lastImageCacheFlushDate: Date? {
|
||||
get {
|
||||
return date(for: Key.lastImageCacheFlushDate)
|
||||
}
|
||||
set {
|
||||
setDate(for: Key.lastImageCacheFlushDate, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
static var lastRefresh: Date? {
|
||||
get {
|
||||
return date(for: Key.lastRefresh)
|
||||
}
|
||||
set {
|
||||
setDate(for: Key.lastRefresh, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var timelineNumberOfLines: Int {
|
||||
get {
|
||||
return int(for: Key.timelineNumberOfLines)
|
||||
}
|
||||
set {
|
||||
setInt(for: Key.timelineNumberOfLines, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
static var timelineIconSize: IconSize {
|
||||
get {
|
||||
let rawValue = AppDefaults.shared.integer(forKey: Key.timelineIconSize)
|
||||
return IconSize(rawValue: rawValue) ?? IconSize.medium
|
||||
}
|
||||
set {
|
||||
AppDefaults.shared.set(newValue.rawValue, forKey: Key.timelineIconSize)
|
||||
}
|
||||
}
|
||||
|
||||
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? {
|
||||
get {
|
||||
return date(for: Key.firstRunDate)
|
||||
}
|
||||
set {
|
||||
setDate(for: Key.firstRunDate, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
return .orderedDescending
|
||||
}
|
||||
|
||||
static func setSortDirection(for key: String, _ value: ComparisonResult) {
|
||||
if value == .orderedAscending {
|
||||
setInt(for: key, ComparisonResult.orderedAscending.rawValue)
|
||||
}
|
||||
else {
|
||||
setInt(for: key, ComparisonResult.orderedDescending.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,33 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.933",
|
||||
"green" : "0.416",
|
||||
"red" : "0.031"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.945",
|
||||
"green" : "0.502",
|
||||
"red" : "0.176"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icloud.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
Binary file not shown.
15
Multiplatform/Shared/Assets.xcassets/accountFeedWrangler.imageset/Contents.json
vendored
Normal file
15
Multiplatform/Shared/Assets.xcassets/accountFeedWrangler.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "outline-512.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountFeedWrangler.imageset/outline-512.png
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountFeedWrangler.imageset/outline-512.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "accountFeedbin.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true,
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountFeedbin.imageset/accountFeedbin.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountFeedbin.imageset/accountFeedbin.pdf
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "accountFeedly.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountFeedly.imageset/accountFeedly.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountFeedly.imageset/accountFeedly.pdf
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "accountFreshRSS.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountFreshRSS.imageset/accountFreshRSS.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountFreshRSS.imageset/accountFreshRSS.pdf
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "localAccountMac.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountLocalMac.imageset/localAccountMac.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountLocalMac.imageset/localAccountMac.pdf
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "localAccountPad.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true,
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountLocalPad.imageset/localAccountPad.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountLocalPad.imageset/localAccountPad.pdf
vendored
Normal file
Binary file not shown.
16
Multiplatform/Shared/Assets.xcassets/accountLocalPhone.imageset/Contents.json
vendored
Normal file
16
Multiplatform/Shared/Assets.xcassets/accountLocalPhone.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "localAccountPhone.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true,
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountLocalPhone.imageset/localAccountPhone.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountLocalPhone.imageset/localAccountPhone.pdf
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "newsblur-512.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/accountNewsBlur.imageset/newsblur-512.png
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/accountNewsBlur.imageset/newsblur-512.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
15
Multiplatform/Shared/Assets.xcassets/extensionPointMarsEdit.imageset/Contents.json
vendored
Normal file
15
Multiplatform/Shared/Assets.xcassets/extensionPointMarsEdit.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "MarsEditOfficial.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointMarsEdit.imageset/MarsEditOfficial.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointMarsEdit.imageset/MarsEditOfficial.pdf
vendored
Normal file
Binary file not shown.
15
Multiplatform/Shared/Assets.xcassets/extensionPointMicroblog.imageset/Contents.json
vendored
Normal file
15
Multiplatform/Shared/Assets.xcassets/extensionPointMicroblog.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "micro-dot-blog.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointMicroblog.imageset/micro-dot-blog.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointMicroblog.imageset/micro-dot-blog.pdf
vendored
Normal file
Binary file not shown.
25
Multiplatform/Shared/Assets.xcassets/extensionPointReddit.imageset/Contents.json
vendored
Normal file
25
Multiplatform/Shared/Assets.xcassets/extensionPointReddit.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "reddit-light.pdf",
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "reddit-dark.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointReddit.imageset/reddit-dark.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointReddit.imageset/reddit-dark.pdf
vendored
Normal file
Binary file not shown.
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointReddit.imageset/reddit-light.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointReddit.imageset/reddit-light.pdf
vendored
Normal file
Binary file not shown.
15
Multiplatform/Shared/Assets.xcassets/extensionPointTwitter.imageset/Contents.json
vendored
Normal file
15
Multiplatform/Shared/Assets.xcassets/extensionPointTwitter.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "twitter.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointTwitter.imageset/twitter.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/extensionPointTwitter.imageset/twitter.pdf
vendored
Normal file
Binary file not shown.
12
Multiplatform/Shared/Assets.xcassets/faviconTemplateImage.imageset/Contents.json
vendored
Normal file
12
Multiplatform/Shared/Assets.xcassets/faviconTemplateImage.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "faviconTemplateImage.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Multiplatform/Shared/Assets.xcassets/faviconTemplateImage.imageset/faviconTemplateImage.pdf
vendored
Normal file
BIN
Multiplatform/Shared/Assets.xcassets/faviconTemplateImage.imageset/faviconTemplateImage.pdf
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// ErrorHandler.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 6/28/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
import os.log
|
||||
|
||||
struct ErrorHandler {
|
||||
|
||||
private static var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
|
||||
|
||||
// public static func present(_ viewController: UIViewController) -> (Error) -> () {
|
||||
// return { [weak viewController] error in
|
||||
// if UIApplication.shared.applicationState == .active {
|
||||
// viewController?.presentError(error)
|
||||
// } else {
|
||||
// ErrorHandler.log(error)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public static func log(_ error: Error) {
|
||||
os_log(.error, log: self.log, "%@", error.localizedDescription)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// NetNewsWire_MultiplatformApp.swift
|
||||
// NetNewsWire.swift
|
||||
// Shared
|
||||
//
|
||||
// Created by Maurice Parker on 6/27/20.
|
||||
|
@ -9,7 +9,15 @@
|
|||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct NetNewsWire_MultiplatformApp: App {
|
||||
struct NetNewsWire: App {
|
||||
|
||||
#if os(macOS)
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
||||
#endif
|
||||
#if os(iOS)
|
||||
@UIApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
||||
#endif
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
|
@ -0,0 +1,390 @@
|
|||
//
|
||||
// AppDelegate.swift
|
||||
// Multiplatform iOS
|
||||
//
|
||||
// Created by Maurice Parker on 6/28/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RSCore
|
||||
import RSWeb
|
||||
import Account
|
||||
import BackgroundTasks
|
||||
import os.log
|
||||
|
||||
var appDelegate: AppDelegate!
|
||||
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, UnreadCountProvider {
|
||||
|
||||
private var bgTaskDispatchQueue = DispatchQueue.init(label: "BGTaskScheduler")
|
||||
|
||||
private var waitBackgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
|
||||
private var syncBackgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
|
||||
|
||||
var syncTimer: ArticleStatusSyncTimer?
|
||||
|
||||
var shuttingDown = false {
|
||||
didSet {
|
||||
if shuttingDown {
|
||||
syncTimer?.shuttingDown = shuttingDown
|
||||
syncTimer?.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
|
||||
|
||||
var userNotificationManager: UserNotificationManager!
|
||||
var faviconDownloader: FaviconDownloader!
|
||||
var imageDownloader: ImageDownloader!
|
||||
var authorAvatarDownloader: AuthorAvatarDownloader!
|
||||
var webFeedIconDownloader: WebFeedIconDownloader!
|
||||
// TODO: Add Extension back in
|
||||
// var extensionContainersFile: ExtensionContainersFile!
|
||||
// var extensionFeedAddRequestFile: ExtensionFeedAddRequestFile!
|
||||
|
||||
var unreadCount = 0 {
|
||||
didSet {
|
||||
if unreadCount != oldValue {
|
||||
postUnreadCountDidChangeNotification()
|
||||
UIApplication.shared.applicationIconBadgeNumber = unreadCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isSyncArticleStatusRunning = false
|
||||
var isWaitingForSyncTasks = false
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
appDelegate = self
|
||||
|
||||
let documentAccountURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let documentAccountsFolder = documentAccountURL.appendingPathComponent("Accounts").absoluteString
|
||||
let documentAccountsFolderPath = String(documentAccountsFolder.suffix(from: documentAccountsFolder.index(documentAccountsFolder.startIndex, offsetBy: 7)))
|
||||
AccountManager.shared = AccountManager(accountsFolder: documentAccountsFolderPath)
|
||||
FeedProviderManager.shared.delegate = ExtensionPointManager.shared
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(accountRefreshDidFinish(_:)), name: .AccountRefreshDidFinish, object: nil)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
AppDefaults.registerDefaults()
|
||||
|
||||
let isFirstRun = AppDefaults.isFirstRun
|
||||
if isFirstRun {
|
||||
os_log("Is first run.", log: log, type: .info)
|
||||
}
|
||||
|
||||
if isFirstRun && !AccountManager.shared.anyAccountHasAtLeastOneFeed() {
|
||||
let localAccount = AccountManager.shared.defaultAccount
|
||||
DefaultFeedsImporter.importDefaultFeeds(account: localAccount)
|
||||
}
|
||||
|
||||
registerBackgroundTasks()
|
||||
CacheCleaner.purgeIfNecessary()
|
||||
initializeDownloaders()
|
||||
initializeHomeScreenQuickActions()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.unreadCount = AccountManager.shared.unreadCount
|
||||
}
|
||||
|
||||
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
|
||||
if settings.authorizationStatus == .authorized {
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.registerForRemoteNotifications()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UNUserNotificationCenter.current().delegate = self
|
||||
userNotificationManager = UserNotificationManager()
|
||||
|
||||
// extensionContainersFile = ExtensionContainersFile()
|
||||
// extensionFeedAddRequestFile = ExtensionFeedAddRequestFile()
|
||||
|
||||
syncTimer = ArticleStatusSyncTimer()
|
||||
|
||||
#if DEBUG
|
||||
syncTimer!.update()
|
||||
#endif
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
self.resumeDatabaseProcessingIfNecessary()
|
||||
AccountManager.shared.receiveRemoteNotification(userInfo: userInfo) {
|
||||
self.suspendApplication()
|
||||
completionHandler(.newData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
shuttingDown = true
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
@objc func unreadCountDidChange(_ note: Notification) {
|
||||
if note.object is AccountManager {
|
||||
unreadCount = AccountManager.shared.unreadCount
|
||||
}
|
||||
}
|
||||
|
||||
@objc func accountRefreshDidFinish(_ note: Notification) {
|
||||
AppDefaults.lastRefresh = Date()
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
|
||||
func resumeDatabaseProcessingIfNecessary() {
|
||||
if AccountManager.shared.isSuspended {
|
||||
AccountManager.shared.resumeAll()
|
||||
os_log("Application processing resumed.", log: self.log, type: .info)
|
||||
}
|
||||
}
|
||||
|
||||
func prepareAccountsForBackground() {
|
||||
// extensionFeedAddRequestFile.suspend()
|
||||
syncTimer?.invalidate()
|
||||
scheduleBackgroundFeedRefresh()
|
||||
syncArticleStatus()
|
||||
waitForSyncTasksToFinish()
|
||||
}
|
||||
|
||||
func prepareAccountsForForeground() {
|
||||
// extensionFeedAddRequestFile.resume()
|
||||
syncTimer?.update()
|
||||
|
||||
if let lastRefresh = AppDefaults.lastRefresh {
|
||||
if Date() > lastRefresh.addingTimeInterval(15 * 60) {
|
||||
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.log)
|
||||
} else {
|
||||
AccountManager.shared.syncArticleStatusAll()
|
||||
}
|
||||
} else {
|
||||
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.log)
|
||||
}
|
||||
}
|
||||
|
||||
func logMessage(_ message: String, type: LogItem.ItemType) {
|
||||
print("logMessage: \(message) - \(type)")
|
||||
|
||||
}
|
||||
|
||||
func logDebugMessage(_ message: String) {
|
||||
logMessage(message, type: .debug)
|
||||
}
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.banner, .badge, .sound])
|
||||
}
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
defer { completionHandler() }
|
||||
|
||||
// TODO: Add back in User Notification handling
|
||||
// if let sceneDelegate = response.targetScene?.delegate as? SceneDelegate {
|
||||
// sceneDelegate.handle(response)
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: App Initialization
|
||||
|
||||
private extension AppDelegate {
|
||||
|
||||
private func initializeDownloaders() {
|
||||
let tempDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
|
||||
let faviconsFolderURL = tempDir.appendingPathComponent("Favicons")
|
||||
let imagesFolderURL = tempDir.appendingPathComponent("Images")
|
||||
|
||||
try! FileManager.default.createDirectory(at: faviconsFolderURL, withIntermediateDirectories: true, attributes: nil)
|
||||
let faviconsFolder = faviconsFolderURL.absoluteString
|
||||
let faviconsFolderPath = faviconsFolder.suffix(from: faviconsFolder.index(faviconsFolder.startIndex, offsetBy: 7))
|
||||
faviconDownloader = FaviconDownloader(folder: String(faviconsFolderPath))
|
||||
|
||||
let imagesFolder = imagesFolderURL.absoluteString
|
||||
let imagesFolderPath = imagesFolder.suffix(from: imagesFolder.index(imagesFolder.startIndex, offsetBy: 7))
|
||||
try! FileManager.default.createDirectory(at: imagesFolderURL, withIntermediateDirectories: true, attributes: nil)
|
||||
imageDownloader = ImageDownloader(folder: String(imagesFolderPath))
|
||||
|
||||
authorAvatarDownloader = AuthorAvatarDownloader(imageDownloader: imageDownloader)
|
||||
|
||||
let tempFolder = tempDir.absoluteString
|
||||
let tempFolderPath = tempFolder.suffix(from: tempFolder.index(tempFolder.startIndex, offsetBy: 7))
|
||||
webFeedIconDownloader = WebFeedIconDownloader(imageDownloader: imageDownloader, folder: String(tempFolderPath))
|
||||
}
|
||||
|
||||
private func initializeHomeScreenQuickActions() {
|
||||
let unreadTitle = NSLocalizedString("First Unread", comment: "First Unread")
|
||||
let unreadIcon = UIApplicationShortcutIcon(systemImageName: "chevron.down.circle")
|
||||
let unreadItem = UIApplicationShortcutItem(type: "com.ranchero.NetNewsWire.FirstUnread", localizedTitle: unreadTitle, localizedSubtitle: nil, icon: unreadIcon, userInfo: nil)
|
||||
|
||||
let searchTitle = NSLocalizedString("Search", comment: "Search")
|
||||
let searchIcon = UIApplicationShortcutIcon(systemImageName: "magnifyingglass")
|
||||
let searchItem = UIApplicationShortcutItem(type: "com.ranchero.NetNewsWire.ShowSearch", localizedTitle: searchTitle, localizedSubtitle: nil, icon: searchIcon, userInfo: nil)
|
||||
|
||||
let addTitle = NSLocalizedString("Add Feed", comment: "Add Feed")
|
||||
let addIcon = UIApplicationShortcutIcon(systemImageName: "plus")
|
||||
let addItem = UIApplicationShortcutItem(type: "com.ranchero.NetNewsWire.ShowAdd", localizedTitle: addTitle, localizedSubtitle: nil, icon: addIcon, userInfo: nil)
|
||||
|
||||
UIApplication.shared.shortcutItems = [addItem, searchItem, unreadItem]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: Go To Background
|
||||
|
||||
private extension AppDelegate {
|
||||
|
||||
func waitForSyncTasksToFinish() {
|
||||
guard !isWaitingForSyncTasks && UIApplication.shared.applicationState == .background else { return }
|
||||
|
||||
isWaitingForSyncTasks = true
|
||||
|
||||
self.waitBackgroundUpdateTask = UIApplication.shared.beginBackgroundTask { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.completeProcessing(true)
|
||||
os_log("Accounts wait for progress terminated for running too long.", log: self.log, type: .info)
|
||||
}
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.waitToComplete() { [weak self] suspend in
|
||||
self?.completeProcessing(suspend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func waitToComplete(completion: @escaping (Bool) -> Void) {
|
||||
guard UIApplication.shared.applicationState == .background else {
|
||||
os_log("App came back to forground, no longer waiting.", log: self.log, type: .info)
|
||||
completion(false)
|
||||
return
|
||||
}
|
||||
|
||||
if AccountManager.shared.refreshInProgress || isSyncArticleStatusRunning {
|
||||
os_log("Waiting for sync to finish...", log: self.log, type: .info)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
|
||||
self?.waitToComplete(completion: completion)
|
||||
}
|
||||
} else {
|
||||
os_log("Refresh progress complete.", log: self.log, type: .info)
|
||||
completion(true)
|
||||
}
|
||||
}
|
||||
|
||||
func completeProcessing(_ suspend: Bool) {
|
||||
if suspend {
|
||||
suspendApplication()
|
||||
}
|
||||
UIApplication.shared.endBackgroundTask(self.waitBackgroundUpdateTask)
|
||||
self.waitBackgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
|
||||
isWaitingForSyncTasks = false
|
||||
}
|
||||
|
||||
func syncArticleStatus() {
|
||||
guard !isSyncArticleStatusRunning else { return }
|
||||
|
||||
isSyncArticleStatusRunning = true
|
||||
|
||||
let completeProcessing = { [unowned self] in
|
||||
self.isSyncArticleStatusRunning = false
|
||||
UIApplication.shared.endBackgroundTask(self.syncBackgroundUpdateTask)
|
||||
self.syncBackgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
|
||||
}
|
||||
|
||||
self.syncBackgroundUpdateTask = UIApplication.shared.beginBackgroundTask {
|
||||
completeProcessing()
|
||||
os_log("Accounts sync processing terminated for running too long.", log: self.log, type: .info)
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
AccountManager.shared.syncArticleStatusAll() {
|
||||
completeProcessing()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func suspendApplication() {
|
||||
guard UIApplication.shared.applicationState == .background else { return }
|
||||
|
||||
AccountManager.shared.suspendNetworkAll()
|
||||
AccountManager.shared.suspendDatabaseAll()
|
||||
CoalescingQueue.standard.performCallsImmediately()
|
||||
|
||||
os_log("Application processing suspended.", log: self.log, type: .info)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: Background Tasks
|
||||
|
||||
private extension AppDelegate {
|
||||
|
||||
/// Register all background tasks.
|
||||
func registerBackgroundTasks() {
|
||||
// Register background feed refresh.
|
||||
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.ranchero.NetNewsWire.FeedRefresh", using: nil) { (task) in
|
||||
self.performBackgroundFeedRefresh(with: task as! BGAppRefreshTask)
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedules a background app refresh based on `AppDefaults.refreshInterval`.
|
||||
func scheduleBackgroundFeedRefresh() {
|
||||
let request = BGAppRefreshTaskRequest(identifier: "com.ranchero.NetNewsWire.FeedRefresh")
|
||||
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
|
||||
|
||||
// We send this to a dedicated serial queue because as of 11/05/19 on iOS 13.2 the call to the
|
||||
// task scheduler can hang indefinitely.
|
||||
bgTaskDispatchQueue.async {
|
||||
do {
|
||||
try BGTaskScheduler.shared.submit(request)
|
||||
} catch {
|
||||
os_log(.error, log: self.log, "Could not schedule app refresh: %@", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs background feed refresh.
|
||||
/// - Parameter task: `BGAppRefreshTask`
|
||||
/// - Warning: As of Xcode 11 beta 2, when triggered from the debugger this doesn't work.
|
||||
func performBackgroundFeedRefresh(with task: BGAppRefreshTask) {
|
||||
|
||||
scheduleBackgroundFeedRefresh() // schedule next refresh
|
||||
|
||||
os_log("Woken to perform account refresh.", log: self.log, type: .info)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if AccountManager.shared.isSuspended {
|
||||
AccountManager.shared.resumeAll()
|
||||
}
|
||||
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.log) { [unowned self] in
|
||||
if !AccountManager.shared.isSuspended {
|
||||
self.suspendApplication()
|
||||
os_log("Account refresh operation completed.", log: self.log, type: .info)
|
||||
task.setTaskCompleted(success: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set expiration handler
|
||||
task.expirationHandler = { [weak task] in
|
||||
DispatchQueue.main.sync {
|
||||
self.suspendApplication()
|
||||
}
|
||||
os_log("Accounts refresh processing terminated for running too long.", log: self.log, type: .info)
|
||||
task?.setTaskCompleted(success: false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -46,5 +46,40 @@
|
|||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.ranchero.NetNewsWire.FeedRefresh</string>
|
||||
</array>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>Grant permission to save images from the article.</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>AddWebFeedIntent</string>
|
||||
<string>NextUnread</string>
|
||||
<string>ReadArticle</string>
|
||||
<string>Restoration</string>
|
||||
<string>SelectFeed</string>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>processing</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UserAgent</key>
|
||||
<string>NetNewsWire (RSS Reader; https://ranchero.com/netnewswire/)</string>
|
||||
<key>OrganizationIdentifier</key>
|
||||
<string>$(ORGANIZATION_IDENTIFIER)</string>
|
||||
<key>DeveloperEntitlements</key>
|
||||
<string>$(DEVELOPER_ENTITLEMENTS)</string>
|
||||
<key>AppGroup</key>
|
||||
<string>group.$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
<key>AppIdentifierPrefix</key>
|
||||
<string>$(AppIdentifierPrefix)</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
//
|
||||
// AppDelegate.swift
|
||||
// Multiplatform macOS
|
||||
//
|
||||
// Created by Maurice Parker on 6/28/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import AppKit
|
||||
import os.log
|
||||
import UserNotifications
|
||||
import Articles
|
||||
import RSTree
|
||||
import RSWeb
|
||||
import Account
|
||||
import RSCore
|
||||
|
||||
// If we're not going to import Sparkle, provide dummy protocols to make it easy
|
||||
// for AppDelegate to comply
|
||||
#if MAC_APP_STORE || TEST
|
||||
protocol SPUStandardUserDriverDelegate {}
|
||||
protocol SPUUpdaterDelegate {}
|
||||
#else
|
||||
import Sparkle
|
||||
#endif
|
||||
|
||||
var appDelegate: AppDelegate!
|
||||
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate, UnreadCountProvider, SPUStandardUserDriverDelegate, SPUUpdaterDelegate
|
||||
{
|
||||
|
||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
|
||||
|
||||
var userNotificationManager: UserNotificationManager!
|
||||
var faviconDownloader: FaviconDownloader!
|
||||
var imageDownloader: ImageDownloader!
|
||||
var authorAvatarDownloader: AuthorAvatarDownloader!
|
||||
var webFeedIconDownloader: WebFeedIconDownloader!
|
||||
|
||||
var refreshTimer: AccountRefreshTimer?
|
||||
var syncTimer: ArticleStatusSyncTimer?
|
||||
|
||||
var shuttingDown = false {
|
||||
didSet {
|
||||
if shuttingDown {
|
||||
refreshTimer?.shuttingDown = shuttingDown
|
||||
refreshTimer?.invalidate()
|
||||
syncTimer?.shuttingDown = shuttingDown
|
||||
syncTimer?.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unreadCount = 0 {
|
||||
didSet {
|
||||
if unreadCount != oldValue {
|
||||
CoalescingQueue.standard.add(self, #selector(updateDockBadge))
|
||||
postUnreadCountDidChangeNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var appName: String!
|
||||
|
||||
private let appNewsURLString = "https://nnw.ranchero.com/feed.json"
|
||||
private let appMovementMonitor = RSAppMovementMonitor()
|
||||
#if !MAC_APP_STORE && !TEST
|
||||
private var softwareUpdater: SPUUpdater!
|
||||
#endif
|
||||
|
||||
override init() {
|
||||
NSWindow.allowsAutomaticWindowTabbing = false
|
||||
super.init()
|
||||
|
||||
AccountManager.shared = AccountManager(accountsFolder: Platform.dataSubfolder(forApplication: nil, folderName: "Accounts")!)
|
||||
FeedProviderManager.shared.delegate = ExtensionPointManager.shared
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(didWakeNotification(_:)), name: NSWorkspace.didWakeNotification, object: nil)
|
||||
|
||||
appDelegate = self
|
||||
}
|
||||
|
||||
// MARK: - NSApplicationDelegate
|
||||
|
||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
||||
// TODO: add Apple Events back in
|
||||
// installAppleEventHandlers()
|
||||
|
||||
CacheCleaner.purgeIfNecessary()
|
||||
|
||||
// Try to establish a cache in the Caches folder, but if it fails for some reason fall back to a temporary dir
|
||||
let cacheFolder: String
|
||||
if let userCacheFolder = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false).path {
|
||||
cacheFolder = userCacheFolder
|
||||
}
|
||||
else {
|
||||
let bundleIdentifier = (Bundle.main.infoDictionary!["CFBundleIdentifier"]! as! String)
|
||||
cacheFolder = (NSTemporaryDirectory() as NSString).appendingPathComponent(bundleIdentifier)
|
||||
}
|
||||
|
||||
let faviconsFolder = (cacheFolder as NSString).appendingPathComponent("Favicons")
|
||||
let faviconsFolderURL = URL(fileURLWithPath: faviconsFolder)
|
||||
try! FileManager.default.createDirectory(at: faviconsFolderURL, withIntermediateDirectories: true, attributes: nil)
|
||||
faviconDownloader = FaviconDownloader(folder: faviconsFolder)
|
||||
|
||||
let imagesFolder = (cacheFolder as NSString).appendingPathComponent("Images")
|
||||
let imagesFolderURL = URL(fileURLWithPath: imagesFolder)
|
||||
try! FileManager.default.createDirectory(at: imagesFolderURL, withIntermediateDirectories: true, attributes: nil)
|
||||
imageDownloader = ImageDownloader(folder: imagesFolder)
|
||||
|
||||
authorAvatarDownloader = AuthorAvatarDownloader(imageDownloader: imageDownloader)
|
||||
webFeedIconDownloader = WebFeedIconDownloader(imageDownloader: imageDownloader, folder: cacheFolder)
|
||||
|
||||
appName = (Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String)
|
||||
}
|
||||
|
||||
func applicationDidFinishLaunching(_ note: Notification) {
|
||||
|
||||
#if MAC_APP_STORE || TEST
|
||||
checkForUpdatesMenuItem.isHidden = true
|
||||
#else
|
||||
// Initialize Sparkle...
|
||||
let hostBundle = Bundle.main
|
||||
let updateDriver = SPUStandardUserDriver(hostBundle: hostBundle, delegate: self)
|
||||
self.softwareUpdater = SPUUpdater(hostBundle: hostBundle, applicationBundle: hostBundle, userDriver: updateDriver, delegate: self)
|
||||
|
||||
do {
|
||||
try self.softwareUpdater.start()
|
||||
}
|
||||
catch {
|
||||
NSLog("Failed to start software updater with error: \(error)")
|
||||
}
|
||||
#endif
|
||||
|
||||
AppDefaults.registerDefaults()
|
||||
let isFirstRun = AppDefaults.isFirstRun
|
||||
if isFirstRun {
|
||||
os_log(.debug, log: log, "Is first run.")
|
||||
}
|
||||
let localAccount = AccountManager.shared.defaultAccount
|
||||
|
||||
if isFirstRun && !AccountManager.shared.anyAccountHasAtLeastOneFeed() {
|
||||
DefaultFeedsImporter.importDefaultFeeds(account: localAccount)
|
||||
}
|
||||
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webFeedSettingDidChange(_:)), name: .WebFeedSettingDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.unreadCount = AccountManager.shared.unreadCount
|
||||
}
|
||||
|
||||
refreshTimer = AccountRefreshTimer()
|
||||
syncTimer = ArticleStatusSyncTimer()
|
||||
|
||||
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .sound, .alert]) { (granted, error) in }
|
||||
NSApplication.shared.registerForRemoteNotifications()
|
||||
|
||||
UNUserNotificationCenter.current().delegate = self
|
||||
userNotificationManager = UserNotificationManager()
|
||||
|
||||
// TODO: Add a debug menu
|
||||
// if AppDefaults.showDebugMenu {
|
||||
// refreshTimer!.update()
|
||||
// syncTimer!.update()
|
||||
//
|
||||
// // The Web Inspector uses SPI and can never appear in a MAC_APP_STORE build.
|
||||
// #if MAC_APP_STORE
|
||||
// let debugMenu = debugMenuItem.submenu!
|
||||
// let toggleWebInspectorItemIndex = debugMenu.indexOfItem(withTarget: self, andAction: #selector(toggleWebInspectorEnabled(_:)))
|
||||
// if toggleWebInspectorItemIndex != -1 {
|
||||
// debugMenu.removeItem(at: toggleWebInspectorItemIndex)
|
||||
// }
|
||||
// #endif
|
||||
// } else {
|
||||
// debugMenuItem.menu?.removeItem(debugMenuItem)
|
||||
// DispatchQueue.main.async {
|
||||
// self.refreshTimer!.timedRefresh(nil)
|
||||
// self.syncTimer!.timedRefresh(nil)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: Add back in crash reporter
|
||||
// #if !MAC_APP_STORE
|
||||
// DispatchQueue.main.async {
|
||||
// CrashReporter.check(appName: "NetNewsWire")
|
||||
// }
|
||||
// #endif
|
||||
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ notification: Notification) {
|
||||
fireOldTimers()
|
||||
}
|
||||
|
||||
func applicationDidResignActive(_ notification: Notification) {
|
||||
ArticleStringFormatter.emptyCaches()
|
||||
}
|
||||
|
||||
func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) {
|
||||
AccountManager.shared.receiveRemoteNotification(userInfo: userInfo)
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
shuttingDown = true
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
@objc func unreadCountDidChange(_ note: Notification) {
|
||||
if note.object is AccountManager {
|
||||
unreadCount = AccountManager.shared.unreadCount
|
||||
}
|
||||
}
|
||||
|
||||
@objc func webFeedSettingDidChange(_ note: Notification) {
|
||||
guard let feed = note.object as? WebFeed, let key = note.userInfo?[WebFeed.WebFeedSettingUserInfoKey] as? String else {
|
||||
return
|
||||
}
|
||||
if key == WebFeed.WebFeedSettingKey.homePageURL || key == WebFeed.WebFeedSettingKey.faviconURL {
|
||||
let _ = faviconDownloader.favicon(for: feed)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func userDefaultsDidChange(_ note: Notification) {
|
||||
refreshTimer?.update()
|
||||
updateDockBadge()
|
||||
}
|
||||
|
||||
@objc func didWakeNotification(_ note: Notification) {
|
||||
fireOldTimers()
|
||||
}
|
||||
|
||||
// MARK: UNUserNotificationCenterDelegate
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.banner, .badge, .sound])
|
||||
}
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
// TODO: Add back in Notification handling
|
||||
// mainWindowController?.handle(response)
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
// MARK: - Dock Badge
|
||||
@objc func updateDockBadge() {
|
||||
let label = unreadCount > 0 && !AppDefaults.hideDockUnreadCount ? "\(unreadCount)" : ""
|
||||
NSApplication.shared.dockTile.badgeLabel = label
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private extension AppDelegate {
|
||||
|
||||
func fireOldTimers() {
|
||||
// It’s possible there’s a refresh timer set to go off in the past.
|
||||
// In that case, refresh now and update the timer.
|
||||
refreshTimer?.fireOldTimer()
|
||||
syncTimer?.fireOldTimer()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
the ScriptingAppDelegate protocol exposes a narrow set of accessors with
|
||||
internal visibility which are very similar to some private vars.
|
||||
|
||||
These would be unnecessary if the similar accessors were marked internal rather than private,
|
||||
but for now, we'll keep the stratification of visibility
|
||||
*/
|
||||
//extension AppDelegate : ScriptingAppDelegate {
|
||||
//
|
||||
// internal var scriptingMainWindowController: ScriptingMainWindowController? {
|
||||
// return mainWindowController
|
||||
// }
|
||||
//
|
||||
// internal var scriptingCurrentArticle: Article? {
|
||||
// return self.scriptingMainWindowController?.scriptingCurrentArticle
|
||||
// }
|
||||
//
|
||||
// internal var scriptingSelectedArticles: [Article] {
|
||||
// return self.scriptingMainWindowController?.scriptingSelectedArticles ?? []
|
||||
// }
|
||||
//}
|
|
@ -24,5 +24,16 @@
|
|||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2020 Ranchero Software. All rights reserved.</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UserAgent</key>
|
||||
<string>NetNewsWire (RSS Reader; https://ranchero.com/netnewswire/)</string>
|
||||
<key>OrganizationIdentifier</key>
|
||||
<string>$(ORGANIZATION_IDENTIFIER)</string>
|
||||
<key>DeveloperEntitlements</key>
|
||||
<string>$(DEVELOPER_ENTITLEMENTS)</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -251,8 +251,8 @@
|
|||
51BC4B00247277E0000A6ED8 /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
|
||||
51BC4B01247277E0000A6ED8 /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
|
||||
51BEB22D2451E8340066DEDD /* TwitterEnterDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BEB22C2451E8340066DEDD /* TwitterEnterDetailTableViewController.swift */; };
|
||||
51C0515E24A77DF800194D5E /* NetNewsWire_MultiplatformApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C0513624A77DF700194D5E /* NetNewsWire_MultiplatformApp.swift */; };
|
||||
51C0515F24A77DF800194D5E /* NetNewsWire_MultiplatformApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C0513624A77DF700194D5E /* NetNewsWire_MultiplatformApp.swift */; };
|
||||
51C0515E24A77DF800194D5E /* NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C0513624A77DF700194D5E /* NetNewsWire.swift */; };
|
||||
51C0515F24A77DF800194D5E /* NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C0513624A77DF700194D5E /* NetNewsWire.swift */; };
|
||||
51C0516024A77DF800194D5E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C0513724A77DF700194D5E /* ContentView.swift */; };
|
||||
51C0516124A77DF800194D5E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C0513724A77DF700194D5E /* ContentView.swift */; };
|
||||
51C0516224A77DF800194D5E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51C0513824A77DF800194D5E /* Assets.xcassets */; };
|
||||
|
@ -344,6 +344,189 @@
|
|||
51E3EB3D229AB08300645299 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E3EB3C229AB08300645299 /* ErrorHandler.swift */; };
|
||||
51E43962238037C400015C31 /* AddWebFeedFolderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E43961238037C400015C31 /* AddWebFeedFolderViewController.swift */; };
|
||||
51E4398023805EBC00015C31 /* AddComboTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4397F23805EBC00015C31 /* AddComboTableViewCell.swift */; };
|
||||
51E4987F24A8061400B667CB /* Account.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407166A2262A60D00344432 /* Account.framework */; };
|
||||
51E4988024A8061400B667CB /* Account.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407166A2262A60D00344432 /* Account.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988124A8061400B667CB /* Articles.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 840716732262A60F00344432 /* Articles.framework */; };
|
||||
51E4988224A8061400B667CB /* Articles.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 840716732262A60F00344432 /* Articles.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988324A8061400B667CB /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; };
|
||||
51E4988424A8061400B667CB /* ArticlesDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988524A8061400B667CB /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755324451BD500B553B9 /* OAuthSwift.framework */; };
|
||||
51E4988624A8061400B667CB /* OAuthSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755324451BD500B553B9 /* OAuthSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988724A8061400B667CB /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8520DD8CF200CA8CF5 /* RSCore.framework */; };
|
||||
51E4988824A8061400B667CB /* RSCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8520DD8CF200CA8CF5 /* RSCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988924A8061400B667CB /* RSDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37FC420DD8E0C00CA8CF5 /* RSDatabase.framework */; };
|
||||
51E4988A24A8061400B667CB /* RSDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37FC420DD8E0C00CA8CF5 /* RSDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988B24A8061400B667CB /* RSParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8C20DD8CF800CA8CF5 /* RSParser.framework */; };
|
||||
51E4988C24A8061400B667CB /* RSParser.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8C20DD8CF800CA8CF5 /* RSParser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988D24A8061400B667CB /* RSTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9520DD8CFE00CA8CF5 /* RSTree.framework */; };
|
||||
51E4988E24A8061400B667CB /* RSTree.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9520DD8CFE00CA8CF5 /* RSTree.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4988F24A8061400B667CB /* RSWeb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37FA320DD8D0500CA8CF5 /* RSWeb.framework */; };
|
||||
51E4989024A8061400B667CB /* RSWeb.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37FA320DD8D0500CA8CF5 /* RSWeb.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4989124A8061400B667CB /* Secrets.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5102FD7B244008A700534F17 /* Secrets.framework */; };
|
||||
51E4989224A8061400B667CB /* Secrets.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5102FD7B244008A700534F17 /* Secrets.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4989324A8061400B667CB /* SyncDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; };
|
||||
51E4989424A8061400B667CB /* SyncDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4989724A8065700B667CB /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4989624A8065700B667CB /* CloudKit.framework */; };
|
||||
51E4989924A8067000B667CB /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4989824A8067000B667CB /* WebKit.framework */; };
|
||||
51E4989A24A8069300B667CB /* Account.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407166A2262A60D00344432 /* Account.framework */; };
|
||||
51E4989B24A8069300B667CB /* Account.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407166A2262A60D00344432 /* Account.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4989C24A8069300B667CB /* Articles.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 840716732262A60F00344432 /* Articles.framework */; };
|
||||
51E4989D24A8069300B667CB /* Articles.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 840716732262A60F00344432 /* Articles.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4989E24A8069300B667CB /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; };
|
||||
51E4989F24A8069300B667CB /* ArticlesDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498A024A8069300B667CB /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755524451BD500B553B9 /* OAuthSwift.framework */; };
|
||||
51E498A124A8069300B667CB /* OAuthSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755524451BD500B553B9 /* OAuthSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498A224A8069300B667CB /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8120DD8CF200CA8CF5 /* RSCore.framework */; };
|
||||
51E498A324A8069300B667CB /* RSCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8120DD8CF200CA8CF5 /* RSCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498A424A8069300B667CB /* RSDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37FC020DD8E0C00CA8CF5 /* RSDatabase.framework */; };
|
||||
51E498A524A8069300B667CB /* RSDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37FC020DD8E0C00CA8CF5 /* RSDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498A624A8069300B667CB /* RSParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8C20DD8CF800CA8CF5 /* RSParser.framework */; };
|
||||
51E498A724A8069300B667CB /* RSParser.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F8C20DD8CF800CA8CF5 /* RSParser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498A824A8069300B667CB /* RSTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9520DD8CFE00CA8CF5 /* RSTree.framework */; };
|
||||
51E498A924A8069300B667CB /* RSTree.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9520DD8CFE00CA8CF5 /* RSTree.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498AA24A8069300B667CB /* RSWeb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9F20DD8D0500CA8CF5 /* RSWeb.framework */; };
|
||||
51E498AB24A8069300B667CB /* RSWeb.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9F20DD8D0500CA8CF5 /* RSWeb.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498AC24A8069300B667CB /* Secrets.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5102FD7B244008A700534F17 /* Secrets.framework */; };
|
||||
51E498AD24A8069300B667CB /* Secrets.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5102FD7B244008A700534F17 /* Secrets.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498AE24A8069300B667CB /* SyncDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; };
|
||||
51E498AF24A8069300B667CB /* SyncDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E498B124A806A400B667CB /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4DAEC2425F6940091EB5B /* CloudKit.framework */; };
|
||||
51E498B324A806AA00B667CB /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E498B224A806AA00B667CB /* WebKit.framework */; };
|
||||
51E498C724A8085D00B667CB /* StarredFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845EE7B01FC2366500854A1F /* StarredFeedDelegate.swift */; };
|
||||
51E498C824A8085D00B667CB /* SmartFeedsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC88171FE59CBF00644329 /* SmartFeedsController.swift */; };
|
||||
51E498C924A8085D00B667CB /* PseudoFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5351FC22FCB00998D64 /* PseudoFeed.swift */; };
|
||||
51E498CA24A8085D00B667CB /* SmartFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DEE56422C32CA4005FC42C /* SmartFeedDelegate.swift */; };
|
||||
51E498CB24A8085D00B667CB /* TodayFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5361FC22FCB00998D64 /* TodayFeedDelegate.swift */; };
|
||||
51E498CC24A8085D00B667CB /* SearchFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8477ACBD22238E9500DF7F37 /* SearchFeedDelegate.swift */; };
|
||||
51E498CD24A8085D00B667CB /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; };
|
||||
51E498CE24A8085D00B667CB /* UnreadFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5391FC2308B00998D64 /* UnreadFeed.swift */; };
|
||||
51E498CF24A8085D00B667CB /* SmartFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845EE7C01FC2488C00854A1F /* SmartFeed.swift */; };
|
||||
51E498F124A8085D00B667CB /* StarredFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845EE7B01FC2366500854A1F /* StarredFeedDelegate.swift */; };
|
||||
51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC88171FE59CBF00644329 /* SmartFeedsController.swift */; };
|
||||
51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5351FC22FCB00998D64 /* PseudoFeed.swift */; };
|
||||
51E498F424A8085D00B667CB /* SmartFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DEE56422C32CA4005FC42C /* SmartFeedDelegate.swift */; };
|
||||
51E498F524A8085D00B667CB /* TodayFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5361FC22FCB00998D64 /* TodayFeedDelegate.swift */; };
|
||||
51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8477ACBD22238E9500DF7F37 /* SearchFeedDelegate.swift */; };
|
||||
51E498F724A8085D00B667CB /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; };
|
||||
51E498F824A8085D00B667CB /* UnreadFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5391FC2308B00998D64 /* UnreadFeed.swift */; };
|
||||
51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845EE7C01FC2488C00854A1F /* SmartFeed.swift */; };
|
||||
51E498FA24A808BA00B667CB /* SingleFaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845A29081FC74B8E007B49E3 /* SingleFaviconDownloader.swift */; };
|
||||
51E498FB24A808BA00B667CB /* FaviconGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F76227716200050506E /* FaviconGenerator.swift */; };
|
||||
51E498FC24A808BA00B667CB /* FaviconURLFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */; };
|
||||
51E498FD24A808BA00B667CB /* ColorHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F78227716380050506E /* ColorHash.swift */; };
|
||||
51E498FE24A808BA00B667CB /* FaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */; };
|
||||
51E498FF24A808BB00B667CB /* SingleFaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845A29081FC74B8E007B49E3 /* SingleFaviconDownloader.swift */; };
|
||||
51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F76227716200050506E /* FaviconGenerator.swift */; };
|
||||
51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */; };
|
||||
51E4990224A808BB00B667CB /* ColorHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F78227716380050506E /* ColorHash.swift */; };
|
||||
51E4990324A808BB00B667CB /* FaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */; };
|
||||
51E4990424A808C300B667CB /* WebFeedIconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842611891FCB67AA0086A189 /* WebFeedIconDownloader.swift */; };
|
||||
51E4990524A808C300B667CB /* FeaturedImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8426119F1FCB72600086A189 /* FeaturedImageDownloader.swift */; };
|
||||
51E4990624A808C300B667CB /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845213221FCA5B10003B6E93 /* ImageDownloader.swift */; };
|
||||
51E4990724A808C300B667CB /* AuthorAvatarDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E850851FCB60CE0072EA88 /* AuthorAvatarDownloader.swift */; };
|
||||
51E4990824A808C300B667CB /* RSHTMLMetadata+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842611A11FCB769D0086A189 /* RSHTMLMetadata+Extension.swift */; };
|
||||
51E4990924A808C500B667CB /* WebFeedIconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842611891FCB67AA0086A189 /* WebFeedIconDownloader.swift */; };
|
||||
51E4990A24A808C500B667CB /* FeaturedImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8426119F1FCB72600086A189 /* FeaturedImageDownloader.swift */; };
|
||||
51E4990B24A808C500B667CB /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845213221FCA5B10003B6E93 /* ImageDownloader.swift */; };
|
||||
51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E850851FCB60CE0072EA88 /* AuthorAvatarDownloader.swift */; };
|
||||
51E4990D24A808C500B667CB /* RSHTMLMetadata+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842611A11FCB769D0086A189 /* RSHTMLMetadata+Extension.swift */; };
|
||||
51E4990E24A808CC00B667CB /* HTMLMetadataDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8426119D1FCB6ED40086A189 /* HTMLMetadataDownloader.swift */; };
|
||||
51E4990F24A808CC00B667CB /* HTMLMetadataDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8426119D1FCB6ED40086A189 /* HTMLMetadataDownloader.swift */; };
|
||||
51E4991024A808DE00B667CB /* SmallIconProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84411E701FE5FBFA004B527F /* SmallIconProvider.swift */; };
|
||||
51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84411E701FE5FBFA004B527F /* SmallIconProvider.swift */; };
|
||||
51E4991224A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
|
||||
51E4991324A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
|
||||
51E4991424A808FF00B667CB /* ArticleStringFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97731ED9EC04007D329B /* ArticleStringFormatter.swift */; };
|
||||
51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97731ED9EC04007D329B /* ArticleStringFormatter.swift */; };
|
||||
51E4991624A8090300B667CB /* ArticleUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97581ED9EB0D007D329B /* ArticleUtilities.swift */; };
|
||||
51E4991724A8090400B667CB /* ArticleUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97581ED9EB0D007D329B /* ArticleUtilities.swift */; };
|
||||
51E4991824A8090A00B667CB /* CacheCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6B52375E612001ABC45 /* CacheCleaner.swift */; };
|
||||
51E4991924A8090A00B667CB /* CacheCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6B52375E612001ABC45 /* CacheCleaner.swift */; };
|
||||
51E4991A24A8090F00B667CB /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; };
|
||||
51E4991B24A8091000B667CB /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; };
|
||||
51E4991C24A8092000B667CB /* NSAttributedString+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */; };
|
||||
51E4991D24A8092100B667CB /* NSAttributedString+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */; };
|
||||
51E4991E24A8094300B667CB /* RSImage-AppIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */; };
|
||||
51E4991F24A8094300B667CB /* RSImage-AppIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */; };
|
||||
51E4992024A8095000B667CB /* RSImage-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */; };
|
||||
51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */; };
|
||||
51E4992224A8095600B667CB /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
|
||||
51E4992324A8095700B667CB /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
|
||||
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 */; };
|
||||
51E4992E24A8676300B667CB /* FetchRequestQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCA322BC8C08007694F0 /* FetchRequestQueue.swift */; };
|
||||
51E4992F24A8676400B667CB /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; };
|
||||
51E4993024A8676400B667CB /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
||||
51E4993124A8676400B667CB /* FetchRequestOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCAE22BC8C35007694F0 /* FetchRequestOperation.swift */; };
|
||||
51E4993224A8676400B667CB /* FetchRequestQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCA322BC8C08007694F0 /* FetchRequestQueue.swift */; };
|
||||
51E4993324A867E700B667CB /* AppNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842E45CD1ED8C308000A8B52 /* AppNotifications.swift */; };
|
||||
51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511B9805237DCAC90028BCAA /* UserInfoKey.swift */; };
|
||||
51E4993524A867E800B667CB /* AppNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842E45CD1ED8C308000A8B52 /* AppNotifications.swift */; };
|
||||
51E4993624A867E800B667CB /* UserInfoKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511B9805237DCAC90028BCAA /* UserInfoKey.swift */; };
|
||||
51E4993724A8680E00B667CB /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513228F2233037620033D4ED /* Reachability.swift */; };
|
||||
51E4993824A8680E00B667CB /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513228F2233037620033D4ED /* Reachability.swift */; };
|
||||
51E4993A24A8708800B667CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4993924A8708800B667CB /* AppDelegate.swift */; };
|
||||
51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4993B24A8709900B667CB /* AppDelegate.swift */; };
|
||||
51E4993D24A870F800B667CB /* UserNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FE10022345529D0056195D /* UserNotificationManager.swift */; };
|
||||
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, ); }; };
|
||||
51E4994824A872AD00B667CB /* org.sparkle-project.InstallerStatus.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 65ED42BA235E71B40081F399 /* org.sparkle-project.InstallerStatus.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
51E4994A24A8734C00B667CB /* ExtensionPointManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515A50E5243D07A90089E588 /* ExtensionPointManager.swift */; };
|
||||
51E4994B24A8734C00B667CB /* SendToMicroBlogCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A14FF220048CA70046AD9A /* SendToMicroBlogCommand.swift */; };
|
||||
51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */; };
|
||||
51E4994D24A8734C00B667CB /* ExtensionPointIdentifer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515A5176243E90200089E588 /* ExtensionPointIdentifer.swift */; };
|
||||
51E4994E24A8734C00B667CB /* SendToMarsEditCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A1500420048DDF0046AD9A /* SendToMarsEditCommand.swift */; };
|
||||
51E4994F24A8734C00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515A5106243D0CCD0089E588 /* TwitterFeedProvider-Extensions.swift */; };
|
||||
51E4995024A8734C00B667CB /* ExtensionPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510C43F6243D035C009F70C3 /* ExtensionPoint.swift */; };
|
||||
51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515A50E5243D07A90089E588 /* ExtensionPointManager.swift */; };
|
||||
51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */; };
|
||||
51E4995424A8734D00B667CB /* ExtensionPointIdentifer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515A5176243E90200089E588 /* ExtensionPointIdentifer.swift */; };
|
||||
51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515A5106243D0CCD0089E588 /* TwitterFeedProvider-Extensions.swift */; };
|
||||
51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510C43F6243D035C009F70C3 /* ExtensionPoint.swift */; };
|
||||
51E4995924A873F900B667CB /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4995824A873F900B667CB /* ErrorHandler.swift */; };
|
||||
51E4995A24A873F900B667CB /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E4995824A873F900B667CB /* ErrorHandler.swift */; };
|
||||
51E4995B24A875D500B667CB /* ArticlePasteboardWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E95D231FB1087500552D99 /* ArticlePasteboardWriter.swift */; };
|
||||
51E4995C24A875F300B667CB /* ArticleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A977D1ED9EC42007D329B /* ArticleRenderer.swift */; };
|
||||
51E4995D24A875F300B667CB /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
||||
51E4995E24A875F300B667CB /* newsfoot.js in Resources */ = {isa = PBXBuildFile; fileRef = 49F40DEF2335B71000552BF4 /* newsfoot.js */; };
|
||||
51E4995F24A875F300B667CB /* shared.css in Resources */ = {isa = PBXBuildFile; fileRef = B27EEBDF244D15F2000932E6 /* shared.css */; };
|
||||
51E4996024A875F300B667CB /* template.html in Resources */ = {isa = PBXBuildFile; fileRef = 848362FE2262A30E00DA1D35 /* template.html */; };
|
||||
51E4996124A875F400B667CB /* ArticleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A977D1ED9EC42007D329B /* ArticleRenderer.swift */; };
|
||||
51E4996224A875F400B667CB /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
||||
51E4996324A875F400B667CB /* newsfoot.js in Resources */ = {isa = PBXBuildFile; fileRef = 49F40DEF2335B71000552BF4 /* newsfoot.js */; };
|
||||
51E4996424A875F400B667CB /* shared.css in Resources */ = {isa = PBXBuildFile; fileRef = B27EEBDF244D15F2000932E6 /* shared.css */; };
|
||||
51E4996524A875F400B667CB /* template.html in Resources */ = {isa = PBXBuildFile; fileRef = 848362FE2262A30E00DA1D35 /* template.html */; };
|
||||
51E4996624A8760B00B667CB /* ArticleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97871ED9ECEF007D329B /* ArticleStyle.swift */; };
|
||||
51E4996724A8760B00B667CB /* ArticleStylesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97881ED9ECEF007D329B /* ArticleStylesManager.swift */; };
|
||||
51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97871ED9ECEF007D329B /* ArticleStyle.swift */; };
|
||||
51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97881ED9ECEF007D329B /* ArticleStylesManager.swift */; };
|
||||
51E4996A24A8762D00B667CB /* ExtractedArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A62332BE880090D516 /* ExtractedArticle.swift */; };
|
||||
51E4996B24A8762D00B667CB /* ArticleExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A32332BE110090D516 /* ArticleExtractor.swift */; };
|
||||
51E4996C24A8762D00B667CB /* ExtractedArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A62332BE880090D516 /* ExtractedArticle.swift */; };
|
||||
51E4996D24A8762D00B667CB /* ArticleExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A32332BE110090D516 /* ArticleExtractor.swift */; };
|
||||
51E4996E24A8764C00B667CB /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; };
|
||||
51E4996F24A8764C00B667CB /* ActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D87EE02311D34700E63F03 /* ActivityType.swift */; };
|
||||
51E4997024A8764C00B667CB /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; };
|
||||
51E4997124A8764C00B667CB /* ActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D87EE02311D34700E63F03 /* ActivityType.swift */; };
|
||||
51E4997224A8784300B667CB /* DefaultFeedsImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97591ED9EB0D007D329B /* DefaultFeedsImporter.swift */; };
|
||||
51E4997324A8784300B667CB /* DefaultFeeds.opml in Resources */ = {isa = PBXBuildFile; fileRef = 84A3EE52223B667F00557320 /* DefaultFeeds.opml */; };
|
||||
51E4997424A8784400B667CB /* DefaultFeedsImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97591ED9EB0D007D329B /* DefaultFeedsImporter.swift */; };
|
||||
51E4997524A8784400B667CB /* DefaultFeeds.opml in Resources */ = {isa = PBXBuildFile; fileRef = 84A3EE52223B667F00557320 /* DefaultFeeds.opml */; };
|
||||
51E4997624A87FFC00B667CB /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65ED42B0235E71B40081F399 /* Sparkle.framework */; };
|
||||
51E4997724A87FFC00B667CB /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 65ED42B0235E71B40081F399 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
51E4DAED2425F6940091EB5B /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4DAEC2425F6940091EB5B /* CloudKit.framework */; };
|
||||
51E4DB082425F9EB0091EB5B /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4DB072425F9EB0091EB5B /* CloudKit.framework */; };
|
||||
51E595A5228CC36500FCC42B /* ArticleStatusSyncTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */; };
|
||||
|
@ -1320,6 +1503,63 @@
|
|||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
51E4989524A8061400B667CB /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
51E4989024A8061400B667CB /* RSWeb.framework in Embed Frameworks */,
|
||||
51E4988A24A8061400B667CB /* RSDatabase.framework in Embed Frameworks */,
|
||||
51E4988E24A8061400B667CB /* RSTree.framework in Embed Frameworks */,
|
||||
51E4988024A8061400B667CB /* Account.framework in Embed Frameworks */,
|
||||
51E4988224A8061400B667CB /* Articles.framework in Embed Frameworks */,
|
||||
51E4988624A8061400B667CB /* OAuthSwift.framework in Embed Frameworks */,
|
||||
51E4989424A8061400B667CB /* SyncDatabase.framework in Embed Frameworks */,
|
||||
51E4988824A8061400B667CB /* RSCore.framework in Embed Frameworks */,
|
||||
51E4988C24A8061400B667CB /* RSParser.framework in Embed Frameworks */,
|
||||
51E4989224A8061400B667CB /* Secrets.framework in Embed Frameworks */,
|
||||
51E4988424A8061400B667CB /* ArticlesDatabase.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
51E498B024A8069300B667CB /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
51E498AB24A8069300B667CB /* RSWeb.framework in Embed Frameworks */,
|
||||
51E498A524A8069300B667CB /* RSDatabase.framework in Embed Frameworks */,
|
||||
51E498A924A8069300B667CB /* RSTree.framework in Embed Frameworks */,
|
||||
51E4989B24A8069300B667CB /* Account.framework in Embed Frameworks */,
|
||||
51E4989D24A8069300B667CB /* Articles.framework in Embed Frameworks */,
|
||||
51E498A124A8069300B667CB /* OAuthSwift.framework in Embed Frameworks */,
|
||||
51E498AF24A8069300B667CB /* SyncDatabase.framework in Embed Frameworks */,
|
||||
51E4997724A87FFC00B667CB /* Sparkle.framework in Embed Frameworks */,
|
||||
51E498A324A8069300B667CB /* RSCore.framework in Embed Frameworks */,
|
||||
51E498A724A8069300B667CB /* RSParser.framework in Embed Frameworks */,
|
||||
51E498AD24A8069300B667CB /* Secrets.framework in Embed Frameworks */,
|
||||
51E4989F24A8069300B667CB /* ArticlesDatabase.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
51E4994924A872AD00B667CB /* Embed XPC Services */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
51E4994824A872AD00B667CB /* org.sparkle-project.InstallerStatus.xpc in Embed XPC Services */,
|
||||
51E4994624A872AD00B667CB /* org.sparkle-project.InstallerConnection.xpc in Embed XPC Services */,
|
||||
51E4994724A872AD00B667CB /* org.sparkle-project.InstallerLauncher.xpc in Embed XPC Services */,
|
||||
51E4994524A872AD00B667CB /* org.sparkle-project.Downloader.xpc in Embed XPC Services */,
|
||||
);
|
||||
name = "Embed XPC Services";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6581C75720CED60100F4AD34 /* Embed App Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -1565,7 +1805,7 @@
|
|||
51BB7C302335ACDE008E8144 /* page.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = page.html; sourceTree = "<group>"; };
|
||||
51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51BEB22C2451E8340066DEDD /* TwitterEnterDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterEnterDetailTableViewController.swift; sourceTree = "<group>"; };
|
||||
51C0513624A77DF700194D5E /* NetNewsWire_MultiplatformApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetNewsWire_MultiplatformApp.swift; sourceTree = "<group>"; };
|
||||
51C0513624A77DF700194D5E /* NetNewsWire.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetNewsWire.swift; sourceTree = "<group>"; };
|
||||
51C0513724A77DF700194D5E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
51C0513824A77DF800194D5E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
51C0513D24A77DF800194D5E /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetNewsWire.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -1613,6 +1853,14 @@
|
|||
51E3EB3C229AB08300645299 /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = "<group>"; };
|
||||
51E43961238037C400015C31 /* AddWebFeedFolderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedFolderViewController.swift; sourceTree = "<group>"; };
|
||||
51E4397F23805EBC00015C31 /* AddComboTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddComboTableViewCell.swift; sourceTree = "<group>"; };
|
||||
51E4989624A8065700B667CB /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
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>"; };
|
||||
51E4DAEC2425F6940091EB5B /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
||||
51E4DB072425F9EB0091EB5B /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleStatusSyncTimer.swift; sourceTree = "<group>"; };
|
||||
|
@ -1910,6 +2158,19 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
51E4988F24A8061400B667CB /* RSWeb.framework in Frameworks */,
|
||||
51E4988924A8061400B667CB /* RSDatabase.framework in Frameworks */,
|
||||
51E4988D24A8061400B667CB /* RSTree.framework in Frameworks */,
|
||||
51E4987F24A8061400B667CB /* Account.framework in Frameworks */,
|
||||
51E4988124A8061400B667CB /* Articles.framework in Frameworks */,
|
||||
51E4988524A8061400B667CB /* OAuthSwift.framework in Frameworks */,
|
||||
51E4989324A8061400B667CB /* SyncDatabase.framework in Frameworks */,
|
||||
51E4988724A8061400B667CB /* RSCore.framework in Frameworks */,
|
||||
51E4988B24A8061400B667CB /* RSParser.framework in Frameworks */,
|
||||
51E4989724A8065700B667CB /* CloudKit.framework in Frameworks */,
|
||||
51E4989124A8061400B667CB /* Secrets.framework in Frameworks */,
|
||||
51E4989924A8067000B667CB /* WebKit.framework in Frameworks */,
|
||||
51E4988324A8061400B667CB /* ArticlesDatabase.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1917,6 +2178,20 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
51E498AA24A8069300B667CB /* RSWeb.framework in Frameworks */,
|
||||
51E498A424A8069300B667CB /* RSDatabase.framework in Frameworks */,
|
||||
51E498A824A8069300B667CB /* RSTree.framework in Frameworks */,
|
||||
51E4997624A87FFC00B667CB /* Sparkle.framework in Frameworks */,
|
||||
51E4989A24A8069300B667CB /* Account.framework in Frameworks */,
|
||||
51E4989C24A8069300B667CB /* Articles.framework in Frameworks */,
|
||||
51E498A024A8069300B667CB /* OAuthSwift.framework in Frameworks */,
|
||||
51E498AE24A8069300B667CB /* SyncDatabase.framework in Frameworks */,
|
||||
51E498A224A8069300B667CB /* RSCore.framework in Frameworks */,
|
||||
51E498A624A8069300B667CB /* RSParser.framework in Frameworks */,
|
||||
51E498B124A806A400B667CB /* CloudKit.framework in Frameworks */,
|
||||
51E498AC24A8069300B667CB /* Secrets.framework in Frameworks */,
|
||||
51E498B324A806AA00B667CB /* WebKit.framework in Frameworks */,
|
||||
51E4989E24A8069300B667CB /* ArticlesDatabase.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -2269,6 +2544,7 @@
|
|||
51C0513F24A77DF800194D5E /* Info.plist */,
|
||||
51C051CE24A7A72100194D5E /* iOS.entitlements */,
|
||||
51C051CF24A7A72100194D5E /* iOS-dev.entitlements */,
|
||||
51E4993B24A8709900B667CB /* AppDelegate.swift */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2279,6 +2555,7 @@
|
|||
51C0514624A77DF800194D5E /* Info.plist */,
|
||||
51C0514724A77DF800194D5E /* macOS.entitlements */,
|
||||
51C051CD24A7A6DB00194D5E /* macOS-dev.entitlements */,
|
||||
51E4993924A8708800B667CB /* AppDelegate.swift */,
|
||||
);
|
||||
path = macOS;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2286,8 +2563,11 @@
|
|||
51C0519524A77E8B00194D5E /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51C0513624A77DF700194D5E /* NetNewsWire_MultiplatformApp.swift */,
|
||||
51C0513624A77DF700194D5E /* NetNewsWire.swift */,
|
||||
51C0513724A77DF700194D5E /* ContentView.swift */,
|
||||
51E4992524A80AAB00B667CB /* AppAssets.swift */,
|
||||
51E4992824A866F000B667CB /* AppDefaults.swift */,
|
||||
51E4995824A873F900B667CB /* ErrorHandler.swift */,
|
||||
51C0513824A77DF800194D5E /* Assets.xcassets */,
|
||||
);
|
||||
path = Shared;
|
||||
|
@ -2451,8 +2731,11 @@
|
|||
51C452B22265141B00C03939 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51E4989824A8067000B667CB /* WebKit.framework */,
|
||||
51E498B224A806AA00B667CB /* WebKit.framework */,
|
||||
51E4DB072425F9EB0091EB5B /* CloudKit.framework */,
|
||||
51E4DAEC2425F6940091EB5B /* CloudKit.framework */,
|
||||
51E4989624A8065700B667CB /* CloudKit.framework */,
|
||||
51C452B32265141B00C03939 /* WebKit.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
|
@ -3276,6 +3559,7 @@
|
|||
51C0513924A77DF800194D5E /* Sources */,
|
||||
51C0513A24A77DF800194D5E /* Frameworks */,
|
||||
51C0513B24A77DF800194D5E /* Resources */,
|
||||
51E4989524A8061400B667CB /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -3293,6 +3577,8 @@
|
|||
51C0514024A77DF800194D5E /* Sources */,
|
||||
51C0514124A77DF800194D5E /* Frameworks */,
|
||||
51C0514224A77DF800194D5E /* Resources */,
|
||||
51E498B024A8069300B667CB /* Embed Frameworks */,
|
||||
51E4994924A872AD00B667CB /* Embed XPC Services */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -3944,7 +4230,12 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
51E4995F24A875F300B667CB /* shared.css in Resources */,
|
||||
51E4997324A8784300B667CB /* DefaultFeeds.opml in Resources */,
|
||||
51C0516224A77DF800194D5E /* Assets.xcassets in Resources */,
|
||||
51E4996024A875F300B667CB /* template.html in Resources */,
|
||||
51E4995E24A875F300B667CB /* newsfoot.js in Resources */,
|
||||
51E4995D24A875F300B667CB /* main.js in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -3952,7 +4243,12 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
51E4996424A875F400B667CB /* shared.css in Resources */,
|
||||
51E4997524A8784400B667CB /* DefaultFeeds.opml in Resources */,
|
||||
51C0516324A77DF800194D5E /* Assets.xcassets in Resources */,
|
||||
51E4996524A875F400B667CB /* template.html in Resources */,
|
||||
51E4996324A875F400B667CB /* newsfoot.js in Resources */,
|
||||
51E4996224A875F400B667CB /* main.js in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4273,8 +4569,65 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
51E4995924A873F900B667CB /* ErrorHandler.swift in Sources */,
|
||||
51E4992F24A8676400B667CB /* ArticleArray.swift in Sources */,
|
||||
51E4994424A8713C00B667CB /* RefreshInterval.swift in Sources */,
|
||||
51E498F824A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
||||
51E4996A24A8762D00B667CB /* ExtractedArticle.swift in Sources */,
|
||||
51E498F124A8085D00B667CB /* StarredFeedDelegate.swift in Sources */,
|
||||
51E498FF24A808BB00B667CB /* SingleFaviconDownloader.swift in Sources */,
|
||||
51E4997224A8784300B667CB /* DefaultFeedsImporter.swift in Sources */,
|
||||
51E4990D24A808C500B667CB /* RSHTMLMetadata+Extension.swift in Sources */,
|
||||
51E4995C24A875F300B667CB /* ArticleRenderer.swift in Sources */,
|
||||
51E4992324A8095700B667CB /* URL-Extensions.swift in Sources */,
|
||||
51E4993624A867E800B667CB /* UserInfoKey.swift in Sources */,
|
||||
51E4990924A808C500B667CB /* WebFeedIconDownloader.swift in Sources */,
|
||||
51E498F524A8085D00B667CB /* TodayFeedDelegate.swift in Sources */,
|
||||
51E4990B24A808C500B667CB /* ImageDownloader.swift in Sources */,
|
||||
51E498F424A8085D00B667CB /* SmartFeedDelegate.swift in Sources */,
|
||||
51E4993024A8676400B667CB /* ArticleSorter.swift in Sources */,
|
||||
51E4990A24A808C500B667CB /* FeaturedImageDownloader.swift in Sources */,
|
||||
51E4993824A8680E00B667CB /* Reachability.swift in Sources */,
|
||||
51E4993224A8676400B667CB /* FetchRequestQueue.swift in Sources */,
|
||||
51E4991724A8090400B667CB /* ArticleUtilities.swift in Sources */,
|
||||
51E4991B24A8091000B667CB /* IconImage.swift in Sources */,
|
||||
51E4995424A8734D00B667CB /* ExtensionPointIdentifer.swift in Sources */,
|
||||
51C0516024A77DF800194D5E /* ContentView.swift in Sources */,
|
||||
51C0515E24A77DF800194D5E /* NetNewsWire_MultiplatformApp.swift in Sources */,
|
||||
51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */,
|
||||
51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
||||
51E4996B24A8762D00B667CB /* ArticleExtractor.swift in Sources */,
|
||||
51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */,
|
||||
51E4991D24A8092100B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
||||
51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
||||
51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */,
|
||||
51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */,
|
||||
51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */,
|
||||
51E4997024A8764C00B667CB /* ActivityManager.swift in Sources */,
|
||||
51E4990F24A808CC00B667CB /* HTMLMetadataDownloader.swift in Sources */,
|
||||
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 */,
|
||||
51E4991E24A8094300B667CB /* RSImage-AppIcons.swift in Sources */,
|
||||
51E4991324A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */,
|
||||
51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */,
|
||||
51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */,
|
||||
51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */,
|
||||
51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */,
|
||||
51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */,
|
||||
51E4990324A808BB00B667CB /* FaviconDownloader.swift in Sources */,
|
||||
51E4990224A808BB00B667CB /* ColorHash.swift in Sources */,
|
||||
51E4991924A8090A00B667CB /* CacheCleaner.swift in Sources */,
|
||||
51E498F724A8085D00B667CB /* SearchTimelineFeedDelegate.swift in Sources */,
|
||||
51E4993524A867E800B667CB /* AppNotifications.swift in Sources */,
|
||||
51C0515E24A77DF800194D5E /* NetNewsWire.swift in Sources */,
|
||||
51E4993D24A870F800B667CB /* UserNotificationManager.swift in Sources */,
|
||||
51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
||||
51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */,
|
||||
51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4282,8 +4635,70 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
51E4993A24A8708800B667CB /* AppDelegate.swift in Sources */,
|
||||
51E498CE24A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
||||
51E498C724A8085D00B667CB /* StarredFeedDelegate.swift in Sources */,
|
||||
51E498FA24A808BA00B667CB /* SingleFaviconDownloader.swift in Sources */,
|
||||
51E4993F24A8713B00B667CB /* ArticleStatusSyncTimer.swift in Sources */,
|
||||
51E4993724A8680E00B667CB /* Reachability.swift in Sources */,
|
||||
51E4994B24A8734C00B667CB /* SendToMicroBlogCommand.swift in Sources */,
|
||||
51E4996F24A8764C00B667CB /* ActivityType.swift in Sources */,
|
||||
51E4994E24A8734C00B667CB /* SendToMarsEditCommand.swift in Sources */,
|
||||
51E4996624A8760B00B667CB /* ArticleStyle.swift in Sources */,
|
||||
51E4996C24A8762D00B667CB /* ExtractedArticle.swift in Sources */,
|
||||
51E4990824A808C300B667CB /* RSHTMLMetadata+Extension.swift in Sources */,
|
||||
51E4992B24A8676300B667CB /* ArticleArray.swift in Sources */,
|
||||
51E4994D24A8734C00B667CB /* ExtensionPointIdentifer.swift in Sources */,
|
||||
51E4992224A8095600B667CB /* URL-Extensions.swift in Sources */,
|
||||
51E4990424A808C300B667CB /* WebFeedIconDownloader.swift in Sources */,
|
||||
51E498CB24A8085D00B667CB /* TodayFeedDelegate.swift in Sources */,
|
||||
51E4993324A867E700B667CB /* AppNotifications.swift in Sources */,
|
||||
51E4990624A808C300B667CB /* ImageDownloader.swift in Sources */,
|
||||
51E4994F24A8734C00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
|
||||
51E498CA24A8085D00B667CB /* SmartFeedDelegate.swift in Sources */,
|
||||
51E4990524A808C300B667CB /* FeaturedImageDownloader.swift in Sources */,
|
||||
51E4991624A8090300B667CB /* ArticleUtilities.swift in Sources */,
|
||||
51E4991A24A8090F00B667CB /* IconImage.swift in Sources */,
|
||||
51E4992724A80AAB00B667CB /* AppAssets.swift in Sources */,
|
||||
51E4995B24A875D500B667CB /* ArticlePasteboardWriter.swift in Sources */,
|
||||
51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */,
|
||||
51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
||||
51E4994124A8713B00B667CB /* RefreshInterval.swift in Sources */,
|
||||
51C0516124A77DF800194D5E /* ContentView.swift in Sources */,
|
||||
51C0515F24A77DF800194D5E /* NetNewsWire_MultiplatformApp.swift in Sources */,
|
||||
51E498C924A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
||||
51E498FC24A808BA00B667CB /* FaviconURLFinder.swift in Sources */,
|
||||
51E4991C24A8092000B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
||||
51E4994A24A8734C00B667CB /* ExtensionPointManager.swift in Sources */,
|
||||
51E4996D24A8762D00B667CB /* ArticleExtractor.swift in Sources */,
|
||||
51E4994024A8713B00B667CB /* AccountRefreshTimer.swift in Sources */,
|
||||
51E498CC24A8085D00B667CB /* SearchFeedDelegate.swift in Sources */,
|
||||
51E498C824A8085D00B667CB /* SmartFeedsController.swift in Sources */,
|
||||
51E4992C24A8676300B667CB /* ArticleSorter.swift in Sources */,
|
||||
51E4995024A8734C00B667CB /* ExtensionPoint.swift in Sources */,
|
||||
51E4990E24A808CC00B667CB /* HTMLMetadataDownloader.swift in Sources */,
|
||||
51E498FB24A808BA00B667CB /* FaviconGenerator.swift in Sources */,
|
||||
51E4996724A8760B00B667CB /* ArticleStylesManager.swift in Sources */,
|
||||
51E4996E24A8764C00B667CB /* ActivityManager.swift in Sources */,
|
||||
51E4995A24A873F900B667CB /* ErrorHandler.swift in Sources */,
|
||||
51E4991F24A8094300B667CB /* RSImage-AppIcons.swift in Sources */,
|
||||
51E4991224A808FB00B667CB /* AddWebFeedDefaultContainer.swift in Sources */,
|
||||
51E4993E24A870F900B667CB /* UserNotificationManager.swift in Sources */,
|
||||
51E4992E24A8676300B667CB /* FetchRequestQueue.swift in Sources */,
|
||||
51E498CF24A8085D00B667CB /* SmartFeed.swift in Sources */,
|
||||
51E4990724A808C300B667CB /* AuthorAvatarDownloader.swift in Sources */,
|
||||
51E4997424A8784400B667CB /* DefaultFeedsImporter.swift in Sources */,
|
||||
51E4992024A8095000B667CB /* RSImage-Extensions.swift in Sources */,
|
||||
51E498FE24A808BA00B667CB /* FaviconDownloader.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 */,
|
||||
51C0515F24A77DF800194D5E /* NetNewsWire.swift in Sources */,
|
||||
51E4992D24A8676300B667CB /* FetchRequestOperation.swift in Sources */,
|
||||
51E4992424A8098400B667CB /* SmartFeedPasteboardWriter.swift in Sources */,
|
||||
51E4991424A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
||||
51E4991024A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
import RSWeb
|
||||
|
||||
|
@ -28,6 +29,8 @@ final class SingleFaviconDownloader {
|
|||
var iconImage: IconImage?
|
||||
let homePageURL: String?
|
||||
|
||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "SingleFaviconDownloader")
|
||||
|
||||
private var lastDownloadAttemptDate: Date
|
||||
private var diskStatus = DiskStatus.unknown
|
||||
private var diskCache: BinaryDiskCache
|
||||
|
@ -145,7 +148,7 @@ private extension SingleFaviconDownloader {
|
|||
}
|
||||
|
||||
if let error = error {
|
||||
appDelegate.logMessage("Error downloading favicon at \(url): \(error)", type: .warning)
|
||||
os_log(.info, log: self.log, "Error downloading image at %@: %@.", url.absoluteString, error.localizedDescription)
|
||||
}
|
||||
|
||||
completion(nil)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import RSCore
|
||||
import RSWeb
|
||||
|
||||
|
@ -17,6 +18,8 @@ extension Notification.Name {
|
|||
|
||||
final class ImageDownloader {
|
||||
|
||||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ImageDownloader")
|
||||
|
||||
private let folder: String
|
||||
private var diskCache: BinaryDiskCache
|
||||
private let queue: DispatchQueue
|
||||
|
@ -112,7 +115,7 @@ private extension ImageDownloader {
|
|||
self.badURLs.insert(url)
|
||||
}
|
||||
if let error = error {
|
||||
appDelegate.logMessage("Error downloading image at \(url): \(error)", type: .warning)
|
||||
os_log(.info, log: self.log, "Error downloading image at %@: %@.", url, error.localizedDescription)
|
||||
}
|
||||
|
||||
completion(nil)
|
||||
|
|
|
@ -13,9 +13,9 @@ import RSCore
|
|||
struct DefaultFeedsImporter {
|
||||
|
||||
static func importDefaultFeeds(account: Account) {
|
||||
appDelegate.logDebugMessage("Importing default feeds.")
|
||||
let defaultFeedsURL = Bundle.main.url(forResource: "DefaultFeeds", withExtension: "opml")!
|
||||
AccountManager.shared.defaultAccount.importOPML(defaultFeedsURL) { result in }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -17,16 +17,6 @@ protocol PseudoFeed: class, Feed, SmallIconProvider, PasteboardWriterOwner {
|
|||
|
||||
}
|
||||
|
||||
private var smartFeedIcon: RSImage = {
|
||||
return RSImage(named: NSImage.smartBadgeTemplateName)!
|
||||
}()
|
||||
|
||||
extension PseudoFeed {
|
||||
|
||||
var smallIcon: RSImage? {
|
||||
return smartFeedIcon
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
import UIKit
|
||||
|
@ -38,14 +28,10 @@ protocol PseudoFeed: class, Feed, SmallIconProvider {
|
|||
|
||||
}
|
||||
|
||||
private var smartFeedIcon: UIImage = {
|
||||
return AppAssets.smartFeedImage
|
||||
}()
|
||||
#endif
|
||||
|
||||
extension PseudoFeed {
|
||||
var smallIcon: UIImage? {
|
||||
return smartFeedIcon
|
||||
var smallIcon: RSImage? {
|
||||
return AppAssets.smartFeedImage
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue