Merge branch 'develop' into release/beta5

This commit is contained in:
Riley Testut 2017-10-16 13:45:35 -07:00
commit 6cd2f4e0dc
6 changed files with 121 additions and 43 deletions

@ -1 +1 @@
Subproject commit 4854926b2a21fe0c6e652dc1ccb4e7abdef3dcb6 Subproject commit d7213260852683ea5a3f6c2274733bbd65d2ec92

View File

@ -21,11 +21,11 @@ extension UIViewControllerContextTransitioning
/// UIViews /// UIViews
var sourceView: UIView { var sourceView: UIView {
return self.sourceViewController.view return self.view(forKey: .from) ?? self.sourceViewController.view
} }
var destinationView: UIView { var destinationView: UIView {
return self.destinationViewController.view return self.view(forKey: .to) ?? self.destinationViewController.view
} }

View File

@ -17,9 +17,9 @@ import SDWebImage
class GameCollectionViewController: UICollectionViewController class GameCollectionViewController: UICollectionViewController
{ {
var gameCollection: GameCollection! { var gameCollection: GameCollection? {
didSet { didSet {
self.title = self.gameCollection.shortName self.title = self.gameCollection?.shortName
self.updateDataSource() self.updateDataSource()
} }
} }
@ -41,11 +41,12 @@ class GameCollectionViewController: UICollectionViewController
} }
} }
internal let dataSource: RSTFetchedResultsCollectionViewPrefetchingDataSource<Game, UIImage>
weak var activeEmulatorCore: EmulatorCore? weak var activeEmulatorCore: EmulatorCore?
private var activeSaveState: SaveStateProtocol? private var activeSaveState: SaveStateProtocol?
private let dataSource: RSTFetchedResultsCollectionViewPrefetchingDataSource<Game, UIImage>
private let prototypeCell = GridCollectionViewCell() private let prototypeCell = GridCollectionViewCell()
private var _performing3DTouchTransition = false private var _performing3DTouchTransition = false
@ -215,7 +216,12 @@ private extension GameCollectionViewController
func updateDataSource() func updateDataSource()
{ {
let fetchRequest: NSFetchRequest<Game> = Game.fetchRequest() let fetchRequest: NSFetchRequest<Game> = Game.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "ANY %K == %@", #keyPath(Game.gameCollections), self.gameCollection)
if let gameCollection = self.gameCollection
{
fetchRequest.predicate = NSPredicate(format: "ANY %K == %@", #keyPath(Game.gameCollections), gameCollection)
}
fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(Game.name), ascending: true)] fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(Game.name), ascending: true)]
fetchRequest.returnsObjectsAsFaults = false fetchRequest.returnsObjectsAsFaults = false
@ -424,7 +430,7 @@ extension GameCollectionViewController: UIViewControllerPreviewingDelegate
{ {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
{ {
guard self.gameCollection.identifier != GameType.unknown.rawValue else { return nil } guard self.gameCollection?.identifier != GameType.unknown.rawValue else { return nil }
guard guard
let collectionView = self.collectionView, let collectionView = self.collectionView,
@ -598,7 +604,7 @@ extension GameCollectionViewController
{ {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{ {
guard self.gameCollection.identifier != GameType.unknown.rawValue else { return } guard self.gameCollection?.identifier != GameType.unknown.rawValue else { return }
let cell = collectionView.cellForItem(at: indexPath) let cell = collectionView.cellForItem(at: indexPath)
let game = self.dataSource.item(at: indexPath) let game = self.dataSource.item(at: indexPath)

View File

@ -35,12 +35,18 @@ class GamesViewController: UIViewController
} }
} }
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
private var pageViewController: UIPageViewController! private var pageViewController: UIPageViewController!
private var placeholderView: RSTPlaceholderView! private var placeholderView: RSTPlaceholderView!
private var pageControl: UIPageControl! private var pageControl: UIPageControl!
private let fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> private let fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>
private var searchController: RSTSearchController?
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
fatalError("initWithNibName: not implemented") fatalError("initWithNibName: not implemented")
} }
@ -88,6 +94,11 @@ extension GamesViewController
self.navigationController?.navigationBar.barStyle = .blackTranslucent self.navigationController?.navigationBar.barStyle = .blackTranslucent
self.navigationController?.toolbar.barStyle = .blackTranslucent self.navigationController?.toolbar.barStyle = .blackTranslucent
if #available(iOS 11.0, *)
{
self.prepareSearchController()
}
self.updateTheme() self.updateTheme()
} }
@ -153,6 +164,48 @@ extension GamesViewController
/// UI /// UI
private extension GamesViewController private extension GamesViewController
{ {
@available(iOS 11.0, *)
func prepareSearchController()
{
let searchResultsController = self.storyboard?.instantiateViewController(withIdentifier: "gameCollectionViewController") as! GameCollectionViewController
searchResultsController.gameCollection = nil
searchResultsController.theme = self.theme
searchResultsController.activeEmulatorCore = self.activeEmulatorCore
let placeholderView = RSTPlaceholderView()
placeholderView.textLabel.text = NSLocalizedString("No Games Found", comment: "")
placeholderView.detailTextLabel.text = NSLocalizedString("Please make sure the name is correct, or try searching for another game.", comment: "")
switch self.theme
{
case .opaque: searchResultsController.dataSource.placeholderView = placeholderView
case .translucent:
let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: .dark)))
vibrancyView.contentView.addSubview(placeholderView, pinningEdgesWith: .zero)
searchResultsController.dataSource.placeholderView = vibrancyView
}
self.searchController = RSTSearchController(searchResultsController: searchResultsController)
self.searchController?.searchableKeyPaths = [#keyPath(Game.name)]
self.searchController?.searchHandler = { [weak searchController, weak searchResultsController] (searchValue, _) in
if searchController?.searchBar.text?.isEmpty == false
{
self.pageViewController.view.isHidden = true
}
else
{
self.pageViewController.view.isHidden = false
}
searchResultsController?.dataSource.predicate = searchValue.predicate
return nil
}
self.navigationItem.searchController = self.searchController
self.navigationItem.hidesSearchBarWhenScrolling = false
self.definesPresentationContext = true
}
func updateTheme() func updateTheme()
{ {
switch self.theme switch self.theme
@ -190,7 +243,7 @@ private extension GamesViewController
let indexPath = IndexPath(row: safeIndex, section: 0) let indexPath = IndexPath(row: safeIndex, section: 0)
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gameCollectionViewController") as! GameCollectionViewController let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gameCollectionViewController") as! GameCollectionViewController
viewController.gameCollection = self.fetchedResultsController.object(at: indexPath) as! GameCollection viewController.gameCollection = self.fetchedResultsController.object(at: indexPath) as? GameCollection
viewController.theme = self.theme viewController.theme = self.theme
viewController.activeEmulatorCore = self.activeEmulatorCore viewController.activeEmulatorCore = self.activeEmulatorCore
@ -402,6 +455,21 @@ extension GamesViewController: UIPageViewControllerDataSource, UIPageViewControl
} }
} }
extension GamesViewController: UISearchResultsUpdating
{
func updateSearchResults(for searchController: UISearchController)
{
if searchController.searchBar.text?.isEmpty == false
{
self.pageViewController.view.isHidden = true
}
else
{
self.pageViewController.view.isHidden = false
}
}
}
//MARK: - NSFetchedResultsControllerDelegate - //MARK: - NSFetchedResultsControllerDelegate -
/// NSFetchedResultsControllerDelegate /// NSFetchedResultsControllerDelegate
extension GamesViewController: NSFetchedResultsControllerDelegate extension GamesViewController: NSFetchedResultsControllerDelegate

