Shows AirPlay icon + message when AirPlaying

This commit is contained in:
Riley Testut 2023-11-16 17:44:55 -06:00
parent 4b159603a1
commit a87fea63ad
3 changed files with 102 additions and 3 deletions

View File

@ -209,6 +209,7 @@
D5CDCCF12A859E7500E22131 /* ReviewSaveStatesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A1375A2A7D8F2600AB1372 /* ReviewSaveStatesViewController.swift */; }; D5CDCCF12A859E7500E22131 /* ReviewSaveStatesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A1375A2A7D8F2600AB1372 /* ReviewSaveStatesViewController.swift */; };
D5CDCCF22A859E7500E22131 /* RepairDatabaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A137442A7D814000AB1372 /* RepairDatabaseViewController.swift */; }; D5CDCCF22A859E7500E22131 /* RepairDatabaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A137442A7D814000AB1372 /* RepairDatabaseViewController.swift */; };
D5CDCCF32A859E7500E22131 /* GamePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A137662A7DB37200AB1372 /* GamePickerViewController.swift */; }; D5CDCCF32A859E7500E22131 /* GamePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A137662A7DB37200AB1372 /* GamePickerViewController.swift */; };
D5D39E792AF2D624004BE3F7 /* GameView+AirPlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D39E782AF2D624004BE3F7 /* GameView+AirPlay.swift */; };
D5D78AE529F9BC3700E064F0 /* DSAirPlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D78AE429F9BC3700E064F0 /* DSAirPlay.swift */; }; D5D78AE529F9BC3700E064F0 /* DSAirPlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D78AE429F9BC3700E064F0 /* DSAirPlay.swift */; };
D5D78AE729F9D40A00E064F0 /* EnvironmentValues+FeatureOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D78AE629F9D40A00E064F0 /* EnvironmentValues+FeatureOption.swift */; }; D5D78AE729F9D40A00E064F0 /* EnvironmentValues+FeatureOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D78AE629F9D40A00E064F0 /* EnvironmentValues+FeatureOption.swift */; };
D5D797E6298D946200738869 /* Contributor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D797E5298D946200738869 /* Contributor.swift */; }; D5D797E6298D946200738869 /* Contributor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D797E5298D946200738869 /* Contributor.swift */; };
@ -484,6 +485,7 @@
D5CDCCC32A85765900E22131 /* OSLog+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSLog+Delta.swift"; sourceTree = "<group>"; }; D5CDCCC32A85765900E22131 /* OSLog+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSLog+Delta.swift"; sourceTree = "<group>"; };
D5CDCCEA2A8593FC00E22131 /* UserDefaults+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Delta.swift"; sourceTree = "<group>"; }; D5CDCCEA2A8593FC00E22131 /* UserDefaults+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Delta.swift"; sourceTree = "<group>"; };
D5CDCCEC2A859B2B00E22131 /* SyncValidationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncValidationError.swift; sourceTree = "<group>"; }; D5CDCCEC2A859B2B00E22131 /* SyncValidationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncValidationError.swift; sourceTree = "<group>"; };
D5D39E782AF2D624004BE3F7 /* GameView+AirPlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameView+AirPlay.swift"; sourceTree = "<group>"; };
D5D78AE429F9BC3700E064F0 /* DSAirPlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSAirPlay.swift; sourceTree = "<group>"; }; D5D78AE429F9BC3700E064F0 /* DSAirPlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSAirPlay.swift; sourceTree = "<group>"; };
D5D78AE629F9D40A00E064F0 /* EnvironmentValues+FeatureOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+FeatureOption.swift"; sourceTree = "<group>"; }; D5D78AE629F9D40A00E064F0 /* EnvironmentValues+FeatureOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+FeatureOption.swift"; sourceTree = "<group>"; };
D5D797E5298D946200738869 /* Contributor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contributor.swift; sourceTree = "<group>"; }; D5D797E5298D946200738869 /* Contributor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contributor.swift; sourceTree = "<group>"; };
@ -566,6 +568,7 @@
D5CDCCC32A85765900E22131 /* OSLog+Delta.swift */, D5CDCCC32A85765900E22131 /* OSLog+Delta.swift */,
D5CDCCEA2A8593FC00E22131 /* UserDefaults+Delta.swift */, D5CDCCEA2A8593FC00E22131 /* UserDefaults+Delta.swift */,
AC1AE30B2A6A068F00956EB9 /* Bundle+AppIconImage.swift */, AC1AE30B2A6A068F00956EB9 /* Bundle+AppIconImage.swift */,
D5D39E782AF2D624004BE3F7 /* GameView+AirPlay.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1669,6 +1672,7 @@
BF5942861E09BC8B0051894B /* _Cheat.swift in Sources */, BF5942861E09BC8B0051894B /* _Cheat.swift in Sources */,
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */, BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,
BF8CA9361F5F651900499FDD /* PopoverMenuController.swift in Sources */, BF8CA9361F5F651900499FDD /* PopoverMenuController.swift in Sources */,
D5D39E792AF2D624004BE3F7 /* GameView+AirPlay.swift in Sources */,
BFEF24F31F7DD4FD00454C62 /* SaveStateMigrationPolicy.swift in Sources */, BFEF24F31F7DD4FD00454C62 /* SaveStateMigrationPolicy.swift in Sources */,
BF5942931E09BD1A0051894B /* NSFetchedResultsController+Conveniences.m in Sources */, BF5942931E09BD1A0051894B /* NSFetchedResultsController+Conveniences.m in Sources */,
D5CDCCEE2A859DC200E22131 /* SyncValidationError.swift in Sources */, D5CDCCEE2A859DC200E22131 /* SyncValidationError.swift in Sources */,

