mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-02-05 13:27:45 +01:00
Merge pull request #2210 from philviso/swiftui-progressview
Implement iOS progress view
This commit is contained in:
commit
208271d6b4
@ -69,7 +69,7 @@ struct AppAssets {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
static var faviconTemplateImage: RSImage = {
|
static var faviconTemplateImage: RSImage = {
|
||||||
return RSImage(named: "FaviconTemplateImage")!
|
return RSImage(named: "faviconTemplateImage")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var settingsImage: Image = {
|
static var settingsImage: Image = {
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// PreviewProvider+RefreshProgressModel.swift
|
||||||
|
// NetNewsWire
|
||||||
|
//
|
||||||
|
// Created by Phil Viso on 7/3/20.
|
||||||
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Account
|
||||||
|
import Foundation
|
||||||
|
import RSWeb
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension PreviewProvider {
|
||||||
|
|
||||||
|
static func refreshProgressModel(lastRefreshDate: Date?,
|
||||||
|
tasksCompleted: Int,
|
||||||
|
totalTasks: Int) -> RefreshProgressModel {
|
||||||
|
return RefreshProgressModel { () -> Date? in
|
||||||
|
return lastRefreshDate
|
||||||
|
} combinedRefreshProgressProvider: { () -> CombinedRefreshProgress in
|
||||||
|
let progress = DownloadProgress(numberOfTasks: totalTasks)
|
||||||
|
progress.numberRemaining = totalTasks - tasksCompleted
|
||||||
|
|
||||||
|
return CombinedRefreshProgress(downloadProgressArray: [progress])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
101
Multiplatform/Shared/RefreshProgressModel.swift
Normal file
101
Multiplatform/Shared/RefreshProgressModel.swift
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// RefreshProgressModel.swift
|
||||||
|
// NetNewsWire
|
||||||
|
//
|
||||||
|
// Created by Phil Viso on 7/2/20.
|
||||||
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Account
|
||||||
|
import Combine
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
class RefreshProgressModel: ObservableObject {
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
case refreshProgress(Float)
|
||||||
|
case lastRefreshDateText(String)
|
||||||
|
case none
|
||||||
|
}
|
||||||
|
|
||||||
|
@Published var state = State.none
|
||||||
|
|
||||||
|
private static var dateFormatter: RelativeDateTimeFormatter = {
|
||||||
|
let formatter = RelativeDateTimeFormatter()
|
||||||
|
formatter.dateTimeStyle = .named
|
||||||
|
|
||||||
|
return formatter
|
||||||
|
}()
|
||||||
|
|
||||||
|
private let lastRefreshDate: () -> Date?
|
||||||
|
private let combinedRefreshProgress: () -> CombinedRefreshProgress
|
||||||
|
|
||||||
|
private static let lastRefreshDateTextUpdateInterval = 60
|
||||||
|
private static let lastRefreshDateTextRelativeDateFormattingThreshold = 60.0
|
||||||
|
|
||||||
|
init(lastRefreshDateProvider: @escaping () -> Date?,
|
||||||
|
combinedRefreshProgressProvider: @escaping () -> CombinedRefreshProgress) {
|
||||||
|
self.lastRefreshDate = lastRefreshDateProvider
|
||||||
|
self.combinedRefreshProgress = combinedRefreshProgressProvider
|
||||||
|
|
||||||
|
updateState()
|
||||||
|
|
||||||
|
observeRefreshProgress()
|
||||||
|
scheduleLastRefreshDateTextUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Observing account changes
|
||||||
|
|
||||||
|
private func observeRefreshProgress() {
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(updateState), name: .AccountRefreshProgressDidChange, object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Refreshing state
|
||||||
|
|
||||||
|
@objc private func updateState() {
|
||||||
|
let progress = combinedRefreshProgress()
|
||||||
|
|
||||||
|
if !progress.isComplete {
|
||||||
|
let fractionCompleted = Float(progress.numberCompleted) / Float(progress.numberOfTasks)
|
||||||
|
self.state = .refreshProgress(fractionCompleted)
|
||||||
|
} else if let lastRefreshDate = self.lastRefreshDate() {
|
||||||
|
let text = localizedLastRefreshText(lastRefreshDate: lastRefreshDate)
|
||||||
|
self.state = .lastRefreshDateText(text)
|
||||||
|
} else {
|
||||||
|
self.state = .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func scheduleLastRefreshDateTextUpdate() {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(Self.lastRefreshDateTextUpdateInterval)) {
|
||||||
|
self.updateState()
|
||||||
|
self.scheduleLastRefreshDateTextUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func localizedLastRefreshText(lastRefreshDate: Date) -> String {
|
||||||
|
let now = Date()
|
||||||
|
|
||||||
|
if now > lastRefreshDate.addingTimeInterval(Self.lastRefreshDateTextRelativeDateFormattingThreshold) {
|
||||||
|
let localizedDate = Self.dateFormatter.localizedString(for: lastRefreshDate, relativeTo: now)
|
||||||
|
let formatString = NSLocalizedString("Updated %@", comment: "Updated") as NSString
|
||||||
|
|
||||||
|
return NSString.localizedStringWithFormat(formatString, localizedDate) as String
|
||||||
|
} else {
|
||||||
|
return NSLocalizedString("Updated Just Now", comment: "Updated Just Now")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RefreshProgressModel {
|
||||||
|
|
||||||
|
convenience init() {
|
||||||
|
self.init(
|
||||||
|
lastRefreshDateProvider: { AccountManager.shared.lastArticleFetchEndTime },
|
||||||
|
combinedRefreshProgressProvider: { AccountManager.shared.combinedRefreshProgress }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -11,10 +11,19 @@ import Account
|
|||||||
|
|
||||||
final class SceneModel: ObservableObject {
|
final class SceneModel: ObservableObject {
|
||||||
|
|
||||||
|
@Published var refreshProgressState = RefreshProgressModel.State.none
|
||||||
|
|
||||||
var sidebarModel: SidebarModel?
|
var sidebarModel: SidebarModel?
|
||||||
var timelineModel: TimelineModel?
|
var timelineModel: TimelineModel?
|
||||||
var articleModel: ArticleModel?
|
var articleModel: ArticleModel?
|
||||||
|
|
||||||
|
private let refreshProgressModel: RefreshProgressModel
|
||||||
|
|
||||||
|
init(refreshProgressModel: RefreshProgressModel = RefreshProgressModel()) {
|
||||||
|
self.refreshProgressModel = refreshProgressModel
|
||||||
|
self.refreshProgressModel.$state.assign(to: self.$refreshProgressState)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: SidebarModelDelegate
|
// MARK: SidebarModelDelegate
|
||||||
|
57
Multiplatform/Shared/Sidebar/RefreshProgressView.swift
Normal file
57
Multiplatform/Shared/Sidebar/RefreshProgressView.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// RefreshProgressView.swift
|
||||||
|
// NetNewsWire
|
||||||
|
//
|
||||||
|
// Created by Phil Viso on 7/2/20.
|
||||||
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct RefreshProgressView: View {
|
||||||
|
|
||||||
|
@EnvironmentObject var sceneModel: SceneModel
|
||||||
|
|
||||||
|
@ViewBuilder var body: some View {
|
||||||
|
switch sceneModel.refreshProgressState {
|
||||||
|
case .refreshProgress(let progress):
|
||||||
|
ProgressView(value: progress)
|
||||||
|
.frame(width: progressViewWidth())
|
||||||
|
case .lastRefreshDateText(let text):
|
||||||
|
Text(text)
|
||||||
|
.lineLimit(1)
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
case .none:
|
||||||
|
EmptyView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK -
|
||||||
|
|
||||||
|
private func progressViewWidth() -> CGFloat {
|
||||||
|
#if os(iOS)
|
||||||
|
return 100.0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
return 40.0
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RefreshProgressView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
Group {
|
||||||
|
RefreshProgressView()
|
||||||
|
.environmentObject(refreshProgressModel(lastRefreshDate: nil, tasksCompleted: 1, totalTasks: 2))
|
||||||
|
.previewDisplayName("Refresh in progress")
|
||||||
|
|
||||||
|
RefreshProgressView()
|
||||||
|
.environmentObject(refreshProgressModel(lastRefreshDate: Date(timeIntervalSinceNow: -120.0), tasksCompleted: 0, totalTasks: 0))
|
||||||
|
.previewDisplayName("Last refreshed with date")
|
||||||
|
}
|
||||||
|
.previewLayout(.sizeThatFits)
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
struct SidebarToolbar: ViewModifier {
|
struct SidebarToolbar: ViewModifier {
|
||||||
|
|
||||||
@EnvironmentObject private var appSettings: AppDefaults
|
@EnvironmentObject private var appSettings: AppDefaults
|
||||||
@ -25,23 +24,25 @@ struct SidebarToolbar: ViewModifier {
|
|||||||
AppAssets.settingsImage
|
AppAssets.settingsImage
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
Spacer()
|
|
||||||
}).help("Settings")
|
}).help("Settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolbarItem(placement: .automatic, content: {
|
ToolbarItem {
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("Last updated")
|
}
|
||||||
.font(.caption)
|
|
||||||
.foregroundColor(.secondary)
|
ToolbarItem(placement: .automatic) {
|
||||||
|
RefreshProgressView()
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolbarItem {
|
||||||
Spacer()
|
Spacer()
|
||||||
})
|
}
|
||||||
|
|
||||||
ToolbarItem(placement: .automatic, content: {
|
ToolbarItem(placement: .automatic, content: {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
viewModel.showActionSheet = true
|
viewModel.showActionSheet = true
|
||||||
}, label: {
|
}, label: {
|
||||||
Spacer()
|
|
||||||
AppAssets.addMenuImage
|
AppAssets.addMenuImage
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
|
@ -1031,6 +1031,12 @@
|
|||||||
FF3ABF13232599810074C542 /* ArticleSorterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF09232599450074C542 /* ArticleSorterTests.swift */; };
|
FF3ABF13232599810074C542 /* ArticleSorterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF09232599450074C542 /* ArticleSorterTests.swift */; };
|
||||||
FF3ABF1523259DDB0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
FF3ABF1523259DDB0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
||||||
FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
||||||
|
FF64D0E724AF53EE0084080A /* RefreshProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF64D0C424AF53EE0084080A /* RefreshProgressModel.swift */; };
|
||||||
|
FF64D0E824AF53EE0084080A /* RefreshProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF64D0C424AF53EE0084080A /* RefreshProgressModel.swift */; };
|
||||||
|
FF64D0E924AF53EE0084080A /* RefreshProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF64D0E624AF53EE0084080A /* RefreshProgressView.swift */; };
|
||||||
|
FF64D0EA24AF53EE0084080A /* RefreshProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF64D0E624AF53EE0084080A /* RefreshProgressView.swift */; };
|
||||||
|
FFA2BBD624AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA2BBD524AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift */; };
|
||||||
|
FFA2BBD724AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA2BBD524AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift */; };
|
||||||
FFD43E412340F488009E5CA3 /* MarkAsReadAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD43E372340F320009E5CA3 /* MarkAsReadAlertController.swift */; };
|
FFD43E412340F488009E5CA3 /* MarkAsReadAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD43E372340F320009E5CA3 /* MarkAsReadAlertController.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@ -2223,6 +2229,9 @@
|
|||||||
FA80C13D24B072AA00974098 /* AddFolderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddFolderModel.swift; sourceTree = "<group>"; };
|
FA80C13D24B072AA00974098 /* AddFolderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddFolderModel.swift; sourceTree = "<group>"; };
|
||||||
FF3ABF09232599450074C542 /* ArticleSorterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorterTests.swift; sourceTree = "<group>"; };
|
FF3ABF09232599450074C542 /* ArticleSorterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorterTests.swift; sourceTree = "<group>"; };
|
||||||
FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorter.swift; sourceTree = "<group>"; };
|
FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorter.swift; sourceTree = "<group>"; };
|
||||||
|
FF64D0C424AF53EE0084080A /* RefreshProgressModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshProgressModel.swift; sourceTree = "<group>"; };
|
||||||
|
FF64D0E624AF53EE0084080A /* RefreshProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshProgressView.swift; sourceTree = "<group>"; };
|
||||||
|
FFA2BBD524AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreviewProvider+RefreshProgressModel.swift"; sourceTree = "<group>"; };
|
||||||
FFD43E372340F320009E5CA3 /* MarkAsReadAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkAsReadAlertController.swift; sourceTree = "<group>"; };
|
FFD43E372340F320009E5CA3 /* MarkAsReadAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkAsReadAlertController.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@ -2589,6 +2598,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
514E6BFE24AD255D00AC6F6E /* PreviewArticles.swift */,
|
514E6BFE24AD255D00AC6F6E /* PreviewArticles.swift */,
|
||||||
|
FFA2BBD524AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift */,
|
||||||
);
|
);
|
||||||
path = Previews;
|
path = Previews;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2786,6 +2796,7 @@
|
|||||||
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */,
|
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */,
|
||||||
51E4995824A873F900B667CB /* ErrorHandler.swift */,
|
51E4995824A873F900B667CB /* ErrorHandler.swift */,
|
||||||
51C0513624A77DF700194D5E /* MainApp.swift */,
|
51C0513624A77DF700194D5E /* MainApp.swift */,
|
||||||
|
FF64D0C424AF53EE0084080A /* RefreshProgressModel.swift */,
|
||||||
51E499D724A912C200B667CB /* SceneModel.swift */,
|
51E499D724A912C200B667CB /* SceneModel.swift */,
|
||||||
51E49A0224A91FF600B667CB /* SceneNavigationView.swift */,
|
51E49A0224A91FF600B667CB /* SceneNavigationView.swift */,
|
||||||
51C0513824A77DF800194D5E /* Assets.xcassets */,
|
51C0513824A77DF800194D5E /* Assets.xcassets */,
|
||||||
@ -2972,6 +2983,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */,
|
172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */,
|
||||||
|
FF64D0E624AF53EE0084080A /* RefreshProgressView.swift */,
|
||||||
51E499FF24A91FC100B667CB /* RegularSidebarContainerView.swift */,
|
51E499FF24A91FC100B667CB /* RegularSidebarContainerView.swift */,
|
||||||
51392D1A24AC19A000BE0D35 /* SidebarExpandedContainers.swift */,
|
51392D1A24AC19A000BE0D35 /* SidebarExpandedContainers.swift */,
|
||||||
51408B7D24A9EC6F0073CF4E /* SidebarItem.swift */,
|
51408B7D24A9EC6F0073CF4E /* SidebarItem.swift */,
|
||||||
@ -4818,6 +4830,7 @@
|
|||||||
51392D1B24AC19A000BE0D35 /* SidebarExpandedContainers.swift in Sources */,
|
51392D1B24AC19A000BE0D35 /* SidebarExpandedContainers.swift in Sources */,
|
||||||
51E4992F24A8676400B667CB /* ArticleArray.swift in Sources */,
|
51E4992F24A8676400B667CB /* ArticleArray.swift in Sources */,
|
||||||
51E498F824A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
51E498F824A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
||||||
|
FF64D0E724AF53EE0084080A /* RefreshProgressModel.swift in Sources */,
|
||||||
51E4996A24A8762D00B667CB /* ExtractedArticle.swift in Sources */,
|
51E4996A24A8762D00B667CB /* ExtractedArticle.swift in Sources */,
|
||||||
51919FF124AB864A00541E64 /* TimelineModel.swift in Sources */,
|
51919FF124AB864A00541E64 /* TimelineModel.swift in Sources */,
|
||||||
51E498F124A8085D00B667CB /* StarredFeedDelegate.swift in Sources */,
|
51E498F124A8085D00B667CB /* StarredFeedDelegate.swift in Sources */,
|
||||||
@ -4862,6 +4875,7 @@
|
|||||||
51E49A0324A91FF600B667CB /* SceneNavigationView.swift in Sources */,
|
51E49A0324A91FF600B667CB /* SceneNavigationView.swift in Sources */,
|
||||||
51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */,
|
51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */,
|
||||||
51E4991D24A8092100B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
51E4991D24A8092100B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
||||||
|
FF64D0E924AF53EE0084080A /* RefreshProgressView.swift in Sources */,
|
||||||
51E499FD24A9137600B667CB /* SidebarModel.swift in Sources */,
|
51E499FD24A9137600B667CB /* SidebarModel.swift in Sources */,
|
||||||
51A576BE24AE637400078888 /* ArticleView.swift in Sources */,
|
51A576BE24AE637400078888 /* ArticleView.swift in Sources */,
|
||||||
5181C66224B0C326002E0F70 /* SettingsModel.swift in Sources */,
|
5181C66224B0C326002E0F70 /* SettingsModel.swift in Sources */,
|
||||||
@ -4908,6 +4922,7 @@
|
|||||||
51E4993D24A870F800B667CB /* UserNotificationManager.swift in Sources */,
|
51E4993D24A870F800B667CB /* UserNotificationManager.swift in Sources */,
|
||||||
51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
51E4991524A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
||||||
51919FEE24AB85E400541E64 /* TimelineContainerView.swift in Sources */,
|
51919FEE24AB85E400541E64 /* TimelineContainerView.swift in Sources */,
|
||||||
|
FFA2BBD624AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift in Sources */,
|
||||||
51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */,
|
51E4995724A8734D00B667CB /* ExtensionPoint.swift in Sources */,
|
||||||
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */,
|
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */,
|
||||||
51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
51E4991124A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
||||||
@ -4965,6 +4980,7 @@
|
|||||||
51E498C924A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
51E498C924A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
||||||
51E498FC24A808BA00B667CB /* FaviconURLFinder.swift in Sources */,
|
51E498FC24A808BA00B667CB /* FaviconURLFinder.swift in Sources */,
|
||||||
51E4991C24A8092000B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
51E4991C24A8092000B667CB /* NSAttributedString+NetNewsWire.swift in Sources */,
|
||||||
|
FF64D0E824AF53EE0084080A /* RefreshProgressModel.swift in Sources */,
|
||||||
51E499D924A912C200B667CB /* SceneModel.swift in Sources */,
|
51E499D924A912C200B667CB /* SceneModel.swift in Sources */,
|
||||||
51919FB424AAB97900541E64 /* FeedIconImageLoader.swift in Sources */,
|
51919FB424AAB97900541E64 /* FeedIconImageLoader.swift in Sources */,
|
||||||
51E4994A24A8734C00B667CB /* ExtensionPointManager.swift in Sources */,
|
51E4994A24A8734C00B667CB /* ExtensionPointManager.swift in Sources */,
|
||||||
@ -5011,10 +5027,12 @@
|
|||||||
514E6C0024AD255D00AC6F6E /* PreviewArticles.swift in Sources */,
|
514E6C0024AD255D00AC6F6E /* PreviewArticles.swift in Sources */,
|
||||||
1729529524AA1CAA00D65E66 /* GeneralPreferencesView.swift in Sources */,
|
1729529524AA1CAA00D65E66 /* GeneralPreferencesView.swift in Sources */,
|
||||||
1729529424AA1CAA00D65E66 /* AdvancedPreferencesView.swift in Sources */,
|
1729529424AA1CAA00D65E66 /* AdvancedPreferencesView.swift in Sources */,
|
||||||
|
FFA2BBD724AF751100B3149D /* PreviewProvider+RefreshProgressModel.swift in Sources */,
|
||||||
51E4992D24A8676300B667CB /* FetchRequestOperation.swift in Sources */,
|
51E4992D24A8676300B667CB /* FetchRequestOperation.swift in Sources */,
|
||||||
51E4992424A8098400B667CB /* SmartFeedPasteboardWriter.swift in Sources */,
|
51E4992424A8098400B667CB /* SmartFeedPasteboardWriter.swift in Sources */,
|
||||||
51E4991424A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
51E4991424A808FF00B667CB /* ArticleStringFormatter.swift in Sources */,
|
||||||
51A576BF24AE637400078888 /* ArticleView.swift in Sources */,
|
51A576BF24AE637400078888 /* ArticleView.swift in Sources */,
|
||||||
|
FF64D0EA24AF53EE0084080A /* RefreshProgressView.swift in Sources */,
|
||||||
51E4991024A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
51E4991024A808DE00B667CB /* SmallIconProvider.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user