Refactor RefreshTimer code out into a separate class from AppDelegate so that it can be reused on iOS.

This commit is contained in:
Maurice Parker 2019-04-23 11:20:44 -05:00
parent 2a839a3b92
commit 66e4180a8c
4 changed files with 116 additions and 62 deletions

View File

@ -23,13 +23,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
var authorAvatarDownloader: AuthorAvatarDownloader! var authorAvatarDownloader: AuthorAvatarDownloader!
var feedIconDownloader: FeedIconDownloader! var feedIconDownloader: FeedIconDownloader!
var appName: String! var appName: String!
var refreshTimer: Timer? var refreshTimer: RefreshTimer?
var lastTimedRefresh: Date?
let launchTime = Date()
var shuttingDown = false { var shuttingDown = false {
didSet { didSet {
if shuttingDown { if shuttingDown {
invalidateRefreshTimer() refreshTimer?.shuttingDown = shuttingDown
refreshTimer?.invalidate()
} }
} }
} }
@ -159,8 +158,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
} }
#endif #endif
refreshTimer = RefreshTimer(delegate: self)
#if DEBUG #if DEBUG
updateRefreshTimer() refreshTimer!.update()
#endif #endif
#if !MAC_APP_STORE #if !MAC_APP_STORE
@ -187,13 +188,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
func applicationDidBecomeActive(_ notification: Notification) { func applicationDidBecomeActive(_ notification: Notification) {
// Its possible theres a refresh timer set to go off in the past. // Its possible theres a refresh timer set to go off in the past.
// In that case, refresh now and update the timer. // In that case, refresh now and update the timer.
if let timer = refreshTimer { refreshTimer?.fireOldTimer()
if timer.fireDate < Date() {
if AppDefaults.refreshInterval != .manually {
timedRefresh(nil)
}
}
}
} }
func applicationDidResignActive(_ notification: Notification) { func applicationDidResignActive(_ notification: Notification) {
@ -237,7 +232,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
@objc func userDefaultsDidChange(_ note: Notification) { @objc func userDefaultsDidChange(_ note: Notification) {
updateSortMenuItems() updateSortMenuItems()
updateRefreshTimer() refreshTimer?.update()
} }
// MARK: Main Window // MARK: Main Window
@ -281,54 +276,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
return true return true
} }
// MARK: Timed Refresh
@objc func timedRefresh(_ sender: Timer?) {
guard !shuttingDown else {
return
}
lastTimedRefresh = Date()
updateRefreshTimer()
refreshAll(self)
}
private func invalidateRefreshTimer() {
guard let timer = refreshTimer else {
return
}
if timer.isValid {
timer.invalidate()
}
refreshTimer = nil
}
private func updateRefreshTimer() {
guard !shuttingDown else {
return
}
let refreshInterval = AppDefaults.refreshInterval
if refreshInterval == .manually {
invalidateRefreshTimer()
return
}
let lastRefreshDate = lastTimedRefresh ?? launchTime
let secondsToAdd = refreshInterval.inSeconds()
var nextRefreshTime = lastRefreshDate.addingTimeInterval(secondsToAdd)
if nextRefreshTime < Date() {
nextRefreshTime = Date().addingTimeInterval(secondsToAdd)
}
if let currentNextFireDate = refreshTimer?.fireDate, currentNextFireDate == nextRefreshTime {
return
}
invalidateRefreshTimer()
let timer = Timer(fireAt: nextRefreshTime, interval: 0, target: self, selector: #selector(timedRefresh(_:)), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
refreshTimer = timer
print("Next refresh date: \(nextRefreshTime)")
}
// MARK: Add Feed // MARK: Add Feed
func addFeed(_ urlString: String?, name: String? = nil, folder: Folder? = nil) { func addFeed(_ urlString: String?, name: String? = nil, folder: Folder? = nil) {
@ -614,3 +561,10 @@ extension AppDelegate : ScriptingAppDelegate {
} }
} }
extension AppDelegate: RefreshTimerDelegate {
func refresh() {
AccountManager.shared.refreshAll()
}
}

