Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.

Move background handling into Feed.swift for better state control #2285

Merged
merged 1 commit into from
Oct 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Classes/Issues/IssuesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ final class IssuesViewController:
emptyView.delegate = self
emptyView.button.isHidden = false
return emptyView
case .loading, .loadingNext:
case .loading, .loadingNext, .initial:
return nil
}
}
Expand Down
17 changes: 5 additions & 12 deletions Classes/Notifications/NotificationsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ import Squawk

final class NotificationsViewController: BaseListViewController2<Int>,
BaseListViewController2DataSource,
ForegroundHandlerDelegate,
FlatCacheListener,
TabNavRootViewControllerType,
BaseListViewController2EmptyDataSource
{
BaseListViewController2EmptyDataSource {

private let modelController: NotificationModelController
private let foreground = ForegroundHandler(threshold: 5 * 60)
private let inboxType: InboxType
private var notificationIDs = [String]()

Expand All @@ -32,11 +29,13 @@ BaseListViewController2EmptyDataSource
self.modelController = modelController
self.inboxType = inboxType

super.init(emptyErrorMessage: NSLocalizedString("Cannot load your inbox.", comment: ""))
super.init(
emptyErrorMessage: NSLocalizedString("Cannot load your inbox.", comment: ""),
backgroundThreshold: 5 * 60
)

self.dataSource = self
self.emptyDataSource = self
self.foreground.delegate = self

switch inboxType {
case .all: title = NSLocalizedString("All", comment: "")
Expand Down Expand Up @@ -283,12 +282,6 @@ BaseListViewController2EmptyDataSource
})
}

// MARK: ForegroundHandlerDelegate

func didForeground(handler: ForegroundHandler) {
feed.refreshHead()
}

// MARK: FlatCacheListener

