From c58f34f49930f24684b4e0dde8ad3b22401371df Mon Sep 17 00:00:00 2001 From: Armand <4831c0@proton.me> Date: Sat, 28 Feb 2026 15:45:04 +0100 Subject: [PATCH] firka: rewrite Android widget and fix refresh --- .../app/firka/naplo/glance/LessonCard.kt | 6 +- .../app/firka/naplo/glance/TimetableWidget.kt | 23 +++-- .../app/firka/naplo/glance/WidgetLesson.kt | 23 +++++ .../app/src/main/res/xml/timetable_widget.xml | 2 +- firka/lib/data/widget.dart | 98 +++++++++++++------ .../ui/phone/screens/home/home_screen.dart | 3 +- 6 files changed, 114 insertions(+), 41 deletions(-) create mode 100644 firka/android/app/src/main/kotlin/app/firka/naplo/glance/WidgetLesson.kt diff --git a/firka/android/app/src/main/kotlin/app/firka/naplo/glance/LessonCard.kt b/firka/android/app/src/main/kotlin/app/firka/naplo/glance/LessonCard.kt index 3f845cd..91fafe9 100644 --- a/firka/android/app/src/main/kotlin/app/firka/naplo/glance/LessonCard.kt +++ b/firka/android/app/src/main/kotlin/app/firka/naplo/glance/LessonCard.kt @@ -18,7 +18,7 @@ import androidx.glance.text.FontWeight import androidx.glance.text.Text import androidx.glance.text.TextStyle import app.firka.naplo.model.Colors -import app.firka.naplo.model.Lesson +import app.firka.naplo.glance.WidgetLesson import java.time.format.DateTimeFormatterBuilder val hhmm = DateTimeFormatterBuilder() @@ -26,7 +26,7 @@ val hhmm = DateTimeFormatterBuilder() .toFormatter() @Composable -fun LessonCard(lesson: Lesson, colors: Colors, +fun LessonCard(lesson: WidgetLesson, colors: Colors, modifier: GlanceModifier = GlanceModifier) { Box(modifier = modifier @@ -38,7 +38,7 @@ fun LessonCard(lesson: Lesson, colors: Colors, var bgColor = colors.a15p var fgColor = colors.textSecondary - if (lesson.substituteTeacher == null) { + if (lesson.substituteTeacher != null) { bgColor = colors.warning15p fgColor = colors.warningText } diff --git a/firka/android/app/src/main/kotlin/app/firka/naplo/glance/TimetableWidget.kt b/firka/android/app/src/main/kotlin/app/firka/naplo/glance/TimetableWidget.kt index 6f68f1c..b762dcb 100644 --- a/firka/android/app/src/main/kotlin/app/firka/naplo/glance/TimetableWidget.kt +++ b/firka/android/app/src/main/kotlin/app/firka/naplo/glance/TimetableWidget.kt @@ -26,7 +26,7 @@ import androidx.glance.text.FontWeight import androidx.glance.text.Text import androidx.glance.text.TextStyle import app.firka.naplo.model.Colors -import app.firka.naplo.model.Lesson +import app.firka.naplo.glance.WidgetLesson import org.json.JSONObject import java.io.File import java.time.LocalDate @@ -73,17 +73,28 @@ class TimetableWidget : GlanceAppWidget() { val colors = Colors(widgetState) val tt = widgetState.getJSONArray("timetable") - var lessons = mutableListOf() + var lessons = mutableListOf() for (i in 0.. lesson.start.isAfter(start) && lesson.end.isBefore(end) }.toMutableList() + val headerText = if (displayDateStr.isNotEmpty()) displayDateStr else "Mai órarend" + Box(modifier = GlanceModifier .background(colors.background) @@ -92,7 +103,7 @@ class TimetableWidget : GlanceAppWidget() { ) { Column { Text( - "Mai órarend", + headerText, style = TextStyle( color = ColorProvider(colors.textSecondary, colors.textSecondary), fontSize = 12.sp, diff --git a/firka/android/app/src/main/kotlin/app/firka/naplo/glance/WidgetLesson.kt b/firka/android/app/src/main/kotlin/app/firka/naplo/glance/WidgetLesson.kt new file mode 100644 index 0000000..fba1606 --- /dev/null +++ b/firka/android/app/src/main/kotlin/app/firka/naplo/glance/WidgetLesson.kt @@ -0,0 +1,23 @@ +package app.firka.naplo.glance + +import app.firka.naplo.getIntOrNull +import app.firka.naplo.getStringOrNull +import org.json.JSONObject +import java.time.LocalDateTime +import java.time.format.DateTimeFormatterBuilder + +class WidgetLesson(data: JSONObject) { + val formatter = DateTimeFormatterBuilder() + .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS") + .optionalStart() + .appendLiteral('Z') + .optionalEnd() + .toFormatter() + + val name: String = data.getString("Nev") + val start: LocalDateTime = LocalDateTime.parse(data.getString("KezdetIdopont"), formatter) + val end: LocalDateTime = LocalDateTime.parse(data.getString("VegIdopont"), formatter) + val lessonNumber: Int? = data.getIntOrNull("Oraszam") + val roomName: String? = data.getStringOrNull("TeremNeve") + val substituteTeacher: String? = data.getStringOrNull("HelyettesTanarNeve") +} diff --git a/firka/android/app/src/main/res/xml/timetable_widget.xml b/firka/android/app/src/main/res/xml/timetable_widget.xml index b86a1ad..08d7a81 100644 --- a/firka/android/app/src/main/res/xml/timetable_widget.xml +++ b/firka/android/app/src/main/res/xml/timetable_widget.xml @@ -3,5 +3,5 @@ android:minWidth="300dp" android:minHeight="100dp" android:resizeMode="horizontal|vertical" - android:updatePeriodMillis="10000"> + android:updatePeriodMillis="1800000"> \ No newline at end of file diff --git a/firka/lib/data/widget.dart b/firka/lib/data/widget.dart index 1cc3ea0..e90ed09 100644 --- a/firka/lib/data/widget.dart +++ b/firka/lib/data/widget.dart @@ -22,37 +22,56 @@ class WidgetCacheHelper { timetableJson.add(lesson.toJson()); } + return {'colors': _colorsMap(style), 'timetable': timetableJson}; + } + + static Map toAndroidWidgetJson( + FirkaStyle style, + List timetable, + ) { + final timetableJson = >[]; + for (var lesson in timetable) { + timetableJson.add({ + 'Nev': lesson.name, + 'KezdetIdopont': lesson.start.toUtc().toIso8601String(), + 'VegIdopont': lesson.end.toUtc().toIso8601String(), + 'Oraszam': lesson.lessonNumber, + 'TeremNeve': lesson.roomName, + 'HelyettesTanarNeve': lesson.substituteTeacher, + }); + } + return {'colors': _colorsMap(style), 'timetable': timetableJson}; + } + + static Map _colorsMap(FirkaStyle style) { return { - 'colors': { - 'background': style.colors.background.toARGB32(), - 'backgroundAmoled': style.colors.backgroundAmoled.toARGB32(), - 'background0p': style.colors.background0p.toARGB32(), - 'success': style.colors.success.toARGB32(), - 'textPrimary': style.colors.textPrimary.toARGB32(), - 'textSecondary': style.colors.textSecondary.toARGB32(), - 'textTertiary': style.colors.textTertiary.toARGB32(), - 'card': style.colors.card.toARGB32(), - 'cardTranslucent': style.colors.cardTranslucent.toARGB32(), - 'buttonSecondaryFill': style.colors.buttonSecondaryFill.toARGB32(), - 'accent': style.colors.accent.toARGB32(), - 'secondary': style.colors.secondary.toARGB32(), - 'shadowColor': style.colors.shadowColor.toARGB32(), - 'a15p': style.colors.a15p.toARGB32(), - 'warningAccent': style.colors.warningAccent.toARGB32(), - 'warningText': style.colors.warningText.toARGB32(), - 'warning15p': style.colors.warning15p.toARGB32(), - 'warningCard': style.colors.warningCard.toARGB32(), - 'errorAccent': style.colors.errorAccent.toARGB32(), - 'errorText': style.colors.errorText.toARGB32(), - 'error15p': style.colors.error15p.toARGB32(), - 'errorCard': style.colors.errorCard.toARGB32(), - 'grade5': style.colors.grade5.toARGB32(), - 'grade4': style.colors.grade4.toARGB32(), - 'grade3': style.colors.grade3.toARGB32(), - 'grade2': style.colors.grade2.toARGB32(), - 'grade1': style.colors.grade1.toARGB32(), - }, - 'timetable': timetableJson, + 'background': style.colors.background.toARGB32(), + 'backgroundAmoled': style.colors.backgroundAmoled.toARGB32(), + 'background0p': style.colors.background0p.toARGB32(), + 'success': style.colors.success.toARGB32(), + 'textPrimary': style.colors.textPrimary.toARGB32(), + 'textSecondary': style.colors.textSecondary.toARGB32(), + 'textTertiary': style.colors.textTertiary.toARGB32(), + 'card': style.colors.card.toARGB32(), + 'cardTranslucent': style.colors.cardTranslucent.toARGB32(), + 'buttonSecondaryFill': style.colors.buttonSecondaryFill.toARGB32(), + 'accent': style.colors.accent.toARGB32(), + 'secondary': style.colors.secondary.toARGB32(), + 'shadowColor': style.colors.shadowColor.toARGB32(), + 'a15p': style.colors.a15p.toARGB32(), + 'warningAccent': style.colors.warningAccent.toARGB32(), + 'warningText': style.colors.warningText.toARGB32(), + 'warning15p': style.colors.warning15p.toARGB32(), + 'warningCard': style.colors.warningCard.toARGB32(), + 'errorAccent': style.colors.errorAccent.toARGB32(), + 'errorText': style.colors.errorText.toARGB32(), + 'error15p': style.colors.error15p.toARGB32(), + 'errorCard': style.colors.errorCard.toARGB32(), + 'grade5': style.colors.grade5.toARGB32(), + 'grade4': style.colors.grade4.toARGB32(), + 'grade3': style.colors.grade3.toARGB32(), + 'grade2': style.colors.grade2.toARGB32(), + 'grade1': style.colors.grade1.toARGB32(), }; } @@ -82,6 +101,25 @@ class WidgetCacheHelper { } } + static Future generateWidgetStateForDate( + DateTime date, + FirkaStyle style, + KretaClient client, + ) async { + final dataDir = await getApplicationDocumentsDirectory(); + final dayStart = DateTime(date.year, date.month, date.day); + final dayEnd = dayStart.add(Duration(hours: 23, minutes: 59)); + final lessons = await client.getTimeTable(dayStart, dayEnd, forceCache: false); + final dayLessons = lessons.response ?? []; + + final json = toJson(style, dayLessons); + json['displayDate'] = + '${date.year.toString().padLeft(4, '0')}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; + + final widgetFile = File(p.join(dataDir.path, "widget_state.json")); + await widgetFile.writeAsString(jsonEncode(json)); + } + static Future updateIOSWidgets({ required String locale, required String theme, diff --git a/firka/lib/ui/phone/screens/home/home_screen.dart b/firka/lib/ui/phone/screens/home/home_screen.dart index 30a74f4..e5649c9 100644 --- a/firka/lib/ui/phone/screens/home/home_screen.dart +++ b/firka/lib/ui/phone/screens/home/home_screen.dart @@ -198,7 +198,8 @@ class _HomeScreenState extends FirkaState if (Platform.isAndroid) { await WidgetCacheHelper.updateWidgetCache(appStyle, initData.client); await HomeWidget.updateWidget( - qualifiedAndroidName: "app.firka.naplo.glance.TimetableWidget", + qualifiedAndroidName: + "app.firka.naplo.glance.TimetableWidgetReceiver", ); }