//
// ContentView.swift
// ogre
//
// Created by É. Urcades on 2025.10.12.
//
import SwiftUI
struct ConditionalTabViewBottomAccessory: ViewModifier {
let show: Bool
func body(content: Content) -> some View {
content.tabViewBottomAccessory {
if show {
Text("Processing")
}
}
}
}
struct ContentView: View {
@State private var isSearchPresented = false
@State private var selectedTab = 0
@State private var hasSearchBeenDismissed = false
var body: some View {
TabView(selection: $selectedTab) {
Tab("A", systemImage: "tray.and.arrow.down.fill", value: 0) {
FeedView()
}
Tab("B", systemImage: "tray.and.arrow.down.fill", value: 1) {
PlaceholderView()
}
Tab("C", systemImage: "tray.and.arrow.down.fill", value: 2, role: .search) {
Color.clear
}
}
.modifier(ConditionalTabViewBottomAccessory(show: hasSearchBeenDismissed))
.tabBarMinimizeBehavior(.onScrollDown)
.onChange(of: selectedTab) { oldValue, newValue in
if newValue == 2 {
// Search tab tapped - present sheet and revert to previous tab
isSearchPresented = true
selectedTab = oldValue
}
}
.sheet(
isPresented: $isSearchPresented,
onDismiss: {
withAnimation(.easeInOut(duration: 0.3)) {
hasSearchBeenDismissed = true
}
Task {
try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
await MainActor.run {
withAnimation(.easeInOut(duration: 0.3)) {
hasSearchBeenDismissed = false
}
}
}
}
) {
NavigationStack {
SearchView()
}
.presentationDetents([.large])
}
}
}
struct FeedView: View {
var body: some View {
NavigationStack {
GeometryReader { proxy in
ScrollView(.vertical) {
VStack(spacing: 8) {
// World View Modular Scene Cards
HorizontalCardScroll(height: 300, horizontalPadding: 24) {
HorizontalCard(width: proxy.size.width - 48, height: 300) {
MapCard()
}
HorizontalCard(width: proxy.size.width - 48, height: 300) {
DailyCard()
}
HorizontalCard(width: proxy.size.width - 48, height: 300) {
WeeklyCard()
}
HorizontalCard(width: proxy.size.width - 48, height: 300) {
SeasonalCard()
}
}
.padding(.bottom, 8)
// Four-column grid section with varying widths
let totalWidth = proxy.size.width - 16 // Account for horizontal padding
let spacing: CGFloat = 8
let totalSpacing = spacing * 3 // 3 gaps for 4 columns
let columnWidth = (totalWidth - totalSpacing) / 4
//
// MARK: Filter chips
//
ScrollView(.horizontal) {
GlassEffectContainer(spacing: 8) {
HStack(spacing: 8) {
FilterChip(title: "FYP")
FilterChip(title: "Local")
FilterChip(title: "Friends")
FilterChip(title: "Global")
FilterChip(title: "Statuses")
}
.padding(.horizontal, 8)
}
}
.scrollClipDisabled()
.scrollIndicators(.hidden)
VStack(spacing: 8) {
// Row 1: Two 2x2 items (default size)
HStack(spacing: spacing) {
GridCard(columnSpan: 2, columnWidth: columnWidth, spacing: spacing) {
Text("1")
}
GridCard(columnSpan: 2, columnWidth: columnWidth, spacing: spacing) {
Text("2")
}
}
// Status bar: 4 columns x 2 rows
GridStatus(columnWidth: columnWidth, spacing: spacing) {
HStack(spacing: spacing) {
Circle()
.frame(width: 24, height: 24)
.foregroundStyle(Color.black)
VStack(spacing: spacing) {
Text("Username")
}
}
}
// Row 2: Two more 2x2 items
HStack(spacing: spacing) {
GridCard(columnSpan: 2, columnWidth: columnWidth, spacing: spacing) {
Text("3")
}
GridCard(columnSpan: 2, columnWidth: columnWidth, spacing: spacing) {
Text("4")
}
}
// Row 3: Four 1x1 items
HStack(spacing: spacing) {
ForEach(5..<9) { number in
GridCard(columnSpan: 1, columnWidth: columnWidth, spacing: spacing) {
Text(String(number))
}
}
}
// Row 4: Full width 4x4 item
GridCard(columnSpan: 4, columnWidth: columnWidth, spacing: spacing) {
Text("9")
}
// Row 5-6: 3x3 item + three 1x1 items stacked
HStack(alignment: .top, spacing: spacing) {
GridCard(columnSpan: 3, columnWidth: columnWidth, spacing: spacing) {
Text("10")
}
VStack(spacing: spacing) {
ForEach(11..<14) { number in
GridCard(columnSpan: 1, columnWidth: columnWidth, spacing: spacing) {
Text(String(number))
}
}
}
}
// Row 7: Two 2x2 items
HStack(spacing: spacing) {
GridCard(columnSpan: 2, columnWidth: columnWidth, spacing: spacing) {
Text("14")
}
GridCard(columnSpan: 2, columnWidth: columnWidth, spacing: spacing) {
Text("15")
}
}
// Row 8: Four 1x1 items
HStack(spacing: spacing) {
ForEach(16..<20) { number in
GridCard(columnSpan: 1, columnWidth: columnWidth, spacing: spacing) {
Text(String(number))
}
}
}
// Row 9-10: Three 1x1 items + one 3x3 item
HStack(alignment: .top, spacing: spacing) {
VStack(spacing: spacing) {
ForEach(20..<23) { number in
GridCard(columnSpan: 1, columnWidth: columnWidth, spacing: spacing) {
Text(String(number))
}
}
}
GridCard(columnSpan: 3, columnWidth: columnWidth, spacing: spacing) {
Text("23")
}
}
}
.padding(.horizontal, 8)
}
}
.coordinateSpace(name: "scrollView")
.navigationTitle("Yuma")
.navigationBarTitleDisplayMode(.inline)
.scrollIndicators(.hidden)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
// Action for leading button
}) {
Image(systemName: "person")
}
}
ToolbarItem(placement: .principal) {
Text("Yuma")
.font(.title3)
.fontWeight(.medium)
.fontDesign(.rounded)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
// Action for trailing button
}) {
Image(systemName: "plus.message")
}
}
}
}
}
}
}
struct SearchView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
Spacer()
Rectangle()
.frame(width: 111, height: 111)
.foregroundStyle(Color.blue)
Spacer()
Circle()
.frame(width: 111, height: 111)
.foregroundStyle(Color.red)
.padding(.bottom, 111)
}
.navigationTitle("Search")
.navigationBarTitleDisplayMode(.inline)
.scrollIndicators(.hidden)
.toolbar {
ToolbarItem(placement: .principal) {
Text("Search")
.fontDesign(.rounded)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
dismiss()
}) {
Image(systemName: "xmark")
}
}
}
}
}
struct PlaceholderView: View {
var body: some View {
NavigationStack {
VStack {
Spacer()
Text("Chat View")
.font(.title)
.fontWeight(.medium)
.fontDesign(.rounded)
Text("Coming soon")
.foregroundStyle(.secondary)
Spacer()
}
.navigationTitle("Yuma")
.navigationBarTitleDisplayMode(.inline)
.scrollIndicators(.hidden)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
// Action for leading button
}) {
Image(systemName: "person")
}
}
ToolbarItem(placement: .principal) {
Text("Yuma")
.font(.title3)
.fontWeight(.medium)
.fontDesign(.rounded)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
// Action for trailing button
}) {
Image(systemName: "plus.message")
}
}
}
}
}
}
#Preview {
ContentView()
}