feat: speed controls in collapsed tab bar via safeAreaBar
Uses .safeAreaBar(edge: .bottom) on the Reader content — the iOS 26 API that places content in the collapsed tab bar area, same position as the Now Playing mini bar. Speed controls [ - ] 1.50x [ + ] appear in the glass bar when auto-scrolling. Removed the floating speed pill overlay from ContentView. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,53 +73,18 @@ struct MainTabView: View {
|
|||||||
.tint(Color.accentWarm)
|
.tint(Color.accentWarm)
|
||||||
.tabBarMinimizeBehavior(.onScrollDown)
|
.tabBarMinimizeBehavior(.onScrollDown)
|
||||||
|
|
||||||
// Bottom floating controls
|
|
||||||
VStack(spacing: 10) {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
// Speed pill (only when auto-scrolling on Reader)
|
|
||||||
if isAutoScrolling && selectedTab == 2 {
|
|
||||||
HStack(spacing: 12) {
|
|
||||||
Button {
|
|
||||||
scrollSpeed = max(0.25, scrollSpeed - 0.25)
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "minus")
|
|
||||||
.font(.caption.weight(.bold))
|
|
||||||
.foregroundStyle(Color.accentWarm)
|
|
||||||
.frame(width: 32, height: 32)
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(String(format: "%.2fx", scrollSpeed))
|
|
||||||
.font(.system(size: 13, weight: .bold, design: .monospaced))
|
|
||||||
.foregroundStyle(Color.textPrimary)
|
|
||||||
|
|
||||||
Button {
|
|
||||||
scrollSpeed = min(3.0, scrollSpeed + 0.25)
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "plus")
|
|
||||||
.font(.caption.weight(.bold))
|
|
||||||
.foregroundStyle(Color.accentWarm)
|
|
||||||
.frame(width: 32, height: 32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 16)
|
|
||||||
.padding(.vertical, 10)
|
|
||||||
.background(.regularMaterial, in: Capsule())
|
|
||||||
.shadow(color: .black.opacity(0.15), radius: 12, y: 4)
|
|
||||||
.transition(.move(edge: .bottom).combined(with: .opacity))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feedback button (not on Reader)
|
// Feedback button (not on Reader)
|
||||||
if selectedTab != 2 {
|
if selectedTab != 2 {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
HStack {
|
HStack {
|
||||||
FeedbackButton()
|
FeedbackButton()
|
||||||
.padding(.leading, 20)
|
.padding(.leading, 20)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.bottom, 70)
|
.padding(.bottom, 70)
|
||||||
.animation(.spring(duration: 0.3), value: isAutoScrolling)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.confettiCannon(
|
.confettiCannon(
|
||||||
trigger: $confettiTrigger,
|
trigger: $confettiTrigger,
|
||||||
|
|||||||
@@ -140,6 +140,32 @@ struct ReaderTabView: View {
|
|||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.background(Color.canvas)
|
.background(Color.canvas)
|
||||||
.navigationBarHidden(true)
|
.navigationBarHidden(true)
|
||||||
|
.safeAreaBar(edge: .bottom) {
|
||||||
|
if isAutoScrolling {
|
||||||
|
HStack(spacing: 16) {
|
||||||
|
Button {
|
||||||
|
scrollSpeed = max(0.25, scrollSpeed - 0.25)
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "minus")
|
||||||
|
.font(.caption.weight(.bold))
|
||||||
|
.foregroundStyle(Color.accentWarm)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(String(format: "%.2fx", scrollSpeed))
|
||||||
|
.font(.system(size: 13, weight: .bold, design: .monospaced))
|
||||||
|
.foregroundStyle(Color.textPrimary)
|
||||||
|
|
||||||
|
Button {
|
||||||
|
scrollSpeed = min(3.0, scrollSpeed + 0.25)
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "plus")
|
||||||
|
.font(.caption.weight(.bold))
|
||||||
|
.foregroundStyle(Color.accentWarm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
}
|
||||||
|
}
|
||||||
.sheet(isPresented: $showFeedSheet) {
|
.sheet(isPresented: $showFeedSheet) {
|
||||||
AddFeedSheet(vm: vm)
|
AddFeedSheet(vm: vm)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user