mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Revises Patreon UI
This commit is contained in:
@@ -2,18 +2,33 @@
|
||||
// PatreonViewController.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 8/20/19.
|
||||
// Created by Riley Testut on 9/5/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SafariServices
|
||||
import AuthenticationServices
|
||||
|
||||
import Roxas
|
||||
|
||||
class PatreonViewController: UITableViewController
|
||||
extension PatreonViewController
|
||||
{
|
||||
private enum Section: Int, CaseIterable
|
||||
{
|
||||
case about
|
||||
case patrons
|
||||
}
|
||||
}
|
||||
|
||||
class PatreonViewController: UICollectionViewController
|
||||
{
|
||||
private lazy var dataSource = self.makeDataSource()
|
||||
private lazy var patronsDataSource = self.makePatronsDataSource()
|
||||
|
||||
private var prototypeAboutHeader: AboutPatreonHeaderView!
|
||||
|
||||
private var patronsResult: Result<[Patron], Error>?
|
||||
|
||||
@IBOutlet private var signInButton: UIBarButtonItem!
|
||||
@IBOutlet private var signOutButton: UIBarButtonItem!
|
||||
@@ -22,7 +37,14 @@ class PatreonViewController: UITableViewController
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.tableView.dataSource = self.dataSource
|
||||
let aboutHeaderNib = UINib(nibName: "AboutPatreonHeaderView", bundle: nil)
|
||||
self.prototypeAboutHeader = aboutHeaderNib.instantiate(withOwner: nil, options: nil)[0] as? AboutPatreonHeaderView
|
||||
|
||||
self.collectionView.dataSource = self.dataSource
|
||||
|
||||
self.collectionView.register(aboutHeaderNib, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "AboutHeader")
|
||||
self.collectionView.register(PatronsHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "PatronsHeader")
|
||||
self.collectionView.register(PatronsFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "PatronsFooter")
|
||||
|
||||
self.update()
|
||||
}
|
||||
@@ -32,19 +54,45 @@ class PatreonViewController: UITableViewController
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.fetchPatrons()
|
||||
|
||||
self.update()
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
{
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
let layout = self.collectionViewLayout as! UICollectionViewFlowLayout
|
||||
|
||||
var itemWidth = (self.collectionView.bounds.width - (layout.sectionInset.left + layout.sectionInset.right + layout.minimumInteritemSpacing)) / 2
|
||||
itemWidth.round(.down)
|
||||
|
||||
layout.itemSize = CGSize(width: itemWidth, height: layout.itemSize.height)
|
||||
}
|
||||
}
|
||||
|
||||
private extension PatreonViewController
|
||||
{
|
||||
func makeDataSource() -> RSTArrayTableViewDataSource<Patron>
|
||||
func makeDataSource() -> RSTCompositeCollectionViewDataSource<Patron>
|
||||
{
|
||||
let dataSource = RSTArrayTableViewDataSource<Patron>(items: [])
|
||||
dataSource.cellConfigurationHandler = { (cell, patron, indexPath) in
|
||||
cell.textLabel?.text = patron.name
|
||||
let aboutDataSource = RSTDynamicCollectionViewDataSource<Patron>()
|
||||
aboutDataSource.numberOfSectionsHandler = { 1 }
|
||||
aboutDataSource.numberOfItemsHandler = { _ in 0 }
|
||||
|
||||
let dataSource = RSTCompositeCollectionViewDataSource<Patron>(dataSources: [aboutDataSource, self.patronsDataSource])
|
||||
dataSource.proxy = self
|
||||
return dataSource
|
||||
}
|
||||
|
||||
func makePatronsDataSource() -> RSTArrayCollectionViewDataSource<Patron>
|
||||
{
|
||||
let patronsDataSource = RSTArrayCollectionViewDataSource<Patron>(items: [])
|
||||
patronsDataSource.cellConfigurationHandler = { (cell, patron, indexPath) in
|
||||
let cell = cell as! PatronCollectionViewCell
|
||||
cell.textLabel.text = patron.name
|
||||
}
|
||||
|
||||
return dataSource
|
||||
return patronsDataSource
|
||||
}
|
||||
|
||||
func update()
|
||||
@@ -58,28 +106,48 @@ private extension PatreonViewController
|
||||
self.navigationItem.rightBarButtonItem = self.signInButton
|
||||
}
|
||||
}
|
||||
|
||||
func fetchPatrons()
|
||||
{
|
||||
PatreonAPI.shared.fetchPatrons { (result) in
|
||||
do
|
||||
{
|
||||
let patrons = try result.get()
|
||||
self.dataSource.items = patrons
|
||||
}
|
||||
catch
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension PatreonViewController
|
||||
{
|
||||
@objc func fetchPatrons()
|
||||
{
|
||||
if let result = self.patronsResult, case .failure = result
|
||||
{
|
||||
self.patronsResult = nil
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
|
||||
PatreonAPI.shared.fetchPatrons { (result) in
|
||||
self.patronsResult = result
|
||||
|
||||
do
|
||||
{
|
||||
let patrons = try result.get()
|
||||
let sortedPatrons = patrons.sorted { $0.name < $1.name }
|
||||
|
||||
self.patronsDataSource.items = sortedPatrons
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Failed to fetch patrons:", error)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc func openPatreonURL(_ sender: UIButton)
|
||||
{
|
||||
let patreonURL = URL(string: "https://www.patreon.com/rileytestut")!
|
||||
|
||||
let safariViewController = SFSafariViewController(url: patreonURL)
|
||||
safariViewController.preferredControlTintColor = self.view.tintColor
|
||||
self.present(safariViewController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction func authenticate(_ sender: UIBarButtonItem)
|
||||
{
|
||||
PatreonAPI.shared.authenticate { (result) in
|
||||
@@ -108,22 +176,100 @@ private extension PatreonViewController
|
||||
|
||||
@IBAction func signOut(_ sender: UIBarButtonItem)
|
||||
{
|
||||
PatreonAPI.shared.signOut { (result) in
|
||||
do
|
||||
{
|
||||
try result.get()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.update()
|
||||
func signOut()
|
||||
{
|
||||
PatreonAPI.shared.signOut { (result) in
|
||||
do
|
||||
{
|
||||
try result.get()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to sign out?", comment: ""), message: NSLocalizedString("You will no longer have access to beta versions of apps once you sign out.", comment: ""), preferredStyle: .actionSheet)
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Sign Out", comment: ""), style: .destructive) { _ in signOut() })
|
||||
alertController.addAction(.cancel)
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension PatreonViewController
|
||||
{
|
||||
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
|
||||
{
|
||||
let section = Section.allCases[indexPath.section]
|
||||
switch section
|
||||
{
|
||||
case .about:
|
||||
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "AboutHeader", for: indexPath) as! AboutPatreonHeaderView
|
||||
headerView.supportButton.addTarget(self, action: #selector(PatreonViewController.openPatreonURL(_:)), for: .primaryActionTriggered)
|
||||
return headerView
|
||||
|
||||
case .patrons:
|
||||
if kind == UICollectionView.elementKindSectionHeader
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(text: error.localizedDescription, detailText: nil)
|
||||
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2.0)
|
||||
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PatronsHeader", for: indexPath) as! PatronsHeaderView
|
||||
headerView.textLabel.text = NSLocalizedString("Special thanks to...", comment: "")
|
||||
return headerView
|
||||
}
|
||||
else
|
||||
{
|
||||
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PatronsFooter", for: indexPath) as! PatronsFooterView
|
||||
footerView.button.isIndicatingActivity = false
|
||||
footerView.button.isHidden = false
|
||||
footerView.button.addTarget(self, action: #selector(PatreonViewController.fetchPatrons), for: .primaryActionTriggered)
|
||||
|
||||
switch self.patronsResult
|
||||
{
|
||||
case .none: footerView.button.isIndicatingActivity = true
|
||||
case .success?: footerView.button.isHidden = true
|
||||
case .failure?: footerView.button.setTitle(NSLocalizedString("Error Loading Patrons", comment: ""), for: .normal)
|
||||
}
|
||||
|
||||
return footerView
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension PatreonViewController: UICollectionViewDelegateFlowLayout
|
||||
{
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
|
||||
{
|
||||
let section = Section.allCases[section]
|
||||
switch section
|
||||
{
|
||||
case .about:
|
||||
let widthConstraint = self.prototypeAboutHeader.widthAnchor.constraint(equalToConstant: collectionView.bounds.width)
|
||||
NSLayoutConstraint.activate([widthConstraint])
|
||||
defer { NSLayoutConstraint.deactivate([widthConstraint]) }
|
||||
|
||||
let size = self.prototypeAboutHeader.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
|
||||
return size
|
||||
|
||||
case .patrons:
|
||||
return CGSize(width: 320, height: 20)
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
|
||||
{
|
||||
let section = Section.allCases[section]
|
||||
switch section
|
||||
{
|
||||
case .about: return .zero
|
||||
case .patrons: return CGSize(width: 320, height: 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user