From eebb593aa233e7d69361f494ad5118830a11e26e Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Tue, 28 Mar 2017 00:14:47 -0700 Subject: [PATCH] Updates GamesDatabaseBrowserViewController design to match Delta dark theme --- Delta.xcodeproj/project.pbxproj | 4 + Delta/AppDelegate.swift | 12 +- Delta/Base.lproj/Main.storyboard | 51 ++++++-- .../OpenVGDB/GameMetadataTableViewCell.swift | 31 +++++ .../GamesDatabaseBrowserViewController.swift | 112 +++++++++++++----- 5 files changed, 170 insertions(+), 40 deletions(-) create mode 100644 Delta/Database/OpenVGDB/GameMetadataTableViewCell.swift diff --git a/Delta.xcodeproj/project.pbxproj b/Delta.xcodeproj/project.pbxproj index d77061f..07307cc 100644 --- a/Delta.xcodeproj/project.pbxproj +++ b/Delta.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ BFEC732D1AAECC4A00650035 /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFEC732C1AAECC4A00650035 /* Roxas.framework */; }; BFEC732E1AAECC4A00650035 /* Roxas.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFEC732C1AAECC4A00650035 /* Roxas.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; BFF93AA01E0FB036005EC865 /* InputStreamOutputWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */; }; + BFFA4C091E8A24D600D87934 /* GameMetadataTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA4C081E8A24D600D87934 /* GameMetadataTableViewCell.swift */; }; BFFA71DD1AAC406100EE9DD1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */; }; BFFA71E21AAC406100EE9DD1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFFA71E01AAC406100EE9DD1 /* Main.storyboard */; }; BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFC461B1D59823500AF2CC6 /* GamesPresentationController.swift */; }; @@ -199,6 +200,7 @@ BFE4269D1D9C68E600DC913F /* SaveStatesStoryboardSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesStoryboardSegue.swift; path = Segues/SaveStatesStoryboardSegue.swift; sourceTree = ""; }; BFEC732C1AAECC4A00650035 /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InputStreamOutputWriter.swift; path = Components/Importing/InputStreamOutputWriter.swift; sourceTree = ""; }; + BFFA4C081E8A24D600D87934 /* GameMetadataTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GameMetadataTableViewCell.swift; path = Database/OpenVGDB/GameMetadataTableViewCell.swift; sourceTree = ""; }; BFFA71D71AAC406100EE9DD1 /* Delta.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Delta.app; sourceTree = BUILT_PRODUCTS_DIR; }; BFFA71DB1AAC406100EE9DD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -423,6 +425,7 @@ BF59426E1E09BC5D0051894B /* GamesDatabase.swift */, BF95E2761E4977BF0030E7AD /* GameMetadata.swift */, BF95E2781E4982A10030E7AD /* GamesDatabaseBrowserViewController.swift */, + BFFA4C081E8A24D600D87934 /* GameMetadataTableViewCell.swift */, ); name = OpenVGDB; sourceTree = ""; @@ -740,6 +743,7 @@ BF5942891E09BC8B0051894B /* _GameCollection.swift in Sources */, BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */, BF1DAD5D1D9F576000E752A7 /* GameTypeControllerSkinsViewController.swift in Sources */, + BFFA4C091E8A24D600D87934 /* GameMetadataTableViewCell.swift in Sources */, BFFC46231D5984A000AF2CC6 /* LaunchViewController.swift in Sources */, BF5942701E09BC5D0051894B /* GamesDatabase.swift in Sources */, BF34FA071CF0F510006624C7 /* EditCheatViewController.swift in Sources */, diff --git a/Delta/AppDelegate.swift b/Delta/AppDelegate.swift index 8045b36..73ec644 100644 --- a/Delta/AppDelegate.swift +++ b/Delta/AppDelegate.swift @@ -24,7 +24,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate Delta.register(SNES.core) Delta.register(GBA.core) - self.window?.tintColor = UIColor.deltaPurple + self.configureAppearance() // Disable system gestures that delay touches on left edge of screen for gestureRecognizer in self.window?.gestureRecognizers ?? [] where NSStringFromClass(type(of: gestureRecognizer)).contains("GateGesture") @@ -71,6 +71,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate } } +extension AppDelegate +{ + func configureAppearance() + { + self.window?.tintColor = UIColor.deltaPurple + + UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes[NSForegroundColorAttributeName] = UIColor.white + } +} + extension AppDelegate { func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool diff --git a/Delta/Base.lproj/Main.storyboard b/Delta/Base.lproj/Main.storyboard index 216262c..95ac3a9 100644 --- a/Delta/Base.lproj/Main.storyboard +++ b/Delta/Base.lproj/Main.storyboard @@ -6,6 +6,7 @@ + @@ -60,27 +61,54 @@ - + - - + + - + - + + + + + + + + + + + + + + + + + @@ -99,7 +127,7 @@ - + @@ -291,7 +319,7 @@ - + @@ -306,6 +334,7 @@ + diff --git a/Delta/Database/OpenVGDB/GameMetadataTableViewCell.swift b/Delta/Database/OpenVGDB/GameMetadataTableViewCell.swift new file mode 100644 index 0000000..3445ea5 --- /dev/null +++ b/Delta/Database/OpenVGDB/GameMetadataTableViewCell.swift @@ -0,0 +1,31 @@ +// +// GameMetadataTableViewCell.swift +// Delta +// +// Created by Riley Testut on 3/27/17. +// Copyright © 2017 Riley Testut. All rights reserved. +// + +import UIKit + +class GameMetadataTableViewCell: UITableViewCell +{ + @IBOutlet private(set) var nameLabel: UILabel! + @IBOutlet private(set) var artworkImageView: UIImageView! + + @IBOutlet private(set) var artworkImageViewLeadingConstraint: NSLayoutConstraint! + @IBOutlet private(set) var artworkImageViewTrailingConstraint: NSLayoutConstraint! + + override func awakeFromNib() + { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) + { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } +} diff --git a/Delta/Database/OpenVGDB/GamesDatabaseBrowserViewController.swift b/Delta/Database/OpenVGDB/GamesDatabaseBrowserViewController.swift index 12b1d3e..74aacec 100644 --- a/Delta/Database/OpenVGDB/GamesDatabaseBrowserViewController.swift +++ b/Delta/Database/OpenVGDB/GamesDatabaseBrowserViewController.swift @@ -7,6 +7,8 @@ // import UIKit +import AVFoundation + import Roxas class GamesDatabaseBrowserViewController: UITableViewController @@ -37,17 +39,17 @@ class GamesDatabaseBrowserViewController: UITableViewController self.dataSource = RSTArrayTableViewDataSource(items: []) - let titleText = NSLocalizedString("Games Database", comment: "") - let detailText = NSLocalizedString("To search the database, type the name of a game in the search bar.", comment: "") - let placeholderView = RSTBackgroundView() - placeholderView.textLabel.text = titleText - placeholderView.detailTextLabel.text = detailText + placeholderView.textLabel.textColor = UIColor.lightText + placeholderView.detailTextLabel.textColor = UIColor.lightText + self.dataSource.placeholderView = placeholderView super.init(coder: aDecoder) - self.dataSource.cellConfigurationHandler = self.configure(cell:with:for:) + self.dataSource.cellConfigurationHandler = { (cell, metadata, indexPath) in + self.configure(cell: cell as! GameMetadataTableViewCell, with: metadata, for: indexPath) + } if let database = self.database { @@ -60,19 +62,8 @@ class GamesDatabaseBrowserViewController: UITableViewController dataSource.items = results - if searchValue.text == "" - { - rst_dispatch_sync_on_main_thread { - placeholderView.textLabel.text = titleText - placeholderView.detailTextLabel.text = detailText - } - } - else - { - rst_dispatch_sync_on_main_thread { - 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: "") - } + rst_dispatch_sync_on_main_thread { + self.updatePlaceholderView() } }) } @@ -81,27 +72,46 @@ class GamesDatabaseBrowserViewController: UITableViewController self.definesPresentationContext = true } + override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + override func viewDidLoad() { super.viewDidLoad() + self.view.backgroundColor = UIColor.deltaDarkGray + self.tableView.dataSource = self.dataSource + self.tableView.indicatorStyle = .white + self.tableView.separatorColor = UIColor.gray + + self.dataSource.searchController.delegate = self + self.dataSource.searchController.searchBar.barStyle = .blackTranslucent self.tableView.tableHeaderView = self.dataSource.searchController.searchBar - self.tableView.rowHeight = 64 + + self.updatePlaceholderView() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } - - func configure(cell: UITableViewCell, with metadata: GameMetadata, for indexPath: IndexPath) +} + +extension GamesDatabaseBrowserViewController +{ + func configure(cell: GameMetadataTableViewCell, with metadata: GameMetadata, for indexPath: IndexPath) { - cell.textLabel?.text = metadata.name ?? NSLocalizedString("Unknown", comment: "") - cell.textLabel?.numberOfLines = 2 + cell.backgroundColor = UIColor.deltaDarkGray - cell.imageView?.image = #imageLiteral(resourceName: "BoxArt") - cell.imageView?.contentMode = .scaleAspectFit + cell.nameLabel.text = metadata.name ?? NSLocalizedString("Unknown", comment: "") + cell.artworkImageView.image = #imageLiteral(resourceName: "BoxArt") + + cell.artworkImageViewLeadingConstraint.constant = 15 + cell.artworkImageViewTrailingConstraint.constant = 15 + + cell.separatorInset.left = cell.nameLabel.frame.minX if let artworkURL = metadata.artworkURL { @@ -110,9 +120,16 @@ class GamesDatabaseBrowserViewController: UITableViewController operation.resultHandler = { (image, error) in if let image = image { + let artworkDisplaySize = AVMakeRect(aspectRatio: image.size, insideRect: cell.artworkImageView.bounds) + let offset = (cell.artworkImageView.bounds.width - artworkDisplaySize.width) / 2 + DispatchQueue.main.async { - cell.imageView?.image = image - cell.imageView?.superview?.layoutIfNeeded() + // Offset artworkImageViewLeadingConstraint and artworkImageViewTrailingConstraint to right-align artworkImageView + cell.artworkImageViewLeadingConstraint.constant += offset + cell.artworkImageViewTrailingConstraint.constant -= offset + + cell.artworkImageView.image = image + cell.artworkImageView.superview?.layoutIfNeeded() } } } @@ -120,6 +137,22 @@ class GamesDatabaseBrowserViewController: UITableViewController self.operationQueue.addOperation(operation, forKey: indexPath as NSIndexPath) } } + + func updatePlaceholderView() + { + guard let placeholderView = self.dataSource.placeholderView as? RSTBackgroundView else { return } + + if self.dataSource.searchController.searchBar.text == "" + { + placeholderView.textLabel.text = NSLocalizedString("Games Database", comment: "") + placeholderView.detailTextLabel.text = NSLocalizedString("To search the database, type the name of a game in the search bar.", comment: "") + } + else + { + 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: "") + } + } } extension GamesDatabaseBrowserViewController @@ -141,3 +174,26 @@ extension GamesDatabaseBrowserViewController operation?.cancel() } } + +extension GamesDatabaseBrowserViewController: UISearchControllerDelegate +{ + func didPresentSearchController(_ searchController: UISearchController) + { + // Fix incorrect table view scroll indicator insets + self.tableView.scrollIndicatorInsets.top = self.navigationController!.navigationBar.bounds.height + UIApplication.shared.statusBarFrame.height + } + + func willDismissSearchController(_ searchController: UISearchController) + { + // Manually set items to empty array to prevent crash if user dismissses searchController while scrolling + self.dataSource.items = [] + self.updatePlaceholderView() + } + + func didDismissSearchController(_ searchController: UISearchController) + { + // Fix potentially incorrect offset if user dismisses searchController while scrolling + self.tableView.setContentOffset(CGPoint.zero, animated: false) + self.tableView.setContentOffset(CGPoint(x: 0, y: -self.topLayoutGuide.length), animated: false) + } +}