fix(layout): fix rotation crash and improve iPad split view
iPadLayout was rendering TodayView without workoutVM, crashing with a fatal EnvironmentObject error on any device where hSizeClass goes .regular (iPad, iPhone Plus/Max in landscape). Rewrote to use proper NavigationSplitView with List(selection:) driving the detail column. Also caches calendarIcon as a static func + @State instead of recomputing UIGraphicsImageRenderer on every body evaluation.
This commit is contained in:
@@ -11,8 +11,10 @@ struct ContentView: View {
|
||||
@AppStorage("hasOnboarded") private var hasOnboarded = false
|
||||
@State private var showOnboarding = false
|
||||
@State private var selectedTab = 0
|
||||
@State private var iPadSelection: Int? = 0
|
||||
@State private var calIconImage: Image = ContentView.buildCalIcon()
|
||||
|
||||
private var calendarIcon: Image {
|
||||
private static func buildCalIcon() -> Image {
|
||||
let day = Calendar.current.component(.day, from: Date())
|
||||
let size = CGSize(width: 26, height: 26)
|
||||
let renderer = UIGraphicsImageRenderer(size: size)
|
||||
@@ -21,14 +23,12 @@ struct ContentView: View {
|
||||
let lw: CGFloat = 1.5
|
||||
let cr: CGFloat = 4.5
|
||||
|
||||
// Outer rounded rectangle body
|
||||
let body = CGRect(x: lw / 2, y: 3, width: size.width - lw, height: size.height - 3 - lw / 2)
|
||||
let bodyPath = UIBezierPath(roundedRect: body, cornerRadius: cr)
|
||||
color.setStroke()
|
||||
bodyPath.lineWidth = lw
|
||||
bodyPath.stroke()
|
||||
|
||||
// Header divider line
|
||||
let divY = body.minY + 7.5
|
||||
let divPath = UIBezierPath()
|
||||
divPath.move(to: CGPoint(x: body.minX + lw / 2, y: divY))
|
||||
@@ -37,13 +37,11 @@ struct ContentView: View {
|
||||
divPath.lineWidth = 1
|
||||
divPath.stroke()
|
||||
|
||||
// Ring bumps at top
|
||||
color.setFill()
|
||||
for rx in [size.width * 0.3, size.width * 0.7] {
|
||||
UIBezierPath(roundedRect: CGRect(x: rx - 1.5, y: 0.5, width: 3, height: 5.5), cornerRadius: 1.5).fill()
|
||||
}
|
||||
|
||||
// Date number centred in body below header
|
||||
let s = "\(day)"
|
||||
let font = UIFont.systemFont(ofSize: floor(size.height * 0.38), weight: .bold)
|
||||
let attrs: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: color]
|
||||
@@ -133,7 +131,7 @@ struct ContentView: View {
|
||||
|
||||
KisaniTabBar(
|
||||
selection: $selectedTab,
|
||||
calIcon: calendarIcon,
|
||||
calIcon: calIconImage,
|
||||
showMatrix: showMatrixTab,
|
||||
showWorkout: showWorkoutTab
|
||||
)
|
||||
@@ -146,42 +144,27 @@ struct ContentView: View {
|
||||
// MARK: - iPad
|
||||
@ViewBuilder
|
||||
private func iPadLayout() -> some View {
|
||||
NavigationSplitView(columnVisibility: .constant(.all)) {
|
||||
List {
|
||||
iPadSidebarItem("Tasks", icon: "checkmark", tag: 0)
|
||||
iPadSidebarItem("Calendar", icon: "calendar", tag: 1)
|
||||
if showMatrixTab {
|
||||
iPadSidebarItem("Matrix", icon: "square.grid.2x2", tag: 2)
|
||||
}
|
||||
if showWorkoutTab {
|
||||
iPadSidebarItem("Workout", icon: "dumbbell", tag: 3)
|
||||
}
|
||||
iPadSidebarItem("Settings", icon: "gearshape", tag: 4)
|
||||
NavigationSplitView {
|
||||
List(selection: $iPadSelection) {
|
||||
Label("Tasks", systemImage: "checkmark").tag(0)
|
||||
Label("Calendar", systemImage: "calendar").tag(1)
|
||||
if showMatrixTab { Label("Matrix", systemImage: "square.grid.2x2").tag(2) }
|
||||
if showWorkoutTab { Label("Workout", systemImage: "dumbbell").tag(3) }
|
||||
Label("Settings", systemImage: "gearshape").tag(4)
|
||||
}
|
||||
.navigationTitle("Kisani Cal")
|
||||
.listStyle(.sidebar)
|
||||
} detail: {
|
||||
TodayView().environmentObject(taskVM)
|
||||
}
|
||||
.tint(AppColors.accent)
|
||||
}
|
||||
|
||||
private func iPadSidebarItem(_ label: String, icon: String, tag: Int) -> some View {
|
||||
NavigationLink(destination: iPadDetail(tag: tag)) {
|
||||
Label(label, systemImage: icon)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func iPadDetail(tag: Int) -> some View {
|
||||
switch tag {
|
||||
case 0: TodayView().environmentObject(taskVM).environmentObject(workoutVM)
|
||||
switch iPadSelection ?? 0 {
|
||||
case 1: CalendarView().environmentObject(taskVM).environmentObject(workoutVM)
|
||||
case 2: MatrixView().environmentObject(taskVM)
|
||||
case 3: WorkoutView().environmentObject(workoutVM)
|
||||
default: SettingsView().environmentObject(workoutVM)
|
||||
case 4: SettingsView().environmentObject(workoutVM)
|
||||
default: TodayView().environmentObject(taskVM).environmentObject(workoutVM)
|
||||
}
|
||||
}
|
||||
.tint(AppColors.accent)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Custom Tab Bar
|
||||
|
||||
Reference in New Issue
Block a user