diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index 9febeda7e..786e7205d 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -49,6 +49,7 @@ #import #import #import +#import #import #import #import diff --git a/Signal/src/ViewControllers/GifPicker/GifPickerCell.swift b/Signal/src/ViewControllers/GifPicker/GifPickerCell.swift index 2727f860f..e8cfda5a3 100644 --- a/Signal/src/ViewControllers/GifPicker/GifPickerCell.swift +++ b/Signal/src/ViewControllers/GifPicker/GifPickerCell.swift @@ -77,7 +77,7 @@ class GifPickerCell: UICollectionViewCell { clearFullAssetRequest() } - private func ensureCellState() { + public func ensureCellState() { guard isCellVisible else { // Cancel any outstanding requests. clearAssetRequests() diff --git a/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift b/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift index 56edc7066..39af498c5 100644 --- a/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift +++ b/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift @@ -27,6 +27,8 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect var imageInfos = [GiphyImageInfo]() + var reachability: Reachability? + private let kCellReuseIdentifier = "kCellReuseIdentifier" // MARK: Initializers @@ -57,6 +59,38 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect self.layout.delegate = self } + deinit { + NotificationCenter.default.removeObserver(self) + } + + func didBecomeActive() { + AssertIsOnMainThread() + + Logger.info("\(self.TAG) \(#function)") + + // Prod cells to try to load when app becomes active. + ensureCellState() + } + + func reachabilityChanged() { + AssertIsOnMainThread() + + Logger.info("\(self.TAG) \(#function)") + + // Prod cells to try to load when connectivity changes. + ensureCellState() + } + + func ensureCellState() { + for cell in self.collectionView.visibleCells { + guard let cell = cell as? GifPickerCell else { + owsFail("\(TAG) unexpected cell.") + return + } + cell.ensureCellState() + } + } + // MARK: View Lifecycle override func viewDidLoad() { @@ -71,6 +105,16 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect comment: "Title for the 'gif picker' dialog.") createViews() + + reachability = Reachability.forInternetConnection() + NotificationCenter.default.addObserver(self, + selector:#selector(reachabilityChanged), + name:NSNotification.Name.reachabilityChanged, + object:nil) + NotificationCenter.default.addObserver(self, + selector:#selector(didBecomeActive), + name:NSNotification.Name.UIApplicationDidBecomeActive, + object:nil) } override func viewDidAppear(_ animated: Bool) { diff --git a/Signal/src/network/GifDownloader.swift b/Signal/src/network/GifDownloader.swift index 2c0b19a63..a86285bdf 100644 --- a/Signal/src/network/GifDownloader.swift +++ b/Signal/src/network/GifDownloader.swift @@ -269,11 +269,18 @@ extension URLSessionTask { self.startRequestIfNecessary() return } + guard UIApplication.shared.applicationState == .active else { + // If app is not active, fail the asset request. + self.assetRequestDidFail(assetRequest:assetRequest) + self.startRequestIfNecessary() + return + } + self.activeAssetRequests.insert(assetRequest) if let asset = self.assetMap.get(key:assetRequest.rendition.url) { - // Deferred cache hit, avoids re-downloading assets already in the - // asset cache. + // Deferred cache hit, avoids re-downloading assets that were + // downloaded while this request was queued. self.assetRequestDidSucceed(assetRequest : assetRequest, asset: asset) return @@ -297,6 +304,10 @@ extension URLSessionTask { // Prefer the first "high" priority request, // fall back to the first "low" priority request. + // + // TODO: We could refine this logic to defer requests if + // there is already an active asset request with the + // same URL. for priority in [GiphyRequestPriority.high, GiphyRequestPriority.low] { for (assetRequestIndex, assetRequest) in assetRequestQueue.enumerated() { if assetRequest.priority == priority {