fixed iOS widget layout

This commit is contained in:
Marianum
2026-05-13 16:09:43 +02:00
parent d8a5ccfe80
commit 58fb843f3d
4 changed files with 80 additions and 30 deletions
@@ -20,7 +20,7 @@ struct TimetableWeekView: View {
@ViewBuilder
private func content(data: WidgetTimetableData) -> some View {
VStack(alignment: .leading, spacing: 4) {
VStack(alignment: .leading, spacing: 0) {
header(data: data)
dayHeaderRow(data: data)
GeometryReader { geo in
@@ -30,7 +30,10 @@ struct TimetableWeekView: View {
min(MAX_HOUR_HEIGHT, geo.size.height / max(totalMin, 60) * 60)
)
let dayColumnWidth = (geo.size.width - 28 - 4) / 5
let subjectOnly = dayColumnWidth < 70
// 45pt is the minimum where a 7pt-font room (e.g. "F2.04")
// plus the subject fits without `minimumScaleFactor`
// shrinking the subject into illegibility.
let subjectOnly = dayColumnWidth < 45
HStack(alignment: .top, spacing: 0) {
timeLabelsColumn(hourHeight: hourHeight, periods: data.periods)
.frame(width: 28, alignment: .topTrailing)
@@ -62,12 +65,15 @@ struct TimetableWeekView: View {
let endDate = cal.date(byAdding: .day, value: 4, to: data.anchorDate) ?? data.anchorDate
return HStack {
Text("KW \(week) · \(shortDate(data.anchorDate))\(shortDate(endDate))")
.font(.system(size: 13, weight: .semibold))
.font(.system(size: 12, weight: .semibold))
.foregroundStyle(palette.textPrimary)
.lineLimit(1)
.minimumScaleFactor(0.8)
Spacer()
Text("Stand: \(freshnessLabel(for: data.fetchedAt))")
.font(.system(size: 10))
.font(.system(size: 9))
.foregroundStyle(palette.textSecondary)
.lineLimit(1)
}
}
@@ -85,24 +91,30 @@ struct TimetableWeekView: View {
columnDivider
ForEach(0..<5, id: \.self) { offset in
let day = cal.date(byAdding: .day, value: offset, to: data.anchorDate) ?? data.anchorDate
VStack(spacing: 0) {
VStack(spacing: -1) {
Text(weekday(for: day))
.font(.system(size: 11, weight: .bold))
.font(.system(size: 10, weight: .bold))
.foregroundStyle(palette.textPrimary)
Text(shortDate(day))
.font(.system(size: 9))
.font(.system(size: 8))
.foregroundStyle(palette.textSecondary)
}
.frame(maxWidth: .infinity)
if offset < 4 { columnDivider }
}
}
.frame(maxWidth: .infinity, minHeight: 26, maxHeight: 26)
// 20pt fits 10pt weekday + 8pt date with tight -1pt spacing.
.frame(maxWidth: .infinity, minHeight: 20, maxHeight: 20)
}
private func timeLabelsColumn(hourHeight: CGFloat, periods: [WidgetPeriod]) -> some View {
let totalMin = periods.last?.virtualEndMinutes ?? FALLBACK_VIRTUAL_MINUTES
let totalHeight = CGFloat(totalMin) * hourHeight / 60.0
// Mirrors TimeGridView.compactLabels below 26pt/hour a stacked
// time+name no longer fits in one period slot and the two labels
// visually clip into the next slot. Drop to a single bold period
// number until there's room to read both lines.
let compact = hourHeight < 26
return ZStack(alignment: .topTrailing) {
ForEach(periodBoundaries(periods), id: \.self) { virtualMin in
Rectangle()
@@ -112,15 +124,23 @@ struct TimetableWeekView: View {
}
ForEach(periods, id: \.startMinutes) { period in
VStack(alignment: .trailing, spacing: -2) {
Text(String(format: "%02d:%02d", period.startMinutes / 60, period.startMinutes % 60))
.font(.system(size: 8))
.foregroundStyle(palette.textPrimary)
.lineLimit(1)
Text("\(period.name).")
.font(.system(size: 6, weight: .bold))
.foregroundStyle(palette.textSecondary)
.lineLimit(1)
if compact {
Text("\(period.name).")
.font(.system(size: 9, weight: .bold))
.foregroundStyle(palette.textPrimary)
.lineLimit(1)
} else {
Text(String(format: "%02d:%02d", period.startMinutes / 60, period.startMinutes % 60))
.font(.system(size: 9))
.foregroundStyle(palette.textPrimary)
.lineLimit(1)
Text("\(period.name).")
.font(.system(size: 7, weight: .bold))
.foregroundStyle(palette.textSecondary)
.lineLimit(1)
}
}
.padding(.trailing, 4)
.offset(y: CGFloat(period.virtualStartMinutes) * hourHeight / 60.0)
}
}