From 9ea584c1fb939071f5a16490b7b7e4531d97112d Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Thu, 19 Sep 2019 15:18:21 -0700 Subject: [PATCH] Adds placeholder view to NewsViewController and BrowseViewController --- AltStore.xcodeproj/project.pbxproj | 4 ++ AltStore/Browse/BrowseViewController.swift | 57 +++++++++++++++++++-- AltStore/News/NewsViewController.swift | 58 ++++++++++++++++++++-- AltStore/Types/LoadingState.swift | 15 ++++++ 4 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 AltStore/Types/LoadingState.swift diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index 231f403a..0239b2be 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ BF3D64B022E8D4B800E9056B /* AppContentViewControllerCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3D64AF22E8D4B800E9056B /* AppContentViewControllerCells.swift */; }; BF3F786422CAA41E008FBD20 /* ALTDeviceManager+Installation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3F786322CAA41E008FBD20 /* ALTDeviceManager+Installation.swift */; }; BF41B806233423AE00C593A3 /* TabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF41B805233423AE00C593A3 /* TabBarController.swift */; }; + BF41B808233433C100C593A3 /* LoadingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF41B807233433C100C593A3 /* LoadingState.swift */; }; BF43002E22A714AF0051E2BC /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF43002D22A714AF0051E2BC /* Keychain.swift */; }; BF43003022A71C960051E2BC /* UserDefaults+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF43002F22A71C960051E2BC /* UserDefaults+AltStore.swift */; }; BF44CC6C232AEB90004DA9C3 /* LaunchAtLogin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF44CC6A232AEB74004DA9C3 /* LaunchAtLogin.framework */; }; @@ -313,6 +314,7 @@ BF3D64AF22E8D4B800E9056B /* AppContentViewControllerCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppContentViewControllerCells.swift; sourceTree = ""; }; BF3F786322CAA41E008FBD20 /* ALTDeviceManager+Installation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ALTDeviceManager+Installation.swift"; sourceTree = ""; }; BF41B805233423AE00C593A3 /* TabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarController.swift; sourceTree = ""; }; + BF41B807233433C100C593A3 /* LoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingState.swift; sourceTree = ""; }; BF43002D22A714AF0051E2BC /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = ""; }; BF43002F22A71C960051E2BC /* UserDefaults+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+AltStore.swift"; sourceTree = ""; }; BF44CC6A232AEB74004DA9C3 /* LaunchAtLogin.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LaunchAtLogin.framework; path = Carthage/Build/Mac/LaunchAtLogin.framework; sourceTree = ""; }; @@ -600,6 +602,7 @@ BF3D648C22E79AC800E9056B /* ALTAppPermission.m */, BF54E81F2315EF0D000AE0D8 /* ALTPatreonBenefitType.h */, BF54E8202315EF0D000AE0D8 /* ALTPatreonBenefitType.m */, + BF41B807233433C100C593A3 /* LoadingState.swift */, ); path = Types; sourceTree = ""; @@ -1480,6 +1483,7 @@ BF9ABA4722DD0638008935CF /* BrowseCollectionViewCell.swift in Sources */, BF3D648822E79A3700E9056B /* AppPermission.swift in Sources */, BFD6B03322DFF20800B86064 /* MyAppsComponents.swift in Sources */, + BF41B808233433C100C593A3 /* LoadingState.swift in Sources */, BFF0B69A2322D7D0007A79E1 /* UIScreen+CompactHeight.swift in Sources */, BFD5D6EE230D8A86007955AB /* Patron.swift in Sources */, BF8F69C222E659F700049BA1 /* AppContentViewController.swift in Sources */, diff --git a/AltStore/Browse/BrowseViewController.swift b/AltStore/Browse/BrowseViewController.swift index 15324a0f..ce44bdb8 100644 --- a/AltStore/Browse/BrowseViewController.swift +++ b/AltStore/Browse/BrowseViewController.swift @@ -15,9 +15,16 @@ import Nuke class BrowseViewController: UICollectionViewController { private lazy var dataSource = self.makeDataSource() + private lazy var placeholderView = RSTPlaceholderView(frame: .zero) private let prototypeCell = BrowseCollectionViewCell.instantiate(with: BrowseCollectionViewCell.nib!)! + private var loadingState: LoadingState = .loading { + didSet { + self.update() + } + } + private var cachedItemSizes = [String: CGSize]() override func viewDidLoad() @@ -32,6 +39,8 @@ class BrowseViewController: UICollectionViewController self.collectionView.prefetchDataSource = self.dataSource self.registerForPreviewing(with: self, sourceView: self.collectionView) + + self.update() } override func viewWillAppear(_ animated: Bool) @@ -135,6 +144,8 @@ private extension BrowseViewController } } + dataSource.placeholderView = self.placeholderView + return dataSource } @@ -152,21 +163,61 @@ private extension BrowseViewController func fetchSource() { + self.loadingState = .loading + AppManager.shared.fetchSource() { (result) in do - { + { let source = try result.get() try source.managedObjectContext?.save() + + DispatchQueue.main.async { + self.loadingState = .finished(.success(())) + } } catch { DispatchQueue.main.async { - let toastView = ToastView(text: error.localizedDescription, detailText: nil) - toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0) + if self.dataSource.itemCount > 0 + { + let toastView = ToastView(text: error.localizedDescription, detailText: nil) + toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0) + } + + self.loadingState = .finished(.failure(error)) } } } } + + func update() + { + switch self.loadingState + { + case .loading: + self.placeholderView.textLabel.isHidden = true + self.placeholderView.detailTextLabel.isHidden = false + + self.placeholderView.detailTextLabel.text = NSLocalizedString("Loading...", comment: "") + + self.placeholderView.activityIndicatorView.startAnimating() + + case .finished(.failure(let error)): + self.placeholderView.textLabel.isHidden = false + self.placeholderView.detailTextLabel.isHidden = false + + self.placeholderView.textLabel.text = NSLocalizedString("Unable to Fetch Apps", comment: "") + self.placeholderView.detailTextLabel.text = error.localizedDescription + + self.placeholderView.activityIndicatorView.stopAnimating() + + case .finished(.success): + self.placeholderView.textLabel.isHidden = true + self.placeholderView.detailTextLabel.isHidden = true + + self.placeholderView.activityIndicatorView.stopAnimating() + } + } } private extension BrowseViewController diff --git a/AltStore/News/NewsViewController.swift b/AltStore/News/NewsViewController.swift index 13736a21..b04f0af0 100644 --- a/AltStore/News/NewsViewController.swift +++ b/AltStore/News/NewsViewController.swift @@ -34,8 +34,16 @@ private class AppBannerFooterView: UICollectionReusableView class NewsViewController: UICollectionViewController { private lazy var dataSource = self.makeDataSource() + private lazy var placeholderView = RSTPlaceholderView(frame: .zero) + private var prototypeCell: NewsCollectionViewCell! + private var loadingState: LoadingState = .loading { + didSet { + self.update() + } + } + // Cache private var cachedCellSizes = [String: CGSize]() @@ -56,6 +64,8 @@ class NewsViewController: UICollectionViewController self.collectionView.register(AppBannerFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "AppBanner") self.registerForPreviewing(with: self, sourceView: self.collectionView) + + self.update() } override func viewWillAppear(_ animated: Bool) @@ -125,26 +135,68 @@ private extension NewsViewController } } + dataSource.placeholderView = self.placeholderView + return dataSource } - + func fetchSource() { + self.loadingState = .loading + AppManager.shared.fetchSource() { (result) in do { let source = try result.get() try source.managedObjectContext?.save() + + DispatchQueue.main.async { + self.loadingState = .finished(.success(())) + } } catch { DispatchQueue.main.async { - let toastView = ToastView(text: error.localizedDescription, detailText: nil) - toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0) + if self.dataSource.itemCount > 0 + { + let toastView = ToastView(text: error.localizedDescription, detailText: nil) + toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0) + } + + self.loadingState = .finished(.failure(error)) } } } } + + func update() + { + switch self.loadingState + { + case .loading: + self.placeholderView.textLabel.isHidden = true + self.placeholderView.detailTextLabel.isHidden = false + + self.placeholderView.detailTextLabel.text = NSLocalizedString("Loading...", comment: "") + + self.placeholderView.activityIndicatorView.startAnimating() + + case .finished(.failure(let error)): + self.placeholderView.textLabel.isHidden = false + self.placeholderView.detailTextLabel.isHidden = false + + self.placeholderView.textLabel.text = NSLocalizedString("Unable to Fetch News", comment: "") + self.placeholderView.detailTextLabel.text = error.localizedDescription + + self.placeholderView.activityIndicatorView.stopAnimating() + + case .finished(.success): + self.placeholderView.textLabel.isHidden = true + self.placeholderView.detailTextLabel.isHidden = true + + self.placeholderView.activityIndicatorView.stopAnimating() + } + } } private extension NewsViewController diff --git a/AltStore/Types/LoadingState.swift b/AltStore/Types/LoadingState.swift new file mode 100644 index 00000000..f8b13320 --- /dev/null +++ b/AltStore/Types/LoadingState.swift @@ -0,0 +1,15 @@ +// +// LoadingState.swift +// AltStore +// +// Created by Riley Testut on 9/19/19. +// Copyright © 2019 Riley Testut. All rights reserved. +// + +import Foundation + +enum LoadingState +{ + case loading + case finished(Result) +}