Add time formatting helper and update seasonal display logic

This commit is contained in:
Horváth Gergely
2025-12-13 03:31:03 +01:00
committed by 4831c0
parent 02acf0e59b
commit 8c877e43db
5 changed files with 95 additions and 53 deletions

View File

@@ -405,41 +405,25 @@ struct TimetableActivityAttributes: ActivityAttributes {
var seasonalRemainingText: String {
let remaining = max(0, timeRemaining)
let hours = Int(remaining) / 3600
if hours >= 24 {
let days = hours / 24
return "Szünetből hátralévő idő: \(days) nap"
}
return "Szünetből hátralévő idő: \(hours) óra"
}
var seasonalDisplayValue: String {
let remaining = max(0, timeRemaining)
let hours = Int(remaining) / 3600
if hours >= 24 {
let days = hours / 24
return "\(days) nap"
}
return "\(hours) óra"
}
}

View File

@@ -28,6 +28,8 @@ struct SeasonalIconHelper {
return "leaf.fill"
case "winter":
return "snowflake"
case "other":
return "calendar.badge.exclamationmark"
default:
return "snowflake"
}
@@ -57,24 +59,5 @@ struct SeasonalIconHelper {
}
return mode == "seasonalBreak" || mode == "xmas" || mode == "newYearEve" || mode == "newYearDay"
}
static func holidayTitle(for season: String?) -> String {
guard let season = season else {
return "Kellemes szünetet!"
}
switch season {
case "spring":
return "Kellemes tavaszi szünetet!"
case "summer":
return "Kellemes nyári szünetet!"
case "autumn":
return "Kellemes őszi szünetet!"
case "winter":
return "Kellemes téli szünetet!"
default:
return "Kellemes szünetet!"
}
}
}

View File

@@ -0,0 +1,62 @@
import Foundation
struct TimeFormatHelper {
static func compactTime(remaining: TimeInterval) -> String {
let lang = Locale.current.languageCode ?? "hu"
let hours = Int(max(0, remaining)) / 3600
let minutes = (Int(max(0, remaining)) % 3600) / 60
if hours >= 1 {
return shortHours(hours, language: lang)
} else {
return shortMinutes(minutes, language: lang)
}
}
static func compactSeasonalBreak(from message: String) -> String {
let lang = Locale.current.languageCode ?? "hu"
let components = message.split(separator: " ")
let number = components.first.map(String.init) ?? ""
let isDay = message.lowercased().contains("day") ||
message.lowercased().contains("nap") ||
message.lowercased().contains("tag")
if isDay {
return shortDays(Int(number) ?? 0, language: lang)
} else {
return shortHours(Int(number) ?? 0, language: lang)
}
}
// MARK: - Private Helpers
private static func shortHours(_ hours: Int, language: String) -> String {
switch language {
case "en": return "\(hours)h"
case "de": return "\(hours)h"
case "hu": return "\(hours)ó"
default: return "\(hours)h"
}
}
private static func shortMinutes(_ minutes: Int, language: String) -> String {
switch language {
case "en": return "\(minutes)m"
case "de": return "\(minutes)m"
case "hu": return "\(minutes)p"
default: return "\(minutes)m"
}
}
private static func shortDays(_ days: Int, language: String) -> String {
switch language {
case "en": return "\(days)d"
case "de": return "\(days)d"
case "hu": return "\(days)n"
default: return "\(days)d"
}
}
}

View File

@@ -236,6 +236,10 @@ extension TimetableActivityAttributes.ContentState {
}
var seasonalRemainingText: String {
if let remainingLabel = labels?.remainingLabel, let message = message, !message.isEmpty {
return "\(remainingLabel): \(message)"
}
let remaining = max(0, timeRemaining)
let hours = Int(remaining) / 3600
if hours >= 24 {
@@ -246,6 +250,10 @@ extension TimetableActivityAttributes.ContentState {
}
var seasonalDisplayValue: String {
if let message = message, !message.isEmpty {
return message
}
let remaining = max(0, timeRemaining)
let hours = Int(remaining) / 3600
if hours >= 24 {

View File

@@ -101,7 +101,7 @@ struct TimetableLiveActivity: Widget {
Image(systemName: SeasonalIconHelper.iconName(for: mode, season: season))
.font(.system(size: 18))
.foregroundColor(SeasonalIconHelper.iconColor(for: mode))
Text(context.state.labels?.title ?? SeasonalIconHelper.holidayTitle(for: season))
Text(context.state.labels?.title ?? context.state.lessonName)
.font(.system(size: 18, weight: .bold))
.foregroundColor(.white)
.lineLimit(1)
@@ -243,27 +243,32 @@ struct TimetableLiveActivity: Widget {
.font(.system(size: 14))
.foregroundColor(SeasonalIconHelper.iconColor(for: mode))
} compactTrailing: {
if SeasonalIconHelper.isSeasonalMode(mode) {
if mode == "newYearEve" || mode == "seasonalBreak" {
Text(timerInterval: context.state.currentTime...context.state.endTime, countsDown: true)
.font(.system(size: 12, weight: .semibold, design: .rounded))
.foregroundColor(.green)
.monospacedDigit()
.frame(width: 50)
} else {
Text("")
.frame(width: 50)
}
if mode == "seasonalBreak" {
// Seasonal break: static short format from backend message
let compactText = TimeFormatHelper.compactSeasonalBreak(from: context.state.message ?? "")
Text(compactText)
.font(.system(size: 12, weight: .semibold, design: .rounded))
.foregroundColor(.green)
.frame(width: 50)
} else if mode == "xmas" || mode == "newYearDay" {
Text("")
.frame(width: 50)
} else if context.state.isCancelled ?? false {
Text("")
.font(.system(size: 12, weight: .semibold))
.frame(width: 50)
} else {
Text(timerInterval: context.state.currentTime...context.state.endTime, countsDown: true)
.font(.system(size: 12, weight: .semibold, design: .rounded))
.foregroundColor(.green)
.monospacedDigit()
.frame(width: 50)
// Dynamic short format for lesson/break/beforeSchool/newYearEve
TimelineView(.periodic(from: context.state.currentTime, by: 60.0)) { timeline in
let remaining = context.state.endTime.timeIntervalSince(timeline.date)
let compactText = TimeFormatHelper.compactTime(remaining: remaining)
Text(compactText)
.font(.system(size: 12, weight: .semibold, design: .rounded))
.foregroundColor(.green)
.frame(width: 50)
}
}
} minimal: {
let season = context.state.season ?? ""
@@ -324,7 +329,7 @@ struct TimetableLiveActivityView: View {
.foregroundColor(.white)
.lineLimit(2)
} else {
Text(context.state.labels?.title ?? SeasonalIconHelper.holidayTitle(for: context.state.season))
Text(context.state.labels?.title ?? context.state.lessonName)
.font(.system(size: 20, weight: .bold))
.foregroundColor(.white)
.lineLimit(1)