func flatCacheDidUpdate(cache: FlatCache, update: FlatCache.Update) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ final class PullRequestReviewCommentsViewController: MessageViewController,
emptyView.delegate = self
emptyView.button.isHidden = false
return emptyView
case .loadingNext:
case .loadingNext, .initial:
return nil
case .loading:
return EmptyLoadingView()
Expand Down
63 changes: 60 additions & 3 deletions Classes/Systems/Feed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ protocol FeedDelegate: class {
final class Feed: NSObject, UIScrollViewDelegate {

enum Status {
case initial
case idle
case loading
case loadingNext
Expand All @@ -25,31 +26,54 @@ final class Feed: NSObject, UIScrollViewDelegate {
let swiftAdapter: ListSwiftAdapter
let collectionView: UICollectionView

public private(set) var status: Status = .idle
public private(set) var status: Status = .initial
private weak var delegate: FeedDelegate?
private let feedRefresh = FeedRefresh()
private let managesLayout: Bool
private let loadingView = EmptyLoadingView()

private let backgroundThreshold: CFTimeInterval?
private var backgroundTime: CFTimeInterval?

init(
viewController: UIViewController,
delegate: FeedDelegate,
collectionView: UICollectionView? = nil,
managesLayout: Bool = true
managesLayout: Bool = true,
backgroundThreshold: CFTimeInterval? = nil
) {
self.swiftAdapter = ListSwiftAdapter(viewController: viewController)
self.delegate = delegate
self.managesLayout = managesLayout
self.collectionView = collectionView
?? UICollectionView(frame: .zero, collectionViewLayout: ListCollectionViewLayout.basic())
self.backgroundThreshold = backgroundThreshold

super.init()

self.adapter.scrollViewDelegate = self

self.collectionView.alwaysBounceVertical = true
self.collectionView.backgroundColor = Styles.Colors.background
self.collectionView.refreshControl = feedRefresh.refreshControl
self.collectionView.keyboardDismissMode = .onDrag
feedRefresh.refreshControl.addTarget(self, action: #selector(Feed.onRefresh(sender:)), for: .valueChanged)

if backgroundThreshold != nil {
let center = NotificationCenter.default
center.addObserver(
self,
selector: #selector(didBecomeActive),
name: .UIApplicationDidBecomeActive,
object: nil
)
center.addObserver(
self,
selector: #selector(willResignActive),
name: .UIApplicationWillResignActive,
object: nil
)
}
}

// MARK: Public API
Expand Down Expand Up @@ -122,7 +146,7 @@ final class Feed: NSObject, UIScrollViewDelegate {
// MARK: Private API

private func refresh() {
guard status == .idle else { return }
guard status == .idle || status == .initial else { return }
status = .loading
delegate?.loadFromNetwork(feed: self)
}
Expand Down Expand Up @@ -150,4 +174,37 @@ final class Feed: NSObject, UIScrollViewDelegate {
}
}

// MARK: Notifications

@objc func willResignActive() {
backgroundTime = CACurrentMediaTime()
}

@objc func didBecomeActive() {
defer { backgroundTime = nil }

let refresh: (Bool) -> Void = { head in
// there seems to be a bug where refreshing while still becoming active messes up the iOS 11 header and
// refresh control. put an artificial delay to let the system cool down?
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
if head {
self.refreshHead()
} else {
self.refresh()
}
})
}

// if foreground and haven't done an initial load, refresh
// can occur when process is still alive after a background fetch
if status == .initial {
// dont refresh head since spinner will still be shown
refresh(false)
} else if let backgroundTime = self.backgroundTime,
let backgroundThreshold = self.backgroundThreshold,
CACurrentMediaTime() - backgroundTime > backgroundThreshold {
refresh(true)
}
}

}
58 changes: 0 additions & 58 deletions Classes/Systems/ForegroundHandler.swift

This file was deleted.

10 changes: 8 additions & 2 deletions Classes/View Controllers/BaseListViewController2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,22 @@ ListSwiftAdapterEmptyViewSource,
EmptyViewDelegate {

private let emptyErrorMessage: String
private let backgroundThreshold: CFTimeInterval?

public weak var dataSource: BaseListViewController2DataSource?
public weak var emptyDataSource: BaseListViewController2EmptyDataSource?

public private(set) lazy var feed: Feed = { Feed(viewController: self, delegate: self) }()
public private(set) lazy var feed: Feed = { Feed(
viewController: self,
delegate: self,
backgroundThreshold: backgroundThreshold
) }()
private var page: PageType?
private var hasError = false

init(emptyErrorMessage: String) {
init(emptyErrorMessage: String, backgroundThreshold: CFTimeInterval? = nil) {
self.emptyErrorMessage = emptyErrorMessage
self.backgroundThreshold = backgroundThreshold
super.init(nibName: nil, bundle: nil)
}

Expand Down
6 changes: 1 addition & 5 deletions Freetime.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,6 @@
29DB264A1FCA10A800C3D0C9 /* GithubHighlighting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29DB26491FCA10A800C3D0C9 /* GithubHighlighting.swift */; };
29DB5D152132227F00E408D9 /* InboxZeroLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29DB5D142132227F00E408D9 /* InboxZeroLoader.swift */; };
29DB5D192133418300E408D9 /* LocalNotificationsCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29DB5D182133418200E408D9 /* LocalNotificationsCache.swift */; };
29EB1EEF1F425E5100A200B4 /* ForegroundHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EB1EEE1F425E5100A200B4 /* ForegroundHandler.swift */; };
29EDFE7C1F65C580005BCCEB /* SplitViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EDFE7B1F65C580005BCCEB /* SplitViewTests.swift */; };
29EDFE821F661562005BCCEB /* RepositoryReadmeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EDFE811F661562005BCCEB /* RepositoryReadmeModel.swift */; };
29EDFE841F661776005BCCEB /* RepositoryReadmeSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EDFE831F661776005BCCEB /* RepositoryReadmeSectionController.swift */; };
Expand Down Expand Up @@ -926,7 +925,6 @@
29DB26491FCA10A800C3D0C9 /* GithubHighlighting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubHighlighting.swift; sourceTree = "<group>"; };
29DB5D142132227F00E408D9 /* InboxZeroLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxZeroLoader.swift; sourceTree = "<group>"; };
29DB5D182133418200E408D9 /* LocalNotificationsCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalNotificationsCache.swift; sourceTree = "<group>"; };
29EB1EEE1F425E5100A200B4 /* ForegroundHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForegroundHandler.swift; sourceTree = "<group>"; };
29EDFE7B1F65C580005BCCEB /* SplitViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplitViewTests.swift; sourceTree = "<group>"; };
29EDFE811F661562005BCCEB /* RepositoryReadmeModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepositoryReadmeModel.swift; sourceTree = "<group>"; };
29EDFE831F661776005BCCEB /* RepositoryReadmeSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepositoryReadmeSectionController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1601,7 +1599,6 @@
297AE84E1EC0D58A00B44A1F /* Info.plist */,
DC60C6D41F983DF800241271 /* IssueLabelCellTests.swift */,
29A476B11ED24D99005D0953 /* IssueTests.swift */,
BDB6AA752165B8EA009BB73C /* SwitchBranches.swift */,
29C2950D1EC7B43B00D46CD2 /* ListKitTestCase.swift */,
29C295091EC7AFA500D46CD2 /* ListTestKit.swift */,
2977D8BE215AE12D0073F737 /* LocalNotificationCacheTests.swift */,
Expand All @@ -1615,6 +1612,7 @@
DC60C6D21F983BB900241271 /* SignatureTests.swift */,
45A9D0381F9D3D6A00FD5AEF /* Snapshot Tests */,
29EDFE7B1F65C580005BCCEB /* SplitViewTests.swift */,
BDB6AA752165B8EA009BB73C /* SwitchBranches.swift */,
295F52A61EF1B9D2000B53CF /* Test.md */,
);
path = FreetimeTests;
Expand Down Expand Up @@ -1694,7 +1692,6 @@
DC78570F1F97F546009BADDA /* Debouncer.swift */,
29C167791ECA14F700439D62 /* Feed.swift */,
54AD5E8D1F24D953004A4BD6 /* FeedSelectionProviding.swift */,
29EB1EEE1F425E5100A200B4 /* ForegroundHandler.swift */,
29C167731ECA0DBB00439D62 /* GithubAPIDateFormatter.swift */,
29C0E7061ECBC6C50051D756 /* GithubClient.swift */,
2981A8A31EFE9FC700E25EF1 /* GithubEmoji.swift */,
Expand Down Expand Up @@ -2787,7 +2784,6 @@
291929421F3EA8CD0012067B /* File.swift in Sources */,
299E86491EFD9DBB00E5FE70 /* FlexController.m in Sources */,
29F3A18620CBF99E00645CB7 /* NotificationModelController.swift in Sources */,
29EB1EEF1F425E5100A200B4 /* ForegroundHandler.swift in Sources */,
29C167741ECA0DBB00439D62 /* GithubAPIDateFormatter.swift in Sources */,
290CA770216AE91300DE04F8 /* UITabBarController+SelectType.swift in Sources */,
294434E11FB1F2DA00050C06 /* BookmarkNavigationController.swift in Sources */,
Expand Down