iOS widget enhancements

This commit is contained in:
Marianum
2026-05-12 16:46:56 +02:00
parent 1ae3f7bb83
commit d8a5ccfe80
5 changed files with 145 additions and 57 deletions
@@ -53,6 +53,7 @@ func subjectFont(forHourHeight hourHeight: CGFloat) -> CGFloat {
struct TimetableDayView: View {
let entry: TimetableEntry
@Environment(\.widgetPalette) private var palette
var body: some View {
ZStack {
@@ -65,7 +66,6 @@ struct TimetableDayView: View {
}
}
.background(MarianumWatermark())
.widgetThemeOverride(entry.themeMode)
}
@ViewBuilder
@@ -99,11 +99,11 @@ struct TimetableDayView: View {
HStack {
Text(dayLabel(for: data.anchorDate))
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(.primary)
.foregroundStyle(palette.textPrimary)
Spacer()
Text("Stand: \(freshnessLabel(for: data.fetchedAt))")
.font(.system(size: 10))
.foregroundStyle(.secondary)
.foregroundStyle(palette.textSecondary)
}
}
@@ -112,7 +112,7 @@ struct TimetableDayView: View {
Spacer()
Text(text)
.font(.caption)
.foregroundStyle(.secondary)
.foregroundStyle(palette.textSecondary)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -122,9 +122,10 @@ struct TimetableDayView: View {
VStack(spacing: 4) {
Text("Marianum Stundenplan")
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(palette.textPrimary)
Text(message)
.font(.caption)
.foregroundStyle(.secondary)
.foregroundStyle(palette.textSecondary)
.multilineTextAlignment(.center)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -141,6 +142,8 @@ struct TimeGridView: View {
/// Week-widget passes 3 for narrow columns; day-widget keeps 7.
var horizontalPadding: CGFloat = 7
@Environment(\.widgetPalette) private var palette
private var totalVirtualMinutes: Int {
periods.last?.virtualEndMinutes ?? FALLBACK_VIRTUAL_MINUTES
}
@@ -156,10 +159,12 @@ struct TimeGridView: View {
var body: some View {
HStack(alignment: .top, spacing: 0) {
if showTimeLabels {
// 28pt matches the Week widget's time-label column so the
// visual rhythm is identical across both widgets.
timeLabelsColumn
.frame(width: 32, alignment: .topTrailing)
.frame(width: 28, alignment: .topTrailing)
Rectangle()
.fill(Color.primary.opacity(0.13))
.fill(palette.divider)
.frame(width: 1)
}
ZStack(alignment: .top) {
@@ -175,13 +180,9 @@ struct TimeGridView: View {
private var timeLabelsColumn: some View {
ZStack(alignment: .topTrailing) {
// Hour rules continue through the time-label column so it reads
// as a real table column rather than a free-floating tick list.
// Hour rules extend through the time-label column so it reads
// as a table column rather than a free-floating tick list.
ForEach(periodBoundaries(periods), id: \.self) { virtualMin in
Rectangle()
.fill(Color.primary.opacity(0.08))
.fill(palette.divider)
.frame(height: 1)
.offset(y: CGFloat(virtualMin) * hourHeight / 60.0)
}
@@ -190,16 +191,16 @@ struct TimeGridView: View {
if compactLabels {
Text("\(period.name).")
.font(.system(size: 9, weight: .bold))
.foregroundStyle(.primary)
.foregroundStyle(palette.textPrimary)
.lineLimit(1)
} else {
Text(formatHm(period.startMinutes))
.font(.system(size: 9))
.foregroundStyle(.primary)
.foregroundStyle(palette.textPrimary)
.lineLimit(1)
Text("\(period.name).")
.font(.system(size: 7, weight: .bold))
.foregroundStyle(.secondary)
.foregroundStyle(palette.textSecondary)
.lineLimit(1)
}
}
@@ -212,11 +213,9 @@ struct TimeGridView: View {
private var gridLines: some View {
ZStack(alignment: .top) {
// Hour rules continue through the time-label column so it reads
// as a real table column rather than a free-floating tick list.
ForEach(periodBoundaries(periods), id: \.self) { virtualMin in
Rectangle()
.fill(Color.primary.opacity(0.08))
.fill(palette.divider)
.frame(height: 1)
.offset(y: CGFloat(virtualMin) * hourHeight / 60.0)
}
@@ -232,7 +231,7 @@ struct TimeGridView: View {
let virtualGap = next.virtualStartMinutes - curr.virtualEndMinutes
if virtualGap > 0 {
Rectangle()
.fill(Color.primary.opacity(0.03))
.fill(palette.breakBlock)
.frame(height: CGFloat(virtualGap) * hourHeight / 60.0)
.padding(.horizontal, 1)
.offset(y: CGFloat(curr.virtualEndMinutes) * hourHeight / 60.0)