View File

@ -24,6 +24,8 @@
5183CCE3226F314C0010922C /* ProgressTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE2226F314C0010922C /* ProgressTableViewController.swift */; }; 5183CCE3226F314C0010922C /* ProgressTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE2226F314C0010922C /* ProgressTableViewController.swift */; };
5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; }; 5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
5183CCE6226F4E110010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; }; 5183CCE6226F4E110010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
5183CCE8226F68D90010922C /* RefreshTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE7226F68D90010922C /* RefreshTimer.swift */; };
5183CCE9226F68D90010922C /* RefreshTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE7226F68D90010922C /* RefreshTimer.swift */; };
519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; }; 519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; };
51C451A9226377C200C03939 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; }; 51C451A9226377C200C03939 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; };
51C451AA226377C200C03939 /* ArticlesDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 51C451AA226377C200C03939 /* ArticlesDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -620,6 +622,7 @@
5183CCDE226F1FCC0010922C /* UINavigationController+Progress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Progress.swift"; sourceTree = "<group>"; }; 5183CCDE226F1FCC0010922C /* UINavigationController+Progress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Progress.swift"; sourceTree = "<group>"; };
5183CCE2226F314C0010922C /* ProgressTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressTableViewController.swift; sourceTree = "<group>"; }; 5183CCE2226F314C0010922C /* ProgressTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressTableViewController.swift; sourceTree = "<group>"; };
5183CCE4226F4DFA0010922C /* RefreshInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshInterval.swift; sourceTree = "<group>"; }; 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshInterval.swift; sourceTree = "<group>"; };
5183CCE7226F68D90010922C /* RefreshTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshTimer.swift; sourceTree = "<group>"; };
519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = "<group>"; }; 519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = "<group>"; };
51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard-Extensions.swift"; sourceTree = "<group>"; }; 51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard-Extensions.swift"; sourceTree = "<group>"; };
51C4524F226506F400C03939 /* UIImage-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage-Extensions.swift"; sourceTree = "<group>"; }; 51C4524F226506F400C03939 /* UIImage-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage-Extensions.swift"; sourceTree = "<group>"; };
@ -922,6 +925,15 @@
path = Progress; path = Progress;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
5183CCEA226F70350010922C /* Refresh */ = {
isa = PBXGroup;
children = (
5183CCE4226F4DFA0010922C /* RefreshInterval.swift */,
5183CCE7226F68D90010922C /* RefreshTimer.swift */,
);
path = Refresh;
sourceTree = "<group>";
};
51C45245226506C800C03939 /* Extensions */ = { 51C45245226506C800C03939 /* Extensions */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1220,7 +1232,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
849A97581ED9EB0D007D329B /* ArticleUtilities.swift */, 849A97581ED9EB0D007D329B /* ArticleUtilities.swift */,
5183CCE4226F4DFA0010922C /* RefreshInterval.swift */,
84411E701FE5FBFA004B527F /* SmallIconProvider.swift */, 84411E701FE5FBFA004B527F /* SmallIconProvider.swift */,
); );
path = Data; path = Data;
@ -1451,6 +1462,7 @@
845213211FCA5B10003B6E93 /* Images */, 845213211FCA5B10003B6E93 /* Images */,
8426119C1FCB6ED40086A189 /* HTMLMetadata */, 8426119C1FCB6ED40086A189 /* HTMLMetadata */,
84F3EE0420DEC97E003FADEB /* FeedFinder */, 84F3EE0420DEC97E003FADEB /* FeedFinder */,
5183CCEA226F70350010922C /* Refresh */,
849A97561ED9EB0D007D329B /* Data */, 849A97561ED9EB0D007D329B /* Data */,
512E08DD22687FA000BDCFDD /* Tree */, 512E08DD22687FA000BDCFDD /* Tree */,
849A97961ED9EFAA007D329B /* Extensions */, 849A97961ED9EFAA007D329B /* Extensions */,
@ -2207,6 +2219,7 @@
512E094D2268B8AB00BDCFDD /* DeleteCommand.swift in Sources */, 512E094D2268B8AB00BDCFDD /* DeleteCommand.swift in Sources */,
51C452AC22650FD200C03939 /* AppNotifications.swift in Sources */, 51C452AC22650FD200C03939 /* AppNotifications.swift in Sources */,
51C452762265091600C03939 /* MasterTimelineViewController.swift in Sources */, 51C452762265091600C03939 /* MasterTimelineViewController.swift in Sources */,
5183CCE9226F68D90010922C /* RefreshTimer.swift in Sources */,
51C452882265093600C03939 /* AddFeedViewController.swift in Sources */, 51C452882265093600C03939 /* AddFeedViewController.swift in Sources */,
51C4527A2265091600C03939 /* SingleLineUILabelSizer.swift in Sources */, 51C4527A2265091600C03939 /* SingleLineUILabelSizer.swift in Sources */,
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */, 51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
@ -2306,6 +2319,7 @@
849A97981ED9EFAA007D329B /* Node-Extensions.swift in Sources */, 849A97981ED9EFAA007D329B /* Node-Extensions.swift in Sources */,
849EE70F203919360082A1EA /* AppImages.swift in Sources */, 849EE70F203919360082A1EA /* AppImages.swift in Sources */,
849A97531ED9EAC0007D329B /* AddFeedController.swift in Sources */, 849A97531ED9EAC0007D329B /* AddFeedController.swift in Sources */,
5183CCE8226F68D90010922C /* RefreshTimer.swift in Sources */,
849A97831ED9EC63007D329B /* SidebarStatusBarView.swift in Sources */, 849A97831ED9EC63007D329B /* SidebarStatusBarView.swift in Sources */,
84F2D5381FC22FCC00998D64 /* TodayFeedDelegate.swift in Sources */, 84F2D5381FC22FCC00998D64 /* TodayFeedDelegate.swift in Sources */,
841ABA5E20145E9200980E11 /* FolderInspectorViewController.swift in Sources */, 841ABA5E20145E9200980E11 /* FolderInspectorViewController.swift in Sources */,

