diff --git a/Cores/Mini_vMac/PVMiniVMac.xcodeproj/project.pbxproj b/Cores/Mini_vMac/PVMiniVMac.xcodeproj/project.pbxproj index 54517bac29..b74b9ff89b 100644 --- a/Cores/Mini_vMac/PVMiniVMac.xcodeproj/project.pbxproj +++ b/Cores/Mini_vMac/PVMiniVMac.xcodeproj/project.pbxproj @@ -890,7 +890,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Update Repository\nif [ \"${TARGET_DEVICE_PLATFORM_NAME}\" = \"iphonesimulator\" ] ; then\n exit 0\nfi\nif [[ \"${CODE_SIGNING_ALLOWED}\" = \"NO\" && ! -f \"${SRCROOT}/../../CodeSigning.xcconfig\" ]]; then\n exit 0\nfi\n\n# Create buildTV Environment\nif [ ! -d \"${SRCROOT}/cmake/buildTV\" ]; then\n mkdir \"${SRCROOT}/cmake/buildTV\"\nfi\n\ncd \"${SRCROOT}\"\nexport LATEST=`git submodule status libretro-minivmac | head -n1 | awk '{print $1;}'`TVBuild2\nif [ ! -f \"${SRCROOT}/cmake/${LATEST}\" ]; then\n rm -fr \"${SRCROOT}/cmake/buildTV/\"*\n touch \"${SRCROOT}/cmake/${LATEST}\"\n cp -pR \"${SRCROOT}/libretro-minivmac/\"* \"${SRCROOT}/cmake/buildTV/\"\n cp \"${SRCROOT}/cmake/Makefile.TV\" \"${SRCROOT}/cmake/buildTV/Makefile\"\nfi\n\n# buildTV\ncd \"${SRCROOT}/cmake/buildTV/\"\n#make clean\nmake -j5\ncp minivmac_libretro_tvos.dylib \"${SRCROOT}/../../CoresRetro/RetroArch/modules/minivmac_libretro_tvos.dylib\"\n"; + shellScript = "# Update Repository\nif [ \"${TARGET_DEVICE_PLATFORM_NAME}\" = \"appletvsimulator\" ] ; then\n exit 0\nfi\nif [[ \"${CODE_SIGNING_ALLOWED}\" = \"NO\" && ! -f \"${SRCROOT}/../../CodeSigning.xcconfig\" ]]; then\n exit 0\nfi\n\n# Create buildTV Environment\nif [ ! -d \"${SRCROOT}/cmake/buildTV\" ]; then\n mkdir \"${SRCROOT}/cmake/buildTV\"\nfi\n\ncd \"${SRCROOT}\"\nexport LATEST=`git submodule status libretro-minivmac | head -n1 | awk '{print $1;}'`TVBuild2\nif [ ! -f \"${SRCROOT}/cmake/${LATEST}\" ]; then\n rm -fr \"${SRCROOT}/cmake/buildTV/\"*\n touch \"${SRCROOT}/cmake/${LATEST}\"\n cp -pR \"${SRCROOT}/libretro-minivmac/\"* \"${SRCROOT}/cmake/buildTV/\"\n cp \"${SRCROOT}/cmake/Makefile.TV\" \"${SRCROOT}/cmake/buildTV/Makefile\"\nfi\n\n# buildTV\ncd \"${SRCROOT}/cmake/buildTV/\"\n#make clean\nmake -j5\ncp minivmac_libretro_tvos.dylib \"${SRCROOT}/../../CoresRetro/RetroArch/modules/minivmac_libretro_tvos.dylib\"\n"; }; 9396AEF62973074100B1EA1C /* ShellScript */ = { isa = PBXShellScriptBuildPhase; diff --git a/Provenance.xcodeproj/project.pbxproj b/Provenance.xcodeproj/project.pbxproj index 94386e868f..555eb3cebc 100644 --- a/Provenance.xcodeproj/project.pbxproj +++ b/Provenance.xcodeproj/project.pbxproj @@ -1379,8 +1379,6 @@ B3F7E5A7297736C200362B92 /* PVYabause.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B3FF641C2873EAEB00829C14 /* PVYabause.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B3F7E5A9297736C200362B92 /* Spotlight.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = B3E21D6B203211BE009939D3 /* Spotlight.appex */; platformFilters = (ios, tvos, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; B3F94A4C27093794002A71EF /* PVAppDelegate+AppCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B357A43B2709228E002C7C0F /* PVAppDelegate+AppCenter.swift */; }; - B3F94A4E27093ABC002A71EF /* AppCenterAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = B3F94A4D27093ABC002A71EF /* AppCenterAnalytics */; }; - B3F94A5027093ABC002A71EF /* AppCenterCrashes in Frameworks */ = {isa = PBXBuildFile; productRef = B3F94A4F27093ABC002A71EF /* AppCenterCrashes */; }; B3FAC921292B44F3005E8B11 /* PVAtari800.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B354693B1DECDA710018B6F3 /* PVAtari800.framework */; }; B3FAC922292B44F4005E8B11 /* PVAtari800.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B354693B1DECDA710018B6F3 /* PVAtari800.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B3FAC929292B4505005E8B11 /* PVFCEU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3270F8B27DCB2B200E83180 /* PVFCEU.framework */; }; @@ -2806,8 +2804,6 @@ B324C30A219195AE009F4EDC /* AudioToolbox.framework in Frameworks */, B324C64F219216DD009F4EDC /* PVLibrary.framework in Frameworks */, B3AF701C21916E38000FA7F9 /* PVSupport.framework in Frameworks */, - B3F94A5027093ABC002A71EF /* AppCenterCrashes in Frameworks */, - B3F94A4E27093ABC002A71EF /* AppCenterAnalytics in Frameworks */, B324C308219195A8009F4EDC /* GLKit.framework in Frameworks */, B3FAC992292B4767005E8B11 /* PVGBA.framework in Frameworks */, B3AEDE2B293F34CA0050BDB6 /* PVPicoDrive.framework in Frameworks */, @@ -4620,11 +4616,11 @@ buildConfigurationList = 1AD481C81BA350A500FDA50A /* Build configuration list for PBXNativeTarget "ProvenanceTV" */; buildPhases = ( 1AD481B01BA350A400FDA50A /* Sources */, + 1AACCAE61BB60DB500DC21AE /* Embed Frameworks */, + B39DC780279E79D40017E28D /* Embed App Extensions */, 1AD481B11BA350A400FDA50A /* Frameworks */, 1AD481B21BA350A400FDA50A /* Resources */, 1A44C0AE1D0A1E730018751A /* Script: Set Build Number */, - 1AACCAE61BB60DB500DC21AE /* Embed Frameworks */, - B39DC780279E79D40017E28D /* Embed App Extensions */, ); buildRules = ( ); @@ -4637,8 +4633,6 @@ name = ProvenanceTV; packageProductDependencies = ( B3D30FC026F0BCE60064603F /* SteamController */, - B3F94A4D27093ABC002A71EF /* AppCenterAnalytics */, - B3F94A4F27093ABC002A71EF /* AppCenterCrashes */, B3CE94B6293446AC0053B891 /* Introspect */, B3AFCF992977A81F00A01010 /* PVLogging */, B3E88CBD2977AB7C00C90E86 /* Reachability */, @@ -10994,16 +10988,6 @@ package = B3F7E431297736C200362B92 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; productName = Introspect; }; - B3F94A4D27093ABC002A71EF /* AppCenterAnalytics */ = { - isa = XCSwiftPackageProductDependency; - package = B357A43627092253002C7C0F /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */; - productName = AppCenterAnalytics; - }; - B3F94A4F27093ABC002A71EF /* AppCenterCrashes */ = { - isa = XCSwiftPackageProductDependency; - package = B357A43627092253002C7C0F /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */; - productName = AppCenterCrashes; - }; B3FB9678276DD7F600F7EDEE /* SteamController */ = { isa = XCSwiftPackageProductDependency; package = B3D30FBD26F0B4CD0064603F /* XCRemoteSwiftPackageReference "SteamController" */; diff --git a/Provenance.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Provenance.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index a6f6fb21de..ff23ebc817 100644 --- a/Provenance.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/Provenance.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -3,7 +3,7 @@ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded - + PreviewsEnabled diff --git a/Provenance.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Provenance.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0746f52e73..2001e4374e 100644 --- a/Provenance.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Provenance.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -132,7 +132,7 @@ "repositoryURL": "https://github.com/siteline/SwiftUI-Introspect", "state": { "branch": "master", - "revision": "d3cbf32788250741d397cfb5bcd532c37aa1096d", + "revision": "8bf15ad33a529359200bd419a72ca2dda841089b", "version": null } }, diff --git a/Provenance/Emulator/PVEmulatorVC/PVEmulatorViewController+PauseMenu.swift b/Provenance/Emulator/PVEmulatorVC/PVEmulatorViewController+PauseMenu.swift index 5326052cf3..aa94b8a7b1 100644 --- a/Provenance/Emulator/PVEmulatorVC/PVEmulatorViewController+PauseMenu.swift +++ b/Provenance/Emulator/PVEmulatorVC/PVEmulatorViewController+PauseMenu.swift @@ -23,9 +23,7 @@ extension PVEmulatorViewController { if let menuButton = menuButton { actionSheet.popoverPresentationController?.sourceView = menuButton actionSheet.popoverPresentationController?.sourceRect = menuButton.bounds - } else { - return - } + } #if targetEnvironment(macCatalyst) || os(macOS) if let menuButton = menuButton, sender === menuButton { actionSheet.popoverPresentationController?.sourceView = menuButton diff --git a/Provenance/Game Library/UI/Cheats/PVCheatsViewController.swift b/Provenance/Game Library/UI/Cheats/PVCheatsViewController.swift index 3732b73613..3d123ca277 100644 --- a/Provenance/Game Library/UI/Cheats/PVCheatsViewController.swift +++ b/Provenance/Game Library/UI/Cheats/PVCheatsViewController.swift @@ -127,8 +127,8 @@ final class PVCheatsViewController: UITableViewController { let alert = UIAlertController(title: "Delete this Cheat Code?", message: nil, preferredStyle: .alert) alert.preferredContentSize = CGSize(width: 300, height: 150) - alert.popoverPresentationController?.sourceView = self.view - alert.popoverPresentationController?.sourceRect = UIScreen.main.bounds + alert.popoverPresentationController?.sourceView = tableView?.cellForRow(at: indexPath)?.contentView + alert.popoverPresentationController?.sourceRect = tableView?.cellForRow(at: indexPath)?.contentView.bounds ?? UIScreen.main.bounds alert.addAction(UIAlertAction(title: "Yes", style: .destructive) { [unowned self] _ in do { try PVCheats.delete(saveState) diff --git a/Provenance/Game Library/UI/Game Library/CollectionViewController/PVGameLibraryViewController.swift b/Provenance/Game Library/UI/Game Library/CollectionViewController/PVGameLibraryViewController.swift index dbcdfc2f6f..4d49ad8f87 100644 --- a/Provenance/Game Library/UI/Game Library/CollectionViewController/PVGameLibraryViewController.swift +++ b/Provenance/Game Library/UI/Game Library/CollectionViewController/PVGameLibraryViewController.swift @@ -811,7 +811,7 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg })) let webServerAction = UIAlertAction(title: "Web Server", style: .default, handler: { _ in - self.startWebServer() + self.startWebServer(sender: sender as? UIView) }) actionSheet.addAction(webServerAction) @@ -853,16 +853,16 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg WLOG("No WiFi. Cannot start web server.") present(alert, animated: true) { () -> Void in } } else { - startWebServer() + startWebServer(sender: sender as? UIView) } #endif } - func startWebServer() { + func startWebServer(sender: UIView?) { // start web transfer service if PVWebServer.shared.startServers() { // show alert view - showServerActiveAlert() + showServerActiveAlert(sender: self.collectionView, barButtonItem: navigationItem.rightBarButtonItem) } else { #if targetEnvironment(simulator) || targetEnvironment(macCatalyst) || os(macOS) let message = "Check your network connection or settings and free up ports: 8080, 8081." @@ -870,6 +870,10 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg let message = "Check your network connection or settings and free up ports: 80, 81." #endif let alert = UIAlertController(title: "Unable to start web server!", message: message, preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem + alert.popoverPresentationController?.sourceView = self.collectionView + alert.popoverPresentationController?.sourceRect = self.collectionView?.bounds ?? UIScreen.main.bounds alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_: UIAlertAction) -> Void in })) present(alert, animated: true) { () -> Void in } @@ -908,6 +912,10 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg fileprivate func showConflictsAlert() { let alert = UIAlertController(title: "Oops!", message: "There was a conflict while importing your game.", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.barButtonItem = navigationItem.leftBarButtonItem + alert.popoverPresentationController?.sourceView = self.collectionView + alert.popoverPresentationController?.sourceRect = self.collectionView?.bounds ?? UIScreen.main.bounds alert.addAction(UIAlertAction(title: "Let's go fix it!", style: .default, handler: { [unowned self] (_: UIAlertAction) -> Void in self.displayConflictVC() })) @@ -1032,6 +1040,9 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg actionSheet.addAction(UIAlertAction(title: "Reset default core selection (\(coreName))", symbol:"bolt.circle", style: .default, handler: { [unowned self] _ in let resetAlert = UIAlertController(title: "Reset core?", message: "Are you sure you want to reset \(game.title) to no longer default to use \(coreName)?", preferredStyle: .alert) + resetAlert.preferredContentSize = CGSize(width: 300, height: 150) + resetAlert.popoverPresentationController?.sourceView = sender + resetAlert.popoverPresentationController?.sourceRect = sender.bounds ?? UIScreen.main.bounds resetAlert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel"), style: .cancel, handler: nil)) resetAlert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { _ in try! RomDatabase.sharedInstance.writeTransaction { @@ -1076,7 +1087,7 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg })) actionSheet.addAction(UIAlertAction(title: "Rename", symbol: "rectangle.and.pencil.and.ellipsis", style: .default, handler: { (_: UIAlertAction) -> Void in - self.renameGame(game) + self.renameGame(game, sender: sender) })) #if os(iOS) @@ -1084,6 +1095,9 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg let md5URL = "provenance://open?md5=\(game.md5Hash)" UIPasteboard.general.string = md5URL let alert = UIAlertController(title: nil, message: "URL copied to clipboard.", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender.bounds ?? UIScreen.main.bounds self.present(alert, animated: true) DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: { alert.dismiss(animated: true, completion: nil) @@ -1154,6 +1168,9 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg actionSheet.addAction(UIAlertAction(title: "Delete", symbol:"trash", style: .destructive, handler: { (_: UIAlertAction) -> Void in let alert = UIAlertController(title: "Delete \(game.title)", message: "Any save states and battery saves will also be deleted, are you sure?", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender.bounds alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (_: UIAlertAction) -> Void in // Delete from Realm do { @@ -1207,8 +1224,11 @@ final class PVGameLibraryViewController: GCEventViewController, UITextFieldDeleg #endif } - func renameGame(_ game: PVGame) { + func renameGame(_ game: PVGame, sender: UIView) { let alert = UIAlertController(title: "Rename", message: "Enter a new name for \(game.title):", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender.bounds ?? UIScreen.main.bounds alert.addTextField(configurationHandler: { (_ textField: UITextField) -> Void in textField.placeholder = game.title textField.text = game.title @@ -1749,7 +1769,7 @@ extension PVGameLibraryViewController { guard let focusedGame = focusedGame else { return } - renameGame(focusedGame) + renameGame(focusedGame, sender: self.collectionView!) } @objc @@ -1807,6 +1827,9 @@ extension PVGameLibraryViewController { extension PVGameLibraryViewController: GameLibraryCollectionViewDelegate { func promptToDeleteGame(_ game: PVGame, completion: ((Bool) -> Void)? = nil) { let alert = UIAlertController(title: "Delete \(game.title)", message: "Any save states and battery saves will also be deleted, are you sure?", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.sourceView = self.collectionView + alert.popoverPresentationController?.sourceRect = self.collectionView?.bounds ?? UIScreen.main.bounds alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (_: UIAlertAction) -> Void in // Delete from Realm do { diff --git a/Provenance/Game Library/UI/GameLaunchingViewController.swift b/Provenance/Game Library/UI/GameLaunchingViewController.swift index 354f4601f6..92cf0aa308 100644 --- a/Provenance/Game Library/UI/GameLaunchingViewController.swift +++ b/Provenance/Game Library/UI/GameLaunchingViewController.swift @@ -442,19 +442,19 @@ extension GameLaunchingViewController where Self: UIViewController { } #endif - let thisTimeOnlyAction = UIAlertAction(title: "This time", style: .default, handler: { _ in self.presentEMU(withCore: core, forGame: game) }) + let thisTimeOnlyAction = UIAlertAction(title: "This time", style: .default, handler: { _ in self.presentEMU(withCore: core, forGame: game, source: sender as? UIView ?? self.view) }) let alwaysThisGameAction = UIAlertAction(title: "Always for this game", style: .default, handler: { [unowned self] _ in try! RomDatabase.sharedInstance.writeTransaction { game.userPreferredCoreID = core.identifier } - self.presentEMU(withCore: core, forGame: game) + self.presentEMU(withCore: core, forGame: game, source: sender as? UIView ?? self.view) }) let alwaysThisSytemAction = UIAlertAction(title: "Always for this system", style: .default, handler: { [unowned self] _ in try! RomDatabase.sharedInstance.writeTransaction { system.userPreferredCoreID = core.identifier } - self.presentEMU(withCore: core, forGame: game) + self.presentEMU(withCore: core, forGame: game, source: sender as? UIView ?? self.view) }) alwaysUseAlert.addAction(thisTimeOnlyAction) @@ -542,14 +542,14 @@ extension GameLaunchingViewController where Self: UIViewController { if let userSelecion = game.userPreferredCoreID ?? system.userPreferredCoreID, let chosenCore = cores.first(where: { $0.identifier == userSelecion }) { ILOG("User has already selected core \(chosenCore.projectName) for \(system.shortName)") - presentEMU(withCore: chosenCore, forGame: game) + presentEMU(withCore: chosenCore, forGame: game, source: sender as? UIView ?? self.view) return } // User has no core preference, present dialogue to pick presentCoreSelection(forGame: game, sender: sender) } else { - presentEMU(withCore: selectedCore ?? cores.first!, forGame: game, fromSaveState: saveState) + presentEMU(withCore: selectedCore ?? cores.first!, forGame: game, fromSaveState: saveState, source: sender as? UIView ?? self.view) // let contentId : String = "\(system.shortName):\(game.title)" // let customAttributes : [String : Any] = ["timeSpent" : game.timeSpentInGame, "md5" : game.md5Hash] // Answers.logContentView(withName: "Play ROM", @@ -582,7 +582,7 @@ extension GameLaunchingViewController where Self: UIViewController { } } - private func presentEMU(withCore core: PVCore, forGame game: PVGame, fromSaveState saveState: PVSaveState? = nil) { + private func presentEMU(withCore core: PVCore, forGame game: PVGame, fromSaveState saveState: PVSaveState? = nil, source: UIView?) { guard let coreInstance = core.createInstance(forSystem: game.system) else { displayAndLogError(withTitle: "Cannot open game", message: "Failed to create instance of core '\(core.projectName)'.") ELOG("Failed to init core instance") @@ -592,15 +592,13 @@ extension GameLaunchingViewController where Self: UIViewController { let emulatorViewController = PVEmulatorViewController(game: game, core: coreInstance) // Check if Save State exists - /* - if saveState == nil, emulatorViewController.core.supportsSaveStates { - checkForSaveStateThenRun(withCore: core, forGame: game) { optionallyChosenSaveState in + if saveState == nil, emulatorViewController.core.supportsSaveStates { + checkForSaveStateThenRun(withCore: core, forGame: game, source: source) { optionallyChosenSaveState in self.presentEMUVC(emulatorViewController, withGame: game, loadingSaveState: optionallyChosenSaveState) } } else { - */ presentEMUVC(emulatorViewController, withGame: game, loadingSaveState: saveState) - //} + } } // Used to just show and then optionally quickly load any passed in PVSaveStates @@ -645,7 +643,7 @@ extension GameLaunchingViewController where Self: UIViewController { updateRecentGames(game) } - private func checkForSaveStateThenRun(withCore core: PVCore, forGame game: PVGame, completion: @escaping (PVSaveState?) -> Void) { + private func checkForSaveStateThenRun(withCore core: PVCore, forGame game: PVGame, source: UIView?, completion: @escaping (PVSaveState?) -> Void) { if let latestSaveState = game.saveStates.filter("core.identifier == \"\(core.identifier)\"").sorted(byKeyPath: "date", ascending: false).first { let shouldAskToLoadSaveState: Bool = PVSettingsModel.shared.askToAutoLoad let shouldAutoLoadSaveState: Bool = PVSettingsModel.shared.autoLoadSaves @@ -657,8 +655,8 @@ extension GameLaunchingViewController where Self: UIViewController { let alert = UIAlertController(title: "Save State Detected", message: nil, preferredStyle: .actionSheet) // TODO: XCode15/iOS17 Requires actual source view here alert.preferredContentSize = CGSize(width: 300, height: 150) - alert.popoverPresentationController?.sourceView = self.view - alert.popoverPresentationController?.sourceRect = UIScreen.main.bounds + alert.popoverPresentationController?.sourceView = source + alert.popoverPresentationController?.sourceRect = source?.bounds ?? UIScreen.main.bounds #if os(iOS) let switchControl = UISwitch() switchControl.isOn = !PVSettingsModel.shared.askToAutoLoad diff --git a/Provenance/Game Library/UI/QuickTableViewController/Views/SwitchCell.swift b/Provenance/Game Library/UI/QuickTableViewController/Views/SwitchCell.swift index 61659d15d9..8aa4024952 100644 --- a/Provenance/Game Library/UI/QuickTableViewController/Views/SwitchCell.swift +++ b/Provenance/Game Library/UI/QuickTableViewController/Views/SwitchCell.swift @@ -49,9 +49,10 @@ open class SwitchCell: UITableViewCell, Configurable { #endif /// The switch cell's delegate object, which should conform to `SwitchCellDelegate`. Not available on tvOS. +#if !os(tvOS) @available(tvOS, unavailable, message: "SwitchCellDelegate is not available on tvOS.") open weak var delegate: SwitchCellDelegate? - +#endif // MARK: - Initializer /** @@ -99,7 +100,9 @@ open class SwitchCell: UITableViewCell, Configurable { @available(tvOS, unavailable, message: "UISwitch is not available on tvOS.") @objc private func didToggleSwitch(_ sender: UISwitch) { +#if !os(tvOS) delegate?.switchCell(self, didToggleSwitch: sender.isOn) +#endif } private func setUpAppearance() { diff --git a/Provenance/Game Library/UI/SaveStates/PVSaveStatesViewController.swift b/Provenance/Game Library/UI/SaveStates/PVSaveStatesViewController.swift index f71b8900bb..79a7e70ddb 100644 --- a/Provenance/Game Library/UI/SaveStates/PVSaveStatesViewController.swift +++ b/Provenance/Game Library/UI/SaveStates/PVSaveStatesViewController.swift @@ -199,8 +199,8 @@ final class PVSaveStatesViewController: UICollectionViewController { let alert = UIAlertController(title: "Delete this save state?", message: nil, preferredStyle: .alert) alert.preferredContentSize = CGSize(width: 300, height: 150) - alert.popoverPresentationController?.sourceView = self.view - alert.popoverPresentationController?.sourceRect = UIScreen.main.bounds + alert.popoverPresentationController?.sourceView = collectionView?.cellForItem(at: indexPath)?.contentView + alert.popoverPresentationController?.sourceRect = collectionView?.cellForItem(at: indexPath)?.contentView.bounds ?? UIScreen.main.bounds alert.addAction(UIAlertAction(title: "Yes", style: .destructive) { [unowned self] _ in do { try PVSaveState.delete(saveState) @@ -231,11 +231,11 @@ final class PVSaveStatesViewController: UICollectionViewController { } } - func showSaveStateOptions(saveState: PVSaveState) { + func showSaveStateOptions(saveState: PVSaveState, source: UIView?) { let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) alert.preferredContentSize = CGSize(width: 300, height: 150) - alert.popoverPresentationController?.sourceView = self.view - alert.popoverPresentationController?.sourceRect = UIScreen.main.bounds + alert.popoverPresentationController?.sourceView = source + alert.popoverPresentationController?.sourceRect = source?.bounds ?? UIScreen.main.bounds alert.addAction(UIAlertAction(title: "Load", style: .default, handler: { (_: UIAlertAction) in self.delegate?.saveStatesViewController(self, load: saveState) })) @@ -323,7 +323,7 @@ final class PVSaveStatesViewController: UICollectionViewController { ELOG("No save state at indexPath: \(indexPath)") return } - showSaveStateOptions(saveState: state) + showSaveStateOptions(saveState: state, source: collectionView?.cellForItem(at: indexPath)?.contentView) default: break } diff --git a/Provenance/Settings/PVSettingsViewController.swift b/Provenance/Settings/PVSettingsViewController.swift index b2710d1496..0e254b8cc0 100644 --- a/Provenance/Settings/PVSettingsViewController.swift +++ b/Provenance/Settings/PVSettingsViewController.swift @@ -630,7 +630,7 @@ final class PVSettingsViewController: QuickTableViewController { // start web transfer service if PVWebServer.shared.startServers() { // show alert view - showServerActiveAlert() + showServerActiveAlert(sender: self.tableView, barButtonItem: nil) } else { // Display error let alert = UIAlertController(title: "Unable to start web server!", diff --git a/Provenance/Settings/WebServerActivatorController.swift b/Provenance/Settings/WebServerActivatorController.swift index c7888c24b3..2bb526fb76 100644 --- a/Provenance/Settings/WebServerActivatorController.swift +++ b/Provenance/Settings/WebServerActivatorController.swift @@ -12,7 +12,7 @@ import Reachability import UIKit protocol WebServerActivatorController: AnyObject { - func showServerActiveAlert() + func showServerActiveAlert(sender: UIView?, barButtonItem: UIBarButtonItem?) } #if os(iOS) @@ -35,8 +35,12 @@ protocol WebServerActivatorController: AnyObject { return message } - func showServerActiveAlert() { + func showServerActiveAlert(sender: UIView?, barButtonItem: UIBarButtonItem?) { let alert = UIAlertController(title: "Web Server Active", message: webServerAlertMessage, preferredStyle: .alert) + alert.popoverPresentationController?.barButtonItem = barButtonItem + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender?.bounds ?? UIScreen.main.bounds + alert.preferredContentSize = CGSize(width: 300, height: 150) alert.addAction(UIAlertAction(title: "Stop", style: .cancel, handler: { (_: UIAlertAction) -> Void in PVWebServer.shared.stopServers() })) @@ -89,7 +93,7 @@ extension WebServerActivatorController where Self: WebServerActivatorControllerR return message } - func showServerActiveAlert() { + func showServerActiveAlert(sender: UIView?, barButtonItem: UIBarButtonItem?) { // Start Webserver // Check to see if we are connected to WiFi. Cannot continue otherwise. let reachability = try! Reachability() @@ -105,6 +109,12 @@ extension WebServerActivatorController where Self: WebServerActivatorControllerR // start web transfer service if PVWebServer.shared.startServers() { let alert = UIAlertController(title: "Web Server Active", message: webServerAlertMessage, preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) +#if !os(tvOS) + alert.popoverPresentationController?.barButtonItem = barButtonItem + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender?.bounds ?? UIScreen.main.bounds +#endif alert.addAction(UIAlertAction(title: "Stop", style: .cancel, handler: { (_: UIAlertAction) -> Void in PVWebServer.shared.stopServers() })) @@ -121,12 +131,24 @@ extension WebServerActivatorController where Self: WebServerActivatorControllerR } else { // Display error let alert = UIAlertController(title: "Unable to start web server!", message: "Check your network connection or settings and free up ports: 80, 81.", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) +#if !os(tvOS) + alert.popoverPresentationController?.barButtonItem = barButtonItem + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender?.bounds ?? UIScreen.main.bounds +#endif alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_: UIAlertAction) -> Void in })) present(alert, animated: true) { () -> Void in } } } else { let alert = UIAlertController(title: "Unable to start web server!", message: "Your device needs to be connected to a WiFi network to continue!", preferredStyle: .alert) + alert.preferredContentSize = CGSize(width: 300, height: 150) + alert.popoverPresentationController?.barButtonItem = barButtonItem +#if !os(tvOS) + alert.popoverPresentationController?.sourceView = sender + alert.popoverPresentationController?.sourceRect = sender?.bounds ?? UIScreen.main.bounds +#endif alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_: UIAlertAction) -> Void in })) present(alert, animated: true) { () -> Void in } diff --git a/Provenance/http/GCDWebServer/Core/GCDWebServer.m b/Provenance/http/GCDWebServer/Core/GCDWebServer.m index fadbbb47e1..09bb34a3dc 100644 --- a/Provenance/http/GCDWebServer/Core/GCDWebServer.m +++ b/Provenance/http/GCDWebServer/Core/GCDWebServer.m @@ -779,7 +779,11 @@ - (void)stop { } _options = nil; } else { - GWS_DNOT_REACHED(); +#if TARGET_OS_TV + //[self _stop]; +#else + GWS_DNOT_REACHED(); +#endif } } diff --git a/README.md b/README.md index 04517eeb16..8005e1ab3e 100644 --- a/README.md +++ b/README.md @@ -270,10 +270,31 @@ Provenance would not be possible without the great work of those who came before + + +
- - rf2222222 + + jasarien
- Richard + James Addyman +
+
+ + JoeMatt +
+ Joe Mattiello +
+
+ + sevdestruct +
+ Sev +
+
+ + mrjschulte +
+ MrJs