diff --git a/ios/Platform/Platform/Features/Fitness/Views/FitnessTabView.swift b/ios/Platform/Platform/Features/Fitness/Views/FitnessTabView.swift index db86c87..c87ee77 100644 --- a/ios/Platform/Platform/Features/Fitness/Views/FitnessTabView.swift +++ b/ios/Platform/Platform/Features/Fitness/Views/FitnessTabView.swift @@ -31,16 +31,18 @@ struct FitnessTabView: View { .padding(.horizontal) .padding(.top, 8) - // Content — no page swipe (conflicts with swipe-to-delete) - Group { - switch selectedSubTab { - case 0: TodayView() - case 1: TemplatesView() - case 2: GoalsView() - case 3: FoodLibraryView() - default: TodayView() - } + // Content + TabView(selection: $selectedSubTab) { + TodayView() + .tag(0) + TemplatesView() + .tag(1) + GoalsView() + .tag(2) + FoodLibraryView() + .tag(3) } + .tabViewStyle(.page(indexDisplayMode: .never)) } .background(Color.canvas) .navigationBarHidden(true) diff --git a/ios/Platform/Platform/Features/Fitness/Views/MealSectionView.swift b/ios/Platform/Platform/Features/Fitness/Views/MealSectionView.swift index a66a470..a9e96ab 100644 --- a/ios/Platform/Platform/Features/Fitness/Views/MealSectionView.swift +++ b/ios/Platform/Platform/Features/Fitness/Views/MealSectionView.swift @@ -68,12 +68,12 @@ struct MealSectionView: View { if isExpanded { ForEach(entries) { entry in - SwipeToDeleteRow(onDelete: { onDelete(entry) }) { - NavigationLink(destination: EntryDetailView(entry: entry, onDelete: { - onDelete(entry) - })) { - entryRow(entry) - } + SwipeToDeleteRow( + onDelete: { onDelete(entry) }, + onTap: { /* handled by NavigationLink */ }, + destination: { EntryDetailView(entry: entry, onDelete: { onDelete(entry) }) } + ) { + entryRow(entry) } } } @@ -118,40 +118,62 @@ struct MealSectionView: View { // MARK: - Swipe to Delete Row -struct SwipeToDeleteRow: View { +struct SwipeToDeleteRow: View { let onDelete: () -> Void + let onTap: () -> Void + let destination: () -> Destination @ViewBuilder let content: () -> Content + @State private var offset: CGFloat = 0 - @State private var showDelete = false + @State private var isSwiping = false + @State private var showDetail = false var body: some View { ZStack(alignment: .trailing) { - // Delete background + // Delete button background HStack { Spacer() Button { withAnimation(.easeInOut(duration: 0.2)) { onDelete() offset = 0 + isSwiping = false } } label: { Image(systemName: "trash.fill") .foregroundStyle(.white) - .frame(width: 70, height: .infinity) + .frame(maxHeight: .infinity) + .frame(width: 70) } - .frame(width: 70) .background(Color.red) } - // Content + // Content row content() .offset(x: offset) - .gesture( - DragGesture() + .background( + NavigationLink(destination: destination(), isActive: $showDetail) { + EmptyView() + } + .opacity(0) + ) + .onTapGesture { + if !isSwiping { + showDetail = true + } else { + // Close swipe + withAnimation(.easeOut(duration: 0.2)) { + offset = 0 + isSwiping = false + } + } + } + .highPriorityGesture( + DragGesture(minimumDistance: 15) .onChanged { value in if value.translation.width < 0 { offset = max(value.translation.width, -80) - } else if showDelete { + } else if isSwiping { offset = min(value.translation.width - 70, 0) } } @@ -159,10 +181,10 @@ struct SwipeToDeleteRow: View { withAnimation(.easeOut(duration: 0.2)) { if value.translation.width < -40 { offset = -70 - showDelete = true + isSwiping = true } else { offset = 0 - showDelete = false + isSwiping = false } } }