Skip to content

Commit a417a5f

Browse files
authored
Layout improvements to align Continue button across devices
1 parent 95c26d5 commit a417a5f

File tree

1 file changed

+69
-41
lines changed

1 file changed

+69
-41
lines changed

Sources/Recap/Public/RecapScreen.swift

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public struct RecapScreen<LeadingView: View, TrailingView: View>: View {
4444
}
4545

4646
public var body: some View {
47-
NavigationStack {
47+
VStack(spacing: 0.0) {
4848
TabView(selection: $selectedIndex) {
4949
self.leadingView
5050
.tag(self.tabIndex(from: .leadingView))
@@ -62,27 +62,31 @@ public struct RecapScreen<LeadingView: View, TrailingView: View>: View {
6262
}
6363
.tabViewStyle(.page(indexDisplayMode: self.releases.count > 1 ? .always : .never))
6464
.background(self.derivedBackgroundStyle)
65-
.navigationBarTitleDisplayMode(.inline)
66-
.toolbar(.hidden, for: .navigationBar)
67-
.toolbar {
68-
ToolbarItem(placement: .bottomBar) {
69-
Button(action: {
70-
dismissAction?() ?? dismiss()
71-
}, label: {
72-
Text("RECAP.SCREEN.DISMISS.BUTTON.TITLE", bundle: .module)
73-
.font(.system(.title3, weight: .bold))
74-
.padding(8.0)
75-
.padding(.vertical, 4.0)
76-
.padding(.horizontal, 16.0)
77-
.foregroundStyle(dismissButtonStyle.foregroundStyle)
78-
})
79-
.frame(maxWidth: .infinity)
80-
.background(self.dismissButtonStyle.backgroundStyle)
81-
.clipShape(.rect(cornerRadius: 16.0))
82-
.padding(.horizontal, 20.0)
83-
.foregroundStyle(.primary)
65+
66+
Button(action: {
67+
dismissAction?() ?? dismiss()
68+
}, label: {
69+
HStack {
70+
Spacer(minLength: 0.0)
71+
72+
Text("RECAP.SCREEN.DISMISS.BUTTON.TITLE", bundle: .module)
73+
.font(.system(.title3, weight: .bold))
74+
.padding(8.0)
75+
.padding(.vertical, 4.0)
76+
.padding(.horizontal, 16.0)
77+
.foregroundStyle(dismissButtonStyle.foregroundStyle)
78+
79+
Spacer(minLength: 0.0)
8480
}
85-
}
81+
.contentShape(.rect(cornerRadius: 16.0))
82+
})
83+
.frame(maxWidth: .infinity)
84+
.background(self.dismissButtonStyle.backgroundStyle)
85+
.clipShape(.rect(cornerRadius: 16.0))
86+
.padding(.horizontal, 40.0)
87+
.foregroundStyle(.primary)
88+
.withBottomPaddingIfNoSafeArea()
89+
.background(self.derivedBackgroundStyle)
8690
.onAppear(perform: {
8791
self.selectedIndex = self.tabIndex(from: self.startIndex)
8892
})
@@ -96,6 +100,34 @@ public struct RecapScreen<LeadingView: View, TrailingView: View>: View {
96100
}
97101
}
98102

103+
// MARK: Convenience Initializers
104+
105+
public extension RecapScreen where LeadingView == EmptyView {
106+
init(releases: [Release], @ViewBuilder trailingView: () -> TrailingView) {
107+
self.releases = releases
108+
self.leadingView = EmptyView()
109+
self.trailingView = trailingView()
110+
}
111+
}
112+
113+
public extension RecapScreen where TrailingView == EmptyView {
114+
init(releases: [Release], @ViewBuilder leadingView: () -> LeadingView) {
115+
self.releases = releases
116+
self.leadingView = leadingView()
117+
self.trailingView = EmptyView()
118+
}
119+
}
120+
121+
public extension RecapScreen where LeadingView == EmptyView, TrailingView == EmptyView {
122+
init(releases: [Release]) {
123+
self.releases = releases
124+
self.leadingView = EmptyView()
125+
self.trailingView = EmptyView()
126+
}
127+
}
128+
129+
// MARK: Private
130+
99131
private extension RecapScreen {
100132
var displayedReleases: [Release] {
101133
self.releases.reversed()
@@ -136,28 +168,24 @@ private extension RecapScreen {
136168
}
137169
}
138170

139-
// MARK: Convenience Initializers
140-
141-
public extension RecapScreen where LeadingView == EmptyView {
142-
init(releases: [Release], @ViewBuilder trailingView: () -> TrailingView) {
143-
self.releases = releases
144-
self.leadingView = EmptyView()
145-
self.trailingView = trailingView()
146-
}
147-
}
171+
// MARK: Safe Area Insets
148172

149-
public extension RecapScreen where TrailingView == EmptyView {
150-
init(releases: [Release], @ViewBuilder leadingView: () -> LeadingView) {
151-
self.releases = releases
152-
self.leadingView = leadingView()
153-
self.trailingView = EmptyView()
173+
private extension View {
174+
var hasSafeAreaForBottomPadding: Bool {
175+
#if os(macOS)
176+
return false
177+
#else
178+
if UIDevice.current.userInterfaceIdiom == .pad {
179+
// On iPad, we don't display fullscreen so the home bar isn't relevant.
180+
return false
181+
} else {
182+
return (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0.0) > 0.0
183+
}
184+
#endif
154185
}
155-
}
156186

157-
public extension RecapScreen where LeadingView == EmptyView, TrailingView == EmptyView {
158-
init(releases: [Release]) {
159-
self.releases = releases
160-
self.leadingView = EmptyView()
161-
self.trailingView = EmptyView()
187+
func withBottomPaddingIfNoSafeArea() -> some View {
188+
guard !hasSafeAreaForBottomPadding else { return self }
189+
return self.padding(.bottom, 24.0)
162190
}
163191
}

0 commit comments

Comments
 (0)