Merge branch 'feature/game_search' into develop
This commit is contained in:
commit
9f27d3bc0e
@ -21,11 +21,11 @@ extension UIViewControllerContextTransitioning
|
||||
|
||||
/// UIViews
|
||||
var sourceView: UIView {
|
||||
return self.sourceViewController.view
|
||||
return self.view(forKey: .from) ?? self.sourceViewController.view
|
||||
}
|
||||
|
||||
var destinationView: UIView {
|
||||
return self.destinationViewController.view
|
||||
return self.view(forKey: .to) ?? self.destinationViewController.view
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@ import SDWebImage
|
||||
|
||||
class GameCollectionViewController: UICollectionViewController
|
||||
{
|
||||
var gameCollection: GameCollection! {
|
||||
var gameCollection: GameCollection? {
|
||||
didSet {
|
||||
self.title = self.gameCollection.shortName
|
||||
self.title = self.gameCollection?.shortName
|
||||
self.updateDataSource()
|
||||
}
|
||||
}
|
||||
@ -41,11 +41,12 @@ class GameCollectionViewController: UICollectionViewController
|
||||
}
|
||||
}
|
||||
|
||||
internal let dataSource: RSTFetchedResultsCollectionViewPrefetchingDataSource<Game, UIImage>
|
||||
|
||||
weak var activeEmulatorCore: EmulatorCore?
|
||||
|
||||
private var activeSaveState: SaveStateProtocol?
|
||||
|
||||
private let dataSource: RSTFetchedResultsCollectionViewPrefetchingDataSource<Game, UIImage>
|
||||
private let prototypeCell = GridCollectionViewCell()
|
||||
|
||||
private var _performing3DTouchTransition = false
|
||||
@ -215,7 +216,12 @@ private extension GameCollectionViewController
|
||||
func updateDataSource()
|
||||
{
|
||||
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.returnsObjectsAsFaults = false
|
||||
|
||||
@ -424,7 +430,7 @@ extension GameCollectionViewController: UIViewControllerPreviewingDelegate
|
||||
{
|
||||
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
|
||||
let collectionView = self.collectionView,
|
||||
@ -598,7 +604,7 @@ extension GameCollectionViewController
|
||||
{
|
||||
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 game = self.dataSource.item(at: indexPath)
|
||||
|
||||
@ -35,12 +35,18 @@ class GamesViewController: UIViewController
|
||||
}
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
private var pageViewController: UIPageViewController!
|
||||
private var placeholderView: RSTPlaceholderView!
|
||||
private var pageControl: UIPageControl!
|
||||
|
||||
private let fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>
|
||||
|
||||
private var searchController: RSTSearchController?
|
||||
|
||||
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
fatalError("initWithNibName: not implemented")
|
||||
}
|
||||
@ -88,6 +94,11 @@ extension GamesViewController
|
||||
self.navigationController?.navigationBar.barStyle = .blackTranslucent
|
||||
self.navigationController?.toolbar.barStyle = .blackTranslucent
|
||||
|
||||
if #available(iOS 11.0, *)
|
||||
{
|
||||
self.prepareSearchController()
|
||||
}
|
||||
|
||||
self.updateTheme()
|
||||
}
|
||||
|
||||
@ -153,6 +164,48 @@ extension GamesViewController
|
||||
/// UI
|
||||
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()
|
||||
{
|
||||
switch self.theme
|
||||
@ -190,7 +243,7 @@ private extension GamesViewController
|
||||
let indexPath = IndexPath(row: safeIndex, section: 0)
|
||||
|
||||
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.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 -
|
||||
/// NSFetchedResultsControllerDelegate
|
||||
extension GamesViewController: NSFetchedResultsControllerDelegate
|
||||
|
||||
@ -85,48 +85,51 @@ extension GamesStoryboardSegue: UIViewControllerAnimatedTransitioning
|
||||
snapshotView.alpha = 1.0
|
||||
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
|
||||
var topPaddingToolbar: UIToolbar? = nil
|
||||
var bottomPaddingToolbar: UIToolbar? = nil
|
||||
|
||||
if let navigationController = transitionContext.destinationViewController as? UINavigationController
|
||||
{
|
||||
let padding: CGFloat = 44
|
||||
// Must be wrapped in no-animation block to prevent iOS 11 search bar from not appearing.
|
||||
UIView.performWithoutAnimation {
|
||||
// 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)
|
||||
topToolbar.translatesAutoresizingMaskIntoConstraints = false
|
||||
topToolbar.barStyle = navigationController.toolbar.barStyle
|
||||
transitionContext.destinationView.insertSubview(topToolbar, belowSubview: navigationController.navigationBar)
|
||||
let padding: CGFloat = 44
|
||||
|
||||
topToolbar.bottomAnchor.constraint(equalTo: navigationController.navigationBar.bottomAnchor).isActive = true
|
||||
topToolbar.centerXAnchor.constraint(equalTo: navigationController.navigationBar.centerXAnchor).isActive = true
|
||||
topToolbar.widthAnchor.constraint(equalTo: navigationController.navigationBar.widthAnchor, constant: padding * 2).isActive = true
|
||||
topToolbar.heightAnchor.constraint(equalTo: navigationController.navigationBar.heightAnchor, constant: padding).isActive = true
|
||||
if !navigationController.isNavigationBarHidden
|
||||
{
|
||||
let topToolbar = UIToolbar(frame: CGRect.zero)
|
||||
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)
|
||||
bottomToolbar.translatesAutoresizingMaskIntoConstraints = false
|
||||
bottomToolbar.barStyle = navigationController.toolbar.barStyle
|
||||
transitionContext.destinationView.insertSubview(bottomToolbar, belowSubview: navigationController.navigationBar)
|
||||
|
||||
bottomToolbar.topAnchor.constraint(equalTo: navigationController.toolbar.topAnchor).isActive = true
|
||||
bottomToolbar.centerXAnchor.constraint(equalTo: navigationController.toolbar.centerXAnchor).isActive = true
|
||||
bottomToolbar.widthAnchor.constraint(equalTo: navigationController.toolbar.widthAnchor, constant: padding * 2).isActive = true
|
||||
bottomToolbar.heightAnchor.constraint(equalTo: navigationController.toolbar.heightAnchor, constant: padding).isActive = true
|
||||
|
||||
bottomPaddingToolbar = bottomToolbar
|
||||
if !navigationController.isToolbarHidden
|
||||
{
|
||||
let bottomToolbar = UIToolbar(frame: CGRect.zero)
|
||||
bottomToolbar.translatesAutoresizingMaskIntoConstraints = false
|
||||
bottomToolbar.barStyle = navigationController.toolbar.barStyle
|
||||
transitionContext.destinationView.insertSubview(bottomToolbar, belowSubview: navigationController.navigationBar)
|
||||
|
||||
bottomToolbar.topAnchor.constraint(equalTo: navigationController.toolbar.topAnchor).isActive = true
|
||||
bottomToolbar.bottomAnchor.constraint(equalTo: navigationController.toolbar.bottomAnchor, constant: padding).isActive = true
|
||||
bottomToolbar.leftAnchor.constraint(equalTo: navigationController.toolbar.leftAnchor, constant: -padding).isActive = true
|
||||
bottomToolbar.rightAnchor.constraint(equalTo: navigationController.toolbar.rightAnchor, constant: padding).isActive = true
|
||||
|
||||
bottomPaddingToolbar = bottomToolbar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.animator.addAnimations {
|
||||
snapshotView.alpha = 0.0
|
||||
transitionContext.destinationView.transform = CGAffineTransform.identity
|
||||
@ -163,3 +166,4 @@ extension GamesStoryboardSegue: UIViewControllerAnimatedTransitioning
|
||||
self.animator.startAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
External/Roxas
vendored
2
External/Roxas
vendored
@ -1 +1 @@
|
||||
Subproject commit 7434aef0372aca1d0b12cc4b8a6a37df034aae7c
|
||||
Subproject commit 192682bb389830944d257946d870e1d50ae4c42b
|
||||
Loading…
Reference in New Issue
Block a user