fix: context-dependent FAB — play/pause on Reader, + on other tabs
Removed Tab(role: .search) — it was always visible on all tabs. Now the floating action button changes based on selected tab: - Home/Fitness: FAB (+) → opens food assistant (same as before) - Reader: Play/Pause circle → toggles auto-scroll - Idle: play.fill icon, warm accent background - Playing: pause.fill icon, red background - Tapping toggles between play/pause Speed controls appear as glass capsule above the FAB when playing. Auto-scroll stops when switching away from Reader tab. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,35 +50,40 @@ struct MainTabView: View {
|
||||
Tab("Reader", systemImage: "newspaper.fill", value: 2) {
|
||||
ReaderTabView(vm: readerVM, isAutoScrolling: $isAutoScrolling, scrollSpeed: $scrollSpeed)
|
||||
}
|
||||
|
||||
// Auto-scroll button — uses .search role for the separated
|
||||
// circular placement on the trailing side of the tab bar
|
||||
Tab("Auto", systemImage: "play.fill", value: 3, role: .search) {
|
||||
// When tapped, toggle auto-scroll instead of showing search
|
||||
Color.clear
|
||||
.onAppear {
|
||||
// Switch to Reader tab and start auto-scroll
|
||||
selectedTab = 2
|
||||
withAnimation(.spring(duration: 0.3)) {
|
||||
isAutoScrolling = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tint(Color.accentWarm)
|
||||
.modifier(TabBarMinimizeModifier())
|
||||
.tabBarMinimizeBehavior(.onScrollDown)
|
||||
|
||||
// Floating buttons (hidden on Reader tab)
|
||||
if selectedTab != 2 {
|
||||
VStack {
|
||||
Spacer()
|
||||
HStack(alignment: .bottom) {
|
||||
// Floating action button — context-dependent
|
||||
VStack {
|
||||
Spacer()
|
||||
HStack(alignment: .bottom) {
|
||||
if selectedTab != 2 {
|
||||
FeedbackButton()
|
||||
.padding(.leading, 20)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
Spacer()
|
||||
|
||||
if selectedTab == 2 && showReader {
|
||||
// Reader: play/pause auto-scroll
|
||||
Button {
|
||||
withAnimation(.spring(duration: 0.3)) {
|
||||
isAutoScrolling.toggle()
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: isAutoScrolling ? "pause.fill" : "play.fill")
|
||||
.font(.system(size: 18))
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: 56, height: 56)
|
||||
.background(isAutoScrolling ? Color.red.opacity(0.85) : Color.accentWarm)
|
||||
.clipShape(Circle())
|
||||
.shadow(color: .black.opacity(0.2), radius: 8, y: 4)
|
||||
}
|
||||
.padding(.trailing, 20)
|
||||
} else {
|
||||
// Home/Fitness: FAB (+) for food
|
||||
Button { showAssistant = true } label: {
|
||||
Image(systemName: "plus")
|
||||
.font(.title2.weight(.semibold))
|
||||
@@ -90,8 +95,8 @@ struct MainTabView: View {
|
||||
}
|
||||
.padding(.trailing, 20)
|
||||
}
|
||||
.padding(.bottom, 70)
|
||||
}
|
||||
.padding(.bottom, 70)
|
||||
}
|
||||
|
||||
// Auto-scroll speed controls (overlay when playing)
|
||||
@@ -120,28 +125,12 @@ struct MainTabView: View {
|
||||
.foregroundStyle(Color.accentWarm)
|
||||
.frame(width: 32, height: 32)
|
||||
}
|
||||
|
||||
Divider()
|
||||
.frame(height: 20)
|
||||
|
||||
Button {
|
||||
withAnimation(.spring(duration: 0.3)) {
|
||||
isAutoScrolling = false
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "stop.fill")
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: 34, height: 34)
|
||||
.background(Color.red.opacity(0.8))
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 8)
|
||||
.background(.ultraThinMaterial, in: Capsule())
|
||||
.shadow(color: .black.opacity(0.1), radius: 8, y: 2)
|
||||
.padding(.bottom, 70)
|
||||
.padding(.bottom, 140)
|
||||
.transition(.move(edge: .bottom).combined(with: .opacity))
|
||||
}
|
||||
.animation(.spring(duration: 0.3), value: isAutoScrolling)
|
||||
@@ -167,6 +156,10 @@ struct MainTabView: View {
|
||||
renderer.attachToWindow()
|
||||
await readerVM.loadInitial()
|
||||
}
|
||||
.onChange(of: selectedTab) { _, newTab in
|
||||
// Stop auto-scroll when leaving Reader
|
||||
if newTab != 2 { isAutoScrolling = false }
|
||||
}
|
||||
}
|
||||
|
||||
private func foodAdded() {
|
||||
@@ -233,11 +226,3 @@ struct AssistantSheetView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Tab Bar Minimize (iOS 26+)
|
||||
|
||||
struct TabBarMinimizeModifier: ViewModifier {
|
||||
func body(content: Content) -> some View {
|
||||
content.tabBarMinimizeBehavior(.onScrollDown)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user