View File

@ -711,12 +711,24 @@ private extension GameViewController
{ {
// AirPlaying, hide all (non-touch) screens. // AirPlaying, hide all (non-touch) screens.
if let traits = self.controllerView.controllerSkinTraits, let screens = self.controllerView.controllerSkin?.screens(for: traits) if let traits = self.controllerView.controllerSkinTraits,
let supportedTraits = self.controllerView.controllerSkin?.supportedTraits(for: traits),
let screens = self.controllerView.controllerSkin?.screens(for: supportedTraits)
{ {
for (screen, gameView) in zip(screens, self.gameViews) for (screen, gameView) in zip(screens, self.gameViews)
{ {
gameView.isEnabled = screen.isTouchScreen gameView.isEnabled = screen.isTouchScreen
gameView.isHidden = !screen.isTouchScreen
if gameView == self.gameView
{
// Always show AirPlay indicator on self.gameView
gameView.isAirPlaying = true
gameView.isHidden = false
}
else
{
gameView.isHidden = !screen.isTouchScreen
}
} }
} }
else else
@ -725,7 +737,8 @@ private extension GameViewController
// Most likely this system only has 1 screen, so just hide self.gameView. // Most likely this system only has 1 screen, so just hide self.gameView.
self.gameView.isEnabled = false self.gameView.isEnabled = false
self.gameView.isHidden = true self.gameView.isHidden = false
self.gameView.isAirPlaying = true
} }
} }
else else
@ -736,6 +749,7 @@ private extension GameViewController
{ {
gameView.isEnabled = true gameView.isEnabled = true
gameView.isHidden = false gameView.isHidden = false
gameView.isAirPlaying = false
} }
} }
} }
@ -1252,6 +1266,8 @@ private extension GameViewController
// Implicitly called from updateControllerSkin() // Implicitly called from updateControllerSkin()
// self.updateExternalDisplay() // self.updateExternalDisplay()
self.gameView?.isAirPlaying = true
} }
func updateExternalDisplay() func updateExternalDisplay()
@ -1322,6 +1338,8 @@ private extension GameViewController
} }
self.updateControllerSkin() // Reset TouchControllerSkin + GameViews self.updateControllerSkin() // Reset TouchControllerSkin + GameViews
self.gameView?.isAirPlaying = false
} }
} }

View File

@ -0,0 +1,77 @@
//
// GameView+AirPlay.swift
// Delta
//
// Created by Riley Testut on 11/1/23.
// Copyright © 2023 Riley Testut. All rights reserved.
//
import Foundation
import ObjectiveC.runtime
import DeltaCore
import Roxas
private var airPlayViewKey = 0
extension GameView
{
var isAirPlaying: Bool {
get { self.airPlayView != nil }
set {
guard newValue != self.isAirPlaying else { return }
if newValue
{
self.showAirPlayView()
}
else
{
self.hideAirPlayView()
}
}
}
}
private extension GameView
{
weak var airPlayView: UIView? {
get { objc_getAssociatedObject(self, &airPlayViewKey) as? UIView }
set { objc_setAssociatedObject(self, &airPlayViewKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN) }
}
func showAirPlayView()
{
guard self.airPlayView == nil else { return }
let placeholderView = RSTPlaceholderView(frame: .zero)
placeholderView.backgroundColor = .black
placeholderView.textLabel.font = UIFont.preferredFont(forTextStyle: .headline)
placeholderView.textLabel.text = NSLocalizedString("AirPlay", comment: "")
placeholderView.textLabel.textColor = .systemGray
placeholderView.detailTextLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
placeholderView.detailTextLabel.text = NSLocalizedString("This game is playing on a second screen.", comment: "")
placeholderView.detailTextLabel.textColor = .systemGray
let config = UIImage.SymbolConfiguration(pointSize: 100)
let airPlayIcon = UIImage(systemName: "tv", withConfiguration: config)
placeholderView.imageView.image = airPlayIcon
placeholderView.imageView.isHidden = false
placeholderView.imageView.tintColor = .systemGray
self.addSubview(placeholderView, pinningEdgesWith: .zero)
self.airPlayView = placeholderView
}
func hideAirPlayView()
{
guard let airPlayView else { return }
airPlayView.removeFromSuperview()
self.airPlayView = nil
}
}