forked from firka/firka
Add time formatting helper and update seasonal display logic
This commit is contained in:
@@ -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"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
62
firka/ios/TimetableWidget/TimeFormatHelper.swift
Normal file
62
firka/ios/TimetableWidget/TimeFormatHelper.swift
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user