Skip to content

macCatalyst, tvOS support #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
- macos-12
platform:
- iOS
- mac-catalyst
- tvOS
swift:
- 5.5
- 5.6
Expand Down
4 changes: 4 additions & 0 deletions .spi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ builder:
- platform: ios
scheme: NavigationTransitions
documentation_targets: [NavigationTransitions, NavigationTransition, AtomicTransition, Animator, Animation]
- platform: macos-xcodebuild
scheme: NavigationTransitions
- platform: tvos
scheme: NavigationTransitions
18 changes: 15 additions & 3 deletions Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
D5535834290E9718009E5D72 /* Swing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D553582C290E9718009E5D72 /* Swing.swift */; };
D5535835290E9718009E5D72 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D553582D290E9718009E5D72 /* RootView.swift */; };
D5535836290E9718009E5D72 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D553582E290E9718009E5D72 /* SceneDelegate.swift */; };
D5535837290E9718009E5D72 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D553582F290E9718009E5D72 /* LaunchScreen.storyboard */; };
D5535837290E9718009E5D72 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D553582F290E9718009E5D72 /* LaunchScreen.storyboard */; platformFilter = ios; };
D5535839290E9718009E5D72 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5535831290E9718009E5D72 /* AppDelegate.swift */; };
D553583F290E97C5009E5D72 /* NavigationTransitions in Frameworks */ = {isa = PBXBuildFile; productRef = D553583E290E97C5009E5D72 /* NavigationTransitions */; };
D5535843290F4BEA009E5D72 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5535842290F4BEA009E5D72 /* AppView.swift */; };
Expand All @@ -36,6 +36,7 @@
D5535842290F4BEA009E5D72 /* AppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
D5535844290F52F7009E5D72 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
D5535846290F5E6F009E5D72 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; };
D571826B291C9426003672F5 /* Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Demo.entitlements; sourceTree = "<group>"; };
D5755A78291ADC00007F2201 /* Zoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Zoom.swift; sourceTree = "<group>"; };
D5AAF4042911C59E009743D3 /* PageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageView.swift; sourceTree = "<group>"; };
D5AAF4062911C621009743D3 /* Pages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pages.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -73,6 +74,7 @@
D553581D290E9691009E5D72 /* Demo */ = {
isa = PBXGroup;
children = (
D571826B291C9426003672F5 /* Demo.entitlements */,
D553583C290E978C009E5D72 /* Info.plist */,
D553582F290E9718009E5D72 /* LaunchScreen.storyboard */,
D5535831290E9718009E5D72 /* AppDelegate.swift */,
Expand Down Expand Up @@ -317,6 +319,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Demo/Demo.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Demo/Preview Content\"";
Expand All @@ -337,10 +340,14 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = mn.dro.Demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 13.0;
};
name = Debug;
};
Expand All @@ -350,6 +357,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Demo/Demo.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Demo/Preview Content\"";
Expand All @@ -370,9 +378,13 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = mn.dro.Demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 13.0;
};
name = Release;
};
Expand Down
6 changes: 4 additions & 2 deletions Demo/Demo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import SwiftUI

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
#if !os(tvOS)
func applicationDidFinishLaunching(_ application: UIApplication) {
customizeNavigationBarAppearance()
customizeTabBarAppearance()
Expand All @@ -18,7 +19,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
proxy.scrollEdgeAppearance = customAppearance
proxy.compactAppearance = customAppearance
proxy.standardAppearance = customAppearance
if #available(iOS 15.0, *) {
if #available(iOS 15.0, tvOS 15, *) {
proxy.compactScrollEdgeAppearance = customAppearance
}
}
Expand All @@ -31,10 +32,11 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {

let proxy = UITabBar.appearance()
proxy.standardAppearance = customAppearance
if #available(iOS 15, *) {
if #available(iOS 15, tvOS 15, *) {
proxy.scrollEdgeAppearance = customAppearance
}
}
#endif

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
Expand Down
10 changes: 10 additions & 0 deletions Demo/Demo/Demo.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
25 changes: 18 additions & 7 deletions Demo/Demo/PageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct PageView<Content: View, Link: View, Destination: View>: View {
ZStack {
Rectangle()
.do {
if #available(iOS 16, *) {
if #available(iOS 16, tvOS 16, *) {
$0.fill(color.gradient)
} else {
$0.fill(color)
Expand All @@ -33,23 +33,34 @@ struct PageView<Content: View, Link: View, Destination: View>: View {
.shadow(color: .white.opacity(0.25), radius: 1, x: 0, y: 1)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.foregroundColor(Color(white: 0.14))
if let link = link, let destination = destination {
if #available(iOS 16, *) {
NavigationLink(value: number + 1) { link }
} else {
NavigationLink(destination: destination) { link }
.frame(maxWidth: 1200)

Group {
if let link = link, let destination = destination {
if #available(iOS 16, tvOS 16, *) {
NavigationLink(value: number + 1) { link }
} else {
NavigationLink(destination: destination) { link }
}
}
}
#if os(tvOS)
.frame(maxWidth: 600)
#else
.frame(maxWidth: 300)
#endif
}
.multilineTextAlignment(.center)
.padding(.horizontal)
.padding(.bottom, 30)
}
#if !os(tvOS)
.navigationBarTitle(Text(title), displayMode: .inline)
#endif
.navigationBarItems(
trailing: Button(action: { appState.isPresentingSettings = true }) {
Group {
if #available(iOS 14, *) {
if #available(iOS 14, tvOS 16, *) {
Image(systemName: "gearshape")
} else {
Image(systemName: "gear")
Expand Down
10 changes: 8 additions & 2 deletions Demo/Demo/Pages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct PageOne: View {
PageTwo()
}
.do {
if #available(iOS 16, *) {
if #available(iOS 16, tvOS 16, *) {
$0.navigationDestination(for: Int.self) { number in
switch number {
case 1: PageOne()
Expand Down Expand Up @@ -125,10 +125,14 @@ struct PageLink: View {

var body: some View {
ZStack {
#if !os(tvOS)
RoundedRectangle(cornerRadius: 6, style: .continuous)
.fill(Color.blue.opacity(0.8))
#endif
Text(title)
#if !os(tvOS)
.foregroundColor(.white)
#endif
.font(.system(size: 18, weight: .medium, design: .rounded))
}
.frame(maxHeight: 50)
Expand All @@ -150,20 +154,22 @@ struct Code<Content: StringProtocol>: View {
let shape = RoundedRectangle(cornerRadius: 4, style: .circular)

Text(content)
.frame(maxWidth: .infinity, alignment: .leading)
.frame(maxWidth: 500, alignment: .leading)
.padding(10)
.lineLimit(lineLimit)
.multilineTextAlignment(.leading)
.minimumScaleFactor(0.5)
.font(.system(size: 14, design: .monospaced))
.background(shape.stroke(Color(white: 0.1).opacity(0.35), lineWidth: 1))
.background(Color(white: 0.94).opacity(0.6).clipShape(shape))
#if !os(tvOS)
.do {
if #available(iOS 15, *) {
$0.textSelection(.enabled)
} else {
$0
}
}
#endif
}
}
6 changes: 4 additions & 2 deletions Demo/Demo/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ struct RootView: View {

var body: some View {
Group {
if #available(iOS 16, *) {
if #available(iOS 16, tvOS 16, *) {
NavigationStack {
PageOne()
}
Expand All @@ -21,6 +21,8 @@ struct RootView: View {
appState.transition().animation(appState.animation()),
interactivity: appState.interactivity()
)
.sheet(isPresented: $appState.isPresentingSettings, content: SettingsView.init)
.sheet(isPresented: $appState.isPresentingSettings) {
SettingsView().environmentObject(appState)
}
}
}
2 changes: 2 additions & 0 deletions Demo/Demo/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ struct SettingsView: View {
picker("Interactivity", $appState.interactivity)
}
}
#if !os(tvOS)
.navigationBarTitle("Settings", displayMode: .inline)
#endif
.navigationBarItems(
leading: Button("Shuffle", action: shuffle),
trailing: Button(action: dismiss) { Text("Done").bold() }
Expand Down
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ let package = Package(
name: "swiftui-navigation-transitions",
platforms: [
.iOS(.v13),
.macCatalyst(.v13),
.tvOS(.v13),
]
)

Expand Down
24 changes: 16 additions & 8 deletions Sources/NavigationTransitions/NavigationTransition+UIKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extension UISplitViewController {

extension UISplitViewController {
var compactViewController: UIViewController? {
if #available(iOS 14, *) {
if #available(iOS 14, tvOS 14, *) {
return viewController(for: .compact)
} else {
if isCollapsed {
Expand All @@ -65,7 +65,7 @@ extension UISplitViewController {
}

var primaryViewController: UIViewController? {
if #available(iOS 14, *) {
if #available(iOS 14, tvOS 14, *) {
return viewController(for: .primary)
} else {
if !isCollapsed {
Expand All @@ -77,7 +77,7 @@ extension UISplitViewController {
}

var supplementaryViewController: UIViewController? {
if #available(iOS 14, *) {
if #available(iOS 14, tvOS 14, *) {
return viewController(for: .supplementary)
} else {
if !isCollapsed {
Expand All @@ -93,7 +93,7 @@ extension UISplitViewController {
}

var secondaryViewController: UIViewController? {
if #available(iOS 14, *) {
if #available(iOS 14, tvOS 14, *) {
return viewController(for: .secondary)
} else {
if !isCollapsed {
Expand Down Expand Up @@ -142,6 +142,13 @@ extension UINavigationController {
defaultDelegate = delegate
}

if transition.type == Default.self {
delegate = defaultDelegate
} else {
customDelegate = NavigationTransitionDelegate(transition: transition, baseDelegate: defaultDelegate)
}

#if !os(tvOS)
if defaultPanRecognizer == nil {
defaultPanRecognizer = UIPanGestureRecognizer()
defaultPanRecognizer.targets = defaultEdgePanRecognizer?.targets // https://stackoverflow.com/a/60526328/1922543
Expand All @@ -165,8 +172,6 @@ extension UINavigationController {
}

if transition.type == Default.self {
delegate = defaultDelegate

switch interactivity {
case .disabled:
exclusivelyEnableGestureRecognizer(.none)
Expand All @@ -176,8 +181,6 @@ extension UINavigationController {
exclusivelyEnableGestureRecognizer(defaultPanRecognizer)
}
} else {
customDelegate = NavigationTransitionDelegate(transition: transition, baseDelegate: defaultDelegate)

switch interactivity {
case .disabled:
exclusivelyEnableGestureRecognizer(.none)
Expand All @@ -187,8 +190,10 @@ extension UINavigationController {
exclusivelyEnableGestureRecognizer(panRecognizer)
}
}
#endif
}

@available(tvOS, unavailable)
private func exclusivelyEnableGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer?) {
for recognizer in [defaultEdgePanRecognizer!, defaultPanRecognizer!, edgePanRecognizer!, panRecognizer!] {
if let gestureRecognizer = gestureRecognizer, recognizer === gestureRecognizer {
Expand All @@ -200,6 +205,7 @@ extension UINavigationController {
}
}

@available(tvOS, unavailable)
extension UINavigationController {
var defaultEdgePanRecognizer: UIScreenEdgePanGestureRecognizer! {
interactivePopGestureRecognizer as? UIScreenEdgePanGestureRecognizer
Expand All @@ -225,6 +231,7 @@ extension UINavigationController {
}
}

@available(tvOS, unavailable)
extension UIGestureRecognizer {
private static var strongDelegateKey = "strongDelegateKey"

Expand Down Expand Up @@ -252,6 +259,7 @@ extension UIGestureRecognizer {
}
}

@available(tvOS, unavailable)
final class NavigationGestureRecognizerDelegate: NSObject, UIGestureRecognizerDelegate {
private unowned let navigationController: UINavigationController

Expand Down