View File

@ -0,0 +1,86 @@
//
// RefreshTimer.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/23/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import Foundation
protocol RefreshTimerDelegate: class {
func refresh()
}
class RefreshTimer {
var shuttingDown = false
private weak var delegate: RefreshTimerDelegate?
private var internalTimer: Timer?
private var lastTimedRefresh: Date?
private let launchTime = Date()
init(delegate: RefreshTimerDelegate) {
self.delegate = delegate
}
func fireOldTimer() {
if let timer = internalTimer {
if timer.fireDate < Date() {
if AppDefaults.refreshInterval != .manually {
timedRefresh(nil)
}
}
}
}
func invalidate() {
guard let timer = internalTimer else {
return
}
if timer.isValid {
timer.invalidate()
}
internalTimer = nil
}
func update() {
guard !shuttingDown else {
return
}
let refreshInterval = AppDefaults.refreshInterval
if refreshInterval == .manually {
invalidate()
return
}
let lastRefreshDate = lastTimedRefresh ?? launchTime
let secondsToAdd = refreshInterval.inSeconds()
var nextRefreshTime = lastRefreshDate.addingTimeInterval(secondsToAdd)
if nextRefreshTime < Date() {
nextRefreshTime = Date().addingTimeInterval(secondsToAdd)
}
if let currentNextFireDate = internalTimer?.fireDate, currentNextFireDate == nextRefreshTime {
return
}
invalidate()
let timer = Timer(fireAt: nextRefreshTime, interval: 0, target: self, selector: #selector(timedRefresh(_:)), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
internalTimer = timer
print("Next refresh date: \(nextRefreshTime)")
}
@objc func timedRefresh(_ sender: Timer?) {
guard !shuttingDown else {
return
}
lastTimedRefresh = Date()
update()
delegate?.refresh()
}
}