Skip to content

Commit 92f842d

Browse files
committed
Fix sheets on tvOS
1 parent a4ec00b commit 92f842d

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

Examples/Sources/WindowingExample/WindowingApp.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import SwiftCrossUI
66
import SwiftBundlerRuntime
77
#endif
88

9+
@available(tvOS, unavailable)
910
struct FileDialogDemo: View {
1011
@State var selectedFile: URL? = nil
1112
@State var saveDestination: URL? = nil
@@ -179,9 +180,11 @@ struct WindowingApp: App {
179180

180181
Divider()
181182

182-
FileDialogDemo()
183+
#if !os(tvOS)
184+
FileDialogDemo()
183185

184-
Divider()
186+
Divider()
187+
#endif
185188

186189
AlertDemo()
187190

Sources/AppKitBackend/AppKitBackend.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,8 @@ public final class AppKitBackend: AppBackend {
17321732

17331733
public func updateSheet(
17341734
_ sheet: NSCustomSheet,
1735+
window: NSCustomWindow,
1736+
environment: EnvironmentValues,
17351737
size: SIMD2<Int>,
17361738
onDismiss: @escaping () -> Void,
17371739
cornerRadius: Double?,

Sources/GtkBackend/GtkBackend.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,8 @@ public final class GtkBackend: AppBackend {
16131613

16141614
public func updateSheet(
16151615
_ sheet: Sheet,
1616+
window: Window,
1617+
environment: EnvironmentValues,
16161618
size: SIMD2<Int>,
16171619
onDismiss: @escaping () -> Void,
16181620
cornerRadius: Double?,

Sources/SwiftCrossUI/Backend/AppBackend.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,13 @@ public protocol AppBackend: Sendable {
612612
/// Updates the content, appearance and behaviour of a sheet.
613613
/// - Parameters:
614614
/// - sheet: The sheet to update.
615+
/// - window: The root window that the sheet will be presented in. Used on
616+
/// platforms such as tvOS to compute layout constraints. The sheet
617+
/// shouldn't get attached to the window by updateSheet. That is handled
618+
/// by presentSheet which is guaranteed to be called exactly once (unlike
619+
/// updateSheet which gets called whenever preferences or sizing change).
620+
/// - environment: The environment that the sheet will be presented in. This
621+
/// differs from the environment passed to the sheet's content.
615622
/// - onDismiss: An action to perform when the sheet gets dismissed by
616623
/// the user. Not triggered by programmatic dismissals. But is triggered
617624
/// by the implicit dismissals of nested sheets when their parent sheet
@@ -633,6 +640,8 @@ public protocol AppBackend: Sendable {
633640
/// key and/or removes system-provided close/cancel buttons from the sheet.
634641
func updateSheet(
635642
_ sheet: Sheet,
643+
window: Window,
644+
environment: EnvironmentValues,
636645
size: SIMD2<Int>,
637646
onDismiss: @escaping () -> Void,
638647
cornerRadius: Double?,
@@ -1246,6 +1255,8 @@ extension AppBackend {
12461255

12471256
public func updateSheet(
12481257
_ sheet: Sheet,
1258+
window: Window,
1259+
environment: EnvironmentValues,
12491260
size: SIMD2<Int>,
12501261
onDismiss: @escaping () -> Void,
12511262
cornerRadius: Double?,

Sources/SwiftCrossUI/Views/Modifiers/SheetModifier.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,15 @@ struct SheetModifier<Content: View, SheetContent: View>: TypeSafeView {
108108
dryRun: false
109109
)
110110

111+
let window = environment.window! as! Backend.Window
111112
let preferences = result.preferences
112113
backend.updateSheet(
113114
sheet,
115+
window: window,
116+
// We intentionally use the outer environment rather than
117+
// sheetEnvironment here, because this is meant to be the sheet's
118+
// environment, not that of its content.
119+
environment: environment,
114120
size: result.size.size,
115121
onDismiss: { handleDismiss(children: children) },
116122
cornerRadius: preferences.presentationCornerRadius,
@@ -121,7 +127,6 @@ struct SheetModifier<Content: View, SheetContent: View>: TypeSafeView {
121127
interactiveDismissDisabled: preferences.interactiveDismissDisabled ?? false
122128
)
123129

124-
let window = environment.window! as! Backend.Window
125130
let parentSheet = environment.sheet.map { $0 as! Backend.Sheet }
126131
backend.presentSheet(
127132
sheet,

Sources/UIKitBackend/UIKitBackend+Sheet.swift

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ extension UIKitBackend {
3636

3737
public func updateSheet(
3838
_ sheet: CustomSheet,
39+
window: Window,
40+
environment: EnvironmentValues,
3941
size: SIMD2<Int>,
4042
onDismiss: @escaping () -> Void,
4143
cornerRadius: Double?,
@@ -44,17 +46,45 @@ extension UIKitBackend {
4446
backgroundColor: Color?,
4547
interactiveDismissDisabled: Bool
4648
) {
47-
// Center the sheet's content
48-
let leadingPadding = (sheet.preferredContentSize.width - CGFloat(size.x)) / 2
49-
sheet.leadingConstraint!.constant = leadingPadding
49+
// Center the sheet's content horizontally
50+
#if os(tvOS)
51+
let leadingPadding = (window.frame.size.width - CGFloat(size.x)) / 2
52+
sheet.leadingConstraint!.constant = -leadingPadding
53+
#else
54+
let leadingPadding = (sheet.preferredContentSize.width - CGFloat(size.x)) / 2
55+
sheet.leadingConstraint!.constant = leadingPadding
56+
#endif
5057

5158
sheet.onDismiss = onDismiss
5259
setPresentationDetents(of: sheet, to: detents)
5360
setPresentationCornerRadius(of: sheet, to: cornerRadius)
5461
setPresentationDragIndicatorVisibility(of: sheet, to: dragIndicatorVisibility, detents: detents)
5562

56-
// TODO: Get the default background color from the environment (via colorScheme?)
57-
sheet.view.backgroundColor = backgroundColor?.uiColor ?? UIColor.systemBackground
63+
let defaultColor: UIColor?
64+
#if targetEnvironment(macCatalyst)
65+
defaultColor = nil
66+
#else
67+
// These values were obtained by measuring the colors on my Mac, so they
68+
// are likely not completely accurate (these are just how they appeared
69+
// in my Mac's color space).
70+
switch environment.colorScheme {
71+
case .light:
72+
defaultColor = UIColor(
73+
red: 1, green: 1, blue: 1, alpha: 1
74+
)
75+
case .dark:
76+
#if os(tvOS)
77+
defaultColor = UIColor(
78+
red: 15 / 255, green: 15 / 255, blue: 15 / 255, alpha: 1
79+
)
80+
#else
81+
defaultColor = UIColor(
82+
red: 28 / 255, green: 28 / 255, blue: 30 / 255, alpha: 1
83+
)
84+
#endif
85+
}
86+
#endif
87+
sheet.view.backgroundColor = backgroundColor?.uiColor ?? defaultColor
5888

5989
// From the UIKit docs for isModalInPresentation:
6090
// When you set it to true, UIKit ignores events outside the view controller’s

0 commit comments

Comments
 (0)