View File

@ -85,48 +85,51 @@ extension GamesStoryboardSegue: UIViewControllerAnimatedTransitioning
snapshotView.alpha = 1.0 snapshotView.alpha = 1.0
transitionContext.containerView.addSubview(snapshotView) transitionContext.containerView.addSubview(snapshotView)
// Ensures navigation controller toolbar (if visible) has been added to view heirachy, allowing us to add constraints
transitionContext.containerView.layoutIfNeeded()
// We add extra padding around the existing navigation bar and toolbar so they never appear to be detached from the edges of the screen during the overshooting of the spring animation // We add extra padding around the existing navigation bar and toolbar so they never appear to be detached from the edges of the screen during the overshooting of the spring animation
var topPaddingToolbar: UIToolbar? = nil var topPaddingToolbar: UIToolbar? = nil
var bottomPaddingToolbar: UIToolbar? = nil var bottomPaddingToolbar: UIToolbar? = nil
if let navigationController = transitionContext.destinationViewController as? UINavigationController // Must be wrapped in no-animation block to prevent iOS 11 search bar from not appearing.
{ UIView.performWithoutAnimation {
let padding: CGFloat = 44 // Ensures navigation controller toolbar (if visible) has been added to view heirachy, allowing us to add constraints
transitionContext.containerView.layoutIfNeeded()
if !navigationController.isNavigationBarHidden if let navigationController = transitionContext.destinationViewController as? UINavigationController
{ {
let topToolbar = UIToolbar(frame: CGRect.zero) let padding: CGFloat = 44
topToolbar.translatesAutoresizingMaskIntoConstraints = false
topToolbar.barStyle = navigationController.toolbar.barStyle
transitionContext.destinationView.insertSubview(topToolbar, belowSubview: navigationController.navigationBar)
topToolbar.bottomAnchor.constraint(equalTo: navigationController.navigationBar.bottomAnchor).isActive = true if !navigationController.isNavigationBarHidden
topToolbar.centerXAnchor.constraint(equalTo: navigationController.navigationBar.centerXAnchor).isActive = true {
topToolbar.widthAnchor.constraint(equalTo: navigationController.navigationBar.widthAnchor, constant: padding * 2).isActive = true let topToolbar = UIToolbar(frame: CGRect.zero)
topToolbar.heightAnchor.constraint(equalTo: navigationController.navigationBar.heightAnchor, constant: padding).isActive = true topToolbar.translatesAutoresizingMaskIntoConstraints = false
topToolbar.barStyle = navigationController.toolbar.barStyle
transitionContext.destinationView.insertSubview(topToolbar, at: 1)
topToolbar.topAnchor.constraint(equalTo: navigationController.navigationBar.topAnchor, constant: -padding).isActive = true
topToolbar.bottomAnchor.constraint(equalTo: navigationController.topViewController!.topLayoutGuide.bottomAnchor).isActive = true
topToolbar.leftAnchor.constraint(equalTo: navigationController.navigationBar.leftAnchor, constant: -padding).isActive = true
topToolbar.rightAnchor.constraint(equalTo: navigationController.navigationBar.rightAnchor, constant: padding).isActive = true
topPaddingToolbar = topToolbar
}
topPaddingToolbar = topToolbar if !navigationController.isToolbarHidden
} {
let bottomToolbar = UIToolbar(frame: CGRect.zero)
if !navigationController.isToolbarHidden bottomToolbar.translatesAutoresizingMaskIntoConstraints = false
{ bottomToolbar.barStyle = navigationController.toolbar.barStyle
let bottomToolbar = UIToolbar(frame: CGRect.zero) transitionContext.destinationView.insertSubview(bottomToolbar, belowSubview: navigationController.navigationBar)
bottomToolbar.translatesAutoresizingMaskIntoConstraints = false
bottomToolbar.barStyle = navigationController.toolbar.barStyle bottomToolbar.topAnchor.constraint(equalTo: navigationController.toolbar.topAnchor).isActive = true
transitionContext.destinationView.insertSubview(bottomToolbar, belowSubview: navigationController.navigationBar) bottomToolbar.bottomAnchor.constraint(equalTo: navigationController.toolbar.bottomAnchor, constant: padding).isActive = true
bottomToolbar.leftAnchor.constraint(equalTo: navigationController.toolbar.leftAnchor, constant: -padding).isActive = true
bottomToolbar.topAnchor.constraint(equalTo: navigationController.toolbar.topAnchor).isActive = true bottomToolbar.rightAnchor.constraint(equalTo: navigationController.toolbar.rightAnchor, constant: padding).isActive = true
bottomToolbar.centerXAnchor.constraint(equalTo: navigationController.toolbar.centerXAnchor).isActive = true
bottomToolbar.widthAnchor.constraint(equalTo: navigationController.toolbar.widthAnchor, constant: padding * 2).isActive = true bottomPaddingToolbar = bottomToolbar
bottomToolbar.heightAnchor.constraint(equalTo: navigationController.toolbar.heightAnchor, constant: padding).isActive = true }
bottomPaddingToolbar = bottomToolbar
} }
} }
self.animator.addAnimations { self.animator.addAnimations {
snapshotView.alpha = 0.0 snapshotView.alpha = 0.0
transitionContext.destinationView.transform = CGAffineTransform.identity transitionContext.destinationView.transform = CGAffineTransform.identity
@ -163,3 +166,4 @@ extension GamesStoryboardSegue: UIViewControllerAnimatedTransitioning
self.animator.startAnimation() self.animator.startAnimation()
} }
} }

2
External/Roxas vendored

@ -1 +1 @@
Subproject commit faf98f4c5276a2b6146e25db0e16760d68cf294d Subproject commit 192682bb389830944d257946d870e1d50ae4c42b