Skip to content

Commit d099946

Browse files
committed
Fix iOS layout editor orientation mismatch state
1 parent 5a60b99 commit d099946

1 file changed

Lines changed: 60 additions & 42 deletions

File tree

app/src/main/swift/Views/Settings/PadLayoutEditView.swift

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,36 @@ struct PadLayoutEditView: View {
2424
GeometryReader { geo in
2525
let isActuallyLandscape = geo.size.width > geo.size.height
2626
let safeAreaTop = geo.safeAreaInsets.top
27+
let safeAreaBottom = geo.safeAreaInsets.bottom
28+
let isMismatch = isActuallyLandscape != editLandscape
2729
ZStack {
2830
// Canvas
2931
if isActuallyLandscape {
30-
landscapeEditorCanvas()
32+
landscapeEditorCanvas(isEditable: !isMismatch)
3133
} else {
32-
portraitEditorCanvas(width: geo.size.width, height: geo.size.height)
34+
portraitEditorCanvas(width: geo.size.width, height: geo.size.height, isEditable: !isMismatch)
35+
}
36+
37+
// Orientation mismatch overlay
38+
if isMismatch {
39+
orientationMismatchView(isLandscape: isActuallyLandscape)
40+
.zIndex(1)
41+
.allowsHitTesting(false)
3342
}
3443

3544
// Chrome overlay
36-
editorChrome(isLandscape: isActuallyLandscape, safeAreaTop: safeAreaTop)
37-
.zIndex(1)
45+
VStack(spacing: 0) {
46+
if isActuallyLandscape {
47+
editorToolbar(isLandscape: true)
48+
Spacer()
49+
} else {
50+
Spacer()
51+
editorToolbar(isLandscape: false)
52+
}
53+
}
54+
.padding(.top, isActuallyLandscape ? max(safeAreaTop, 4) : 0)
55+
.padding(.bottom, isActuallyLandscape ? 0 : max(safeAreaBottom, 8))
56+
.zIndex(2)
3857
}
3958
}
4059
.navigationBarHidden(true)
@@ -54,25 +73,26 @@ struct PadLayoutEditView: View {
5473
}
5574

5675
// MARK: - Landscape editor canvas (always shown when device is landscape)
57-
private func landscapeEditorCanvas() -> some View {
76+
private func landscapeEditorCanvas(isEditable: Bool) -> some View {
5877
GeometryReader { geo in
5978
let width = geo.size.width
6079
let height = geo.size.height
6180
ZStack {
6281
Color.clear
6382
.allowsHitTesting(false)
6483

65-
customSkinPreview(isLandscape: true, width: width, height: height)
66-
67-
editorContent(areaW: width, areaH: height)
84+
if isEditable {
85+
customSkinPreview(isLandscape: true, width: width, height: height)
86+
editorContent(areaW: width, areaH: height)
87+
}
6888
}
6989
.contentShape(Rectangle())
7090
}
7191
.ignoresSafeArea()
7292
}
7393

7494
// MARK: - Portrait editor canvas (always shown when device is portrait)
75-
private func portraitEditorCanvas(width: CGFloat, height: CGFloat) -> some View {
95+
private func portraitEditorCanvas(width: CGFloat, height: CGFloat, isEditable: Bool) -> some View {
7696
let gameHeight = min(width * 3 / 4, height * 0.55)
7797
let padHeight = height - gameHeight
7898
return VStack(spacing: 0) {
@@ -84,29 +104,17 @@ struct PadLayoutEditView: View {
84104
// Bottom: controller deck editing area (dark enough for controls)
85105
ZStack {
86106
Color.black.opacity(0.85)
87-
customSkinPreview(isLandscape: false, width: width, height: padHeight)
88-
editorPortraitContent(areaW: width, areaH: padHeight)
107+
if isEditable {
108+
customSkinPreview(isLandscape: false, width: width, height: padHeight)
109+
editorPortraitContent(areaW: width, areaH: padHeight)
110+
}
89111
}
90112
.frame(height: padHeight)
91113
.clipped()
92114
}
93115
}
94116

95-
// MARK: - Editor chrome overlay
96-
private func editorChrome(isLandscape: Bool, safeAreaTop: CGFloat) -> some View {
97-
VStack(spacing: 0) {
98-
editorToolbar(isLandscape: isLandscape)
99-
100-
if isLandscape != editLandscape {
101-
rotationWarningBanner()
102-
.padding(.top, 8)
103-
}
104-
105-
Spacer()
106-
}
107-
.padding(.top, max(safeAreaTop, 4))
108-
}
109-
117+
// MARK: - Editor toolbar
110118
private func editorToolbar(isLandscape: Bool) -> some View {
111119
HStack(spacing: isLandscape ? 8 : 12) {
112120
// Cancel
@@ -164,27 +172,37 @@ struct PadLayoutEditView: View {
164172
.foregroundStyle(.green)
165173
}
166174
}
167-
.padding(.horizontal)
168-
.padding(.top, 4)
169-
.padding(.bottom, 8)
170-
.background(.black.opacity(0.72), in: RoundedRectangle(cornerRadius: 12, style: .continuous))
175+
.padding(.horizontal, 12)
176+
.padding(.vertical, 6)
177+
.background(.black.opacity(0.55), in: RoundedRectangle(cornerRadius: 10, style: .continuous))
171178
}
172179

173-
private func rotationWarningBanner() -> some View {
174-
HStack(spacing: 6) {
175-
Image(systemName: "exclamationmark.triangle.fill")
176-
Text(editLandscape
177-
? "Editing landscape layout in portrait. Rotate device to landscape for full canvas."
178-
: "Editing portrait layout in landscape. Rotate device to portrait for full canvas.")
179-
.font(.caption.weight(.semibold))
180+
private func orientationMismatchView(isLandscape: Bool) -> some View {
181+
let message = editLandscape
182+
? "Rotate device to landscape to edit landscape layout"
183+
: "Rotate device to portrait to edit portrait layout"
184+
let explanation = editLandscape
185+
? "Accurate editing requires rotating the device or switching to portrait layout."
186+
: "Accurate editing requires rotating the device or switching to landscape layout."
187+
return VStack(spacing: 12) {
188+
Image(systemName: "rotate.right")
189+
.font(.system(size: 48, weight: .light))
190+
.foregroundStyle(.white.opacity(0.6))
191+
Text(message)
192+
.font(.headline.weight(.semibold))
193+
.foregroundStyle(.white)
194+
.multilineTextAlignment(.center)
195+
.lineLimit(3)
196+
Text(explanation)
197+
.font(.subheadline)
198+
.foregroundStyle(.white.opacity(0.7))
180199
.multilineTextAlignment(.center)
181200
.lineLimit(3)
182201
}
183-
.foregroundStyle(.yellow)
184-
.padding(.horizontal, 12)
185-
.padding(.vertical, 8)
186-
.background(.black.opacity(0.6), in: RoundedRectangle(cornerRadius: 8))
187-
.padding(.horizontal, 20)
202+
.padding(.horizontal, 32)
203+
.padding(.vertical, 24)
204+
.background(.black.opacity(0.6), in: RoundedRectangle(cornerRadius: 16))
205+
.frame(maxWidth: .infinity, maxHeight: .infinity)
188206
.allowsHitTesting(false)
189207
}
190208

0 commit comments

Comments
 (0)