From fe70fc7bd157e6da785ba43a95cb5f72b1a8ee94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horv=C3=A1th=20Gergely?= Date: Mon, 24 Nov 2025 21:21:12 +0100 Subject: [PATCH] =?UTF-8?q?-=20Fixed=20lesson=20language=20data;=20backend?= =?UTF-8?q?=20now=20passes=20the=20correct=20values.=20-=20Updated=20handl?= =?UTF-8?q?ing=20of=20cancelled=20lessons:=20removed=20timer=20and=20now?= =?UTF-8?q?=20displaying=20the=20localized=20=E2=80=9CCancelled=E2=80=9D?= =?UTF-8?q?=20text.=20-=20Aligned=20the=20icon=20and=20lesson=20number=20i?= =?UTF-8?q?n=20the=20Dynamic=20Island=20so=20they=20are=20now=20level=20wi?= =?UTF-8?q?th=20the=20label=20text.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimetableActivityAttributes.swift | 56 ++++- .../TimetableLiveActivity.swift | 209 +++++++++--------- firka/lib/helpers/live_activity_service.dart | 41 +++- .../ui/phone/screens/home/home_screen.dart | 26 +++ .../screens/settings/settings_screen.dart | 25 +++ 5 files changed, 241 insertions(+), 116 deletions(-) diff --git a/firka/ios/TimetableWidget/TimetableActivityAttributes.swift b/firka/ios/TimetableWidget/TimetableActivityAttributes.swift index 8433f573..83bd07c0 100644 --- a/firka/ios/TimetableWidget/TimetableActivityAttributes.swift +++ b/firka/ios/TimetableWidget/TimetableActivityAttributes.swift @@ -11,21 +11,36 @@ struct TimetableActivityAttributes: ActivityAttributes { var startTime: Date var endTime: Date var lessonNumber: Int? - + var mode: String? // "lesson" | "break" | "seasonalBreak" | "xmas" | "newYear" var message: String? var season: String? - + var nextLessonName: String? var nextRoomName: String? var nextStartTime: Date? - + var isSubstitution: Bool var isCancelled: Bool var substituteTeacher: String? - + var currentTime: Date + var labels: Labels? + + struct Labels: Codable, Hashable { + var title: String? + var timerLabel: String? + var cancelledText: String? + var substitutionText: String? + var roomLabel: String? + var teacherLabel: String? + var themeLabel: String? + var nextLabel: String? + var firstLessonLabel: String? + var startTimeLabel: String? + } + enum CodingKeys: String, CodingKey { case isBreak case lessonName @@ -45,9 +60,10 @@ struct TimetableActivityAttributes: ActivityAttributes { case isCancelled case substituteTeacher case currentTime + case labels } - init(isBreak: Bool, lessonName: String, lessonTheme: String?, roomName: String?, teacherName: String?, startTime: Date, endTime: Date, lessonNumber: Int?, mode: String?, message: String?, season: String?, nextLessonName: String?, nextRoomName: String?, nextStartTime: Date?, isSubstitution: Bool, isCancelled: Bool, substituteTeacher: String?, currentTime: Date) { + init(isBreak: Bool, lessonName: String, lessonTheme: String?, roomName: String?, teacherName: String?, startTime: Date, endTime: Date, lessonNumber: Int?, mode: String?, message: String?, season: String?, nextLessonName: String?, nextRoomName: String?, nextStartTime: Date?, isSubstitution: Bool, isCancelled: Bool, substituteTeacher: String?, currentTime: Date, labels: Labels? = nil) { self.isBreak = isBreak self.lessonName = lessonName self.lessonTheme = lessonTheme @@ -66,6 +82,7 @@ struct TimetableActivityAttributes: ActivityAttributes { self.isCancelled = isCancelled self.substituteTeacher = substituteTeacher self.currentTime = currentTime + self.labels = labels } init(from decoder: Decoder) throws { @@ -108,7 +125,8 @@ struct TimetableActivityAttributes: ActivityAttributes { isSubstitution = try container.decode(Bool.self, forKey: .isSubstitution) isCancelled = try container.decode(Bool.self, forKey: .isCancelled) substituteTeacher = try container.decodeIfPresent(String.self, forKey: .substituteTeacher) - + labels = try container.decodeIfPresent(Labels.self, forKey: .labels) + let currentTimeStr = try container.decode(String.self, forKey: .currentTime) guard let currentTimeDate = isoFormatter.date(from: currentTimeStr) else { throw DecodingError.dataCorruptedError(forKey: .currentTime, in: container, debugDescription: "Invalid currentTime format: \(currentTimeStr)") @@ -145,7 +163,8 @@ struct TimetableActivityAttributes: ActivityAttributes { try container.encode(isSubstitution, forKey: .isSubstitution) try container.encode(isCancelled, forKey: .isCancelled) try container.encodeIfPresent(substituteTeacher, forKey: .substituteTeacher) - + try container.encodeIfPresent(labels, forKey: .labels) + try container.encode(isoFormatter.string(from: currentTime), forKey: .currentTime) } } @@ -302,7 +321,25 @@ extension TimetableActivityAttributes.ContentState { } else { nextStartTime = nil } - + + let labels: Labels? + if let labelsDict = json["labels"] as? [String: Any] { + labels = Labels( + title: labelsDict["title"] as? String, + timerLabel: labelsDict["timerLabel"] as? String, + cancelledText: labelsDict["cancelledText"] as? String, + substitutionText: labelsDict["substitutionText"] as? String, + roomLabel: labelsDict["roomLabel"] as? String, + teacherLabel: labelsDict["teacherLabel"] as? String, + themeLabel: labelsDict["themeLabel"] as? String, + nextLabel: labelsDict["nextLabel"] as? String, + firstLessonLabel: labelsDict["firstLessonLabel"] as? String, + startTimeLabel: labelsDict["startTimeLabel"] as? String + ) + } else { + labels = nil + } + return TimetableActivityAttributes.ContentState( isBreak: isBreak, lessonName: lessonName, @@ -321,7 +358,8 @@ extension TimetableActivityAttributes.ContentState { isSubstitution: isSubstitution, isCancelled: isCancelled, substituteTeacher: json["substituteTeacher"] as? String, - currentTime: currentTime + currentTime: currentTime, + labels: labels ) } } diff --git a/firka/ios/TimetableWidget/TimetableLiveActivity.swift b/firka/ios/TimetableWidget/TimetableLiveActivity.swift index 8e184a95..410c0963 100644 --- a/firka/ios/TimetableWidget/TimetableLiveActivity.swift +++ b/firka/ios/TimetableWidget/TimetableLiveActivity.swift @@ -49,24 +49,7 @@ struct TimetableLiveActivity: Widget { return DynamicIsland { // Expanded UI DynamicIslandExpandedRegion(.leading) { - let season = context.state.season ?? "" - HStack(alignment: .center, spacing: 4) { - if mode == "beforeSchool" { - Image(systemName: SeasonalIconHelper.iconName(for: mode, season: season)) - .font(.system(size: 18)) - .foregroundColor(SeasonalIconHelper.iconColor(for: mode)) - } else if !SeasonalIconHelper.isSeasonalMode(mode) && !context.state.isBreak { - if let lessonNumber = context.state.lessonNumber { - Text("\(lessonNumber).") - .font(.system(size: 16, weight: .bold)) - .foregroundColor(.white) - } else { - EmptyView() - } - } else { - EmptyView() - } - } + EmptyView() } DynamicIslandExpandedRegion(.trailing) { @@ -78,7 +61,7 @@ struct TimetableLiveActivity: Widget { if SeasonalIconHelper.isSeasonalMode(mode) { EmptyView() } else if mode == "beforeSchool", let timeString = beforeSchoolTime { - Text("Kezdés: \(timeString)") + Text("\(context.state.labels?.startTimeLabel ?? "Kezdés:") \(timeString)") .font(.system(size: 14, weight: .medium)) .foregroundColor(.gray) } else { @@ -92,23 +75,28 @@ struct TimetableLiveActivity: Widget { let season = context.state.season ?? "" VStack(spacing: 4) { if mode == "beforeSchool" { - Text("Hamarosan suli") - .font(.system(size: 18, weight: .bold)) - .foregroundColor(.white) + HStack(alignment: .center, spacing: 6) { + Image(systemName: SeasonalIconHelper.iconName(for: mode, season: season)) + .font(.system(size: 18)) + .foregroundColor(SeasonalIconHelper.iconColor(for: mode)) + Text(context.state.labels?.title ?? "Hamarosan suli") + .font(.system(size: 18, weight: .bold)) + .foregroundColor(.white) + } VStack(alignment: .leading, spacing: 2) { HStack(spacing: 4) { - Text("Első órád:") + Text(context.state.labels?.firstLessonLabel ?? "Első órád:") .font(.system(size: 12)) .foregroundColor(.gray) Text(context.state.lessonName) .font(.system(size: 12, weight: .semibold)) .foregroundColor(.white) } - + if let roomName = context.state.roomName { HStack(spacing: 4) { - Text("Terem:") + Text(context.state.labels?.roomLabel ?? "Terem:") .font(.system(size: 12)) .foregroundColor(.gray) Text(roomName) @@ -119,7 +107,7 @@ struct TimetableLiveActivity: Widget { if let teacherName = context.state.teacherName { HStack(spacing: 4) { - Text("Tanár:") + Text(context.state.labels?.teacherLabel ?? "Tanár:") .font(.system(size: 12)) .foregroundColor(.gray) Text(teacherName) @@ -130,7 +118,6 @@ struct TimetableLiveActivity: Widget { } } else if SeasonalIconHelper.isSeasonalMode(mode) { if mode == "xmas" || mode == "newYearEve" || mode == "newYearDay" { - // Global holidays: show message prominently HStack(alignment: .center, spacing: 6) { Image(systemName: SeasonalIconHelper.iconName(for: mode, season: season)) .font(.system(size: 18)) @@ -141,7 +128,6 @@ struct TimetableLiveActivity: Widget { .lineLimit(2) } } else { - // Seasonal breaks: show holiday title HStack(alignment: .center, spacing: 6) { Image(systemName: SeasonalIconHelper.iconName(for: mode, season: season)) .font(.system(size: 18)) @@ -153,13 +139,18 @@ struct TimetableLiveActivity: Widget { } } } else if context.state.isBreak { - Text("Szünet") - .font(.system(size: 18, weight: .bold)) - .foregroundColor(.white) + HStack(alignment: .center, spacing: 6) { + Image(systemName: "cup.and.saucer.fill") + .font(.system(size: 18)) + .foregroundColor(SeasonalIconHelper.iconColor(for: mode)) + Text(context.state.labels?.title ?? "Szünet") + .font(.system(size: 18, weight: .bold)) + .foregroundColor(.white) + } if let nextLessonName = context.state.nextLessonName { HStack(spacing: 4) { - Text("Következő:") + Text(context.state.labels?.nextLabel ?? "Következő:") .font(.system(size: 14)) .foregroundColor(.gray) Text(nextLessonName) @@ -167,43 +158,46 @@ struct TimetableLiveActivity: Widget { .foregroundColor(.white) } } - + if let nextRoomName = context.state.nextRoomName { - Text("Terem: \(nextRoomName)") + Text("\(context.state.labels?.roomLabel ?? "Terem:") \(nextRoomName)") .font(.system(size: 12)) .foregroundColor(.gray) } } else { - Text(context.state.lessonName) - .font(.system(size: 18, weight: .bold)) - .foregroundColor(.white) - .lineLimit(1) - - if let lessonTheme = context.state.lessonTheme, !lessonTheme.isEmpty { - Text(lessonTheme) - .font(.system(size: 12)) - .foregroundColor(.gray) + HStack(alignment: .center, spacing: 6) { + if let lessonNumber = context.state.lessonNumber { + Text("\(lessonNumber).") + .font(.system(size: 18, weight: .bold)) + .foregroundColor(.white) + } + Text(context.state.lessonName) + .font(.system(size: 18, weight: .bold)) + .foregroundColor(.white) .lineLimit(1) } - + + if !(context.state.isCancelled ?? false) { + if let lessonTheme = context.state.lessonTheme, !lessonTheme.isEmpty { + Text(lessonTheme) + .font(.system(size: 12)) + .foregroundColor(.gray) + .lineLimit(1) + } + } + HStack(spacing: 8) { if let roomName = context.state.roomName { Label(roomName, systemImage: "door.left.hand.closed") .font(.system(size: 12)) .foregroundColor(.gray) } - + if context.state.isSubstitution ?? false { - Label("Helyettesítés", systemImage: "arrow.triangle.2.circlepath") + Label(context.state.labels?.substitutionText ?? "Helyettesítés", systemImage: "arrow.triangle.2.circlepath") .font(.system(size: 12)) .foregroundColor(.orange) } - - if context.state.isCancelled ?? false { - Label("Elmaradt", systemImage: "xmark.circle") - .font(.system(size: 12)) - .foregroundColor(.red) - } } } } @@ -234,6 +228,11 @@ struct TimetableLiveActivity: Widget { .foregroundColor(.green) .multilineTextAlignment(.center) .monospacedDigit() + } else if context.state.isCancelled ?? false { + Text(context.state.labels?.cancelledText ?? "Elmaradt") + .font(.system(size: 20, weight: .bold, design: .rounded)) + .foregroundColor(.red) + .multilineTextAlignment(.center) } else { Text(timerInterval: context.state.currentTime...context.state.endTime, countsDown: true) .font(.system(size: 24, weight: .bold, design: .rounded)) @@ -258,7 +257,6 @@ struct TimetableLiveActivity: Widget { .foregroundColor(SeasonalIconHelper.iconColor(for: mode)) } compactTrailing: { if SeasonalIconHelper.isSeasonalMode(mode) { - // Show timer for New Year's Eve countdown and seasonal breaks if mode == "newYearEve" || mode == "seasonalBreak" { Text(timerInterval: context.state.currentTime...context.state.endTime, countsDown: true) .font(.system(size: 12, weight: .semibold, design: .rounded)) @@ -266,10 +264,13 @@ struct TimetableLiveActivity: Widget { .monospacedDigit() .frame(width: 50) } else { - // No timer for xmas and 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)) @@ -346,30 +347,27 @@ struct TimetableLiveActivityView: View { VStack(alignment: .leading, spacing: 2) { if mode == "beforeSchool" { - Text("Hamarosan suli") + Text(context.state.labels?.title ?? "Hamarosan suli") .font(.system(size: 20, weight: .bold)) .foregroundColor(.white) } else if SeasonalIconHelper.isSeasonalMode(mode) { - // Check if it's a special holiday with a prominent message if mode == "xmas" || mode == "newYearEve" || mode == "newYearDay" { - // Global holidays: show message prominently Text(context.state.message ?? context.state.lessonName) .font(.system(size: 20, weight: .bold)) .foregroundColor(.white) .lineLimit(2) } else { - // Seasonal breaks: show holiday title Text(SeasonalIconHelper.holidayTitle(for: context.state.season)) .font(.system(size: 20, weight: .bold)) .foregroundColor(.white) .lineLimit(1) } } else if context.state.isBreak { - Text("Szünet") + Text(context.state.labels?.title ?? "Szünet") .font(.system(size: 20, weight: .bold)) .foregroundColor(.white) if let nextLessonName = context.state.nextLessonName { - Text("Következő: \(nextLessonName)") + Text("\(context.state.labels?.nextLabel ?? "Következő:") \(nextLessonName)") .font(.system(size: 14)) .foregroundColor(.gray) } @@ -392,7 +390,7 @@ struct TimetableLiveActivityView: View { if SeasonalIconHelper.isSeasonalMode(mode) { EmptyView() } else if mode == "beforeSchool", let timeString = beforeSchoolTime { - Text("Kezdés: \(timeString)") + Text("\(context.state.labels?.startTimeLabel ?? "Kezdés:") \(timeString)") .font(.system(size: 14, weight: .medium)) .foregroundColor(.white) } else { @@ -407,7 +405,7 @@ struct TimetableLiveActivityView: View { EmptyView() } else if context.state.isBreak { if let _ = context.state.nextStartTime { - Text("Kezdés: \(context.state.formattedNextStartTime)") + Text("\(context.state.labels?.startTimeLabel ?? "Kezdés:") \(context.state.formattedNextStartTime)") .font(.system(size: 12)) .foregroundColor(.gray) } else { @@ -434,17 +432,17 @@ struct TimetableLiveActivityView: View { if mode2 == "beforeSchool" { VStack(alignment: .leading, spacing: 4) { HStack(spacing: 4) { - Text("Első órád:") + Text(context.state.labels?.firstLessonLabel ?? "Első órád:") .font(.system(size: 12, weight: .semibold)) .foregroundColor(.gray) Text(context.state.lessonName) .font(.system(size: 12)) .foregroundColor(.white) } - + if let roomName = context.state.roomName { HStack(spacing: 4) { - Text("Terem:") + Text(context.state.labels?.roomLabel ?? "Terem:") .font(.system(size: 12, weight: .semibold)) .foregroundColor(.gray) Text(roomName) @@ -452,10 +450,10 @@ struct TimetableLiveActivityView: View { .foregroundColor(.white) } } - + if let teacherName = context.state.teacherName { HStack(spacing: 4) { - Text("Tanár:") + Text(context.state.labels?.teacherLabel ?? "Tanár:") .font(.system(size: 12, weight: .semibold)) .foregroundColor(.gray) Text(teacherName) @@ -469,15 +467,17 @@ struct TimetableLiveActivityView: View { EmptyView() } else if !context.state.isBreak { VStack(alignment: .leading, spacing: 4) { - if let lessonTheme = context.state.lessonTheme, !lessonTheme.isEmpty { - HStack { - Text("Téma:") - .font(.system(size: 12, weight: .semibold)) - .foregroundColor(.gray) - Text(lessonTheme) - .font(.system(size: 12)) - .foregroundColor(.white) - .lineLimit(1) + if !(context.state.isCancelled ?? false) { + if let lessonTheme = context.state.lessonTheme, !lessonTheme.isEmpty { + HStack { + Text(context.state.labels?.themeLabel ?? "Téma:") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.gray) + Text(lessonTheme) + .font(.system(size: 12)) + .foregroundColor(.white) + .lineLimit(1) + } } } @@ -485,7 +485,7 @@ struct TimetableLiveActivityView: View { HStack(spacing: 4) { Image(systemName: "arrow.triangle.2.circlepath") .font(.system(size: 12)) - Text("Helyettesítés") + Text(context.state.labels?.substitutionText ?? "Helyettesítés") .font(.system(size: 12, weight: .semibold)) if let substituteTeacher = context.state.substituteTeacher { Text("(\(substituteTeacher))") @@ -494,16 +494,6 @@ struct TimetableLiveActivityView: View { } .foregroundColor(.orange) } - - if context.state.isCancelled ?? false { - HStack(spacing: 4) { - Image(systemName: "xmark.circle") - .font(.system(size: 12)) - Text("Elmaradt óra") - .font(.system(size: 12, weight: .semibold)) - } - .foregroundColor(.red) - } } .frame(maxWidth: .infinity, alignment: .leading) } else if let nextRoomName = context.state.nextRoomName { @@ -553,25 +543,32 @@ struct TimetableLiveActivityView: View { .multilineTextAlignment(.center) .monospacedDigit() } else { - let labelText: String = { - if mode3 == "newYearEve" { - return "Új év" - } else if mode3 == "beforeSchool" { - return "Első óra kezdése" - } else if context.state.isBreak { - return "Szünet vége" - } else { - return "Óra vége" - } - }() - Text(labelText) - .font(.system(size: 10)) - .foregroundColor(.gray) - Text(timerInterval: context.state.currentTime...context.state.endTime, countsDown: true) - .font(.system(size: 32, weight: .bold, design: .rounded)) - .foregroundColor(.green) - .multilineTextAlignment(.center) - .monospacedDigit() + if context.state.isCancelled ?? false { + Text(context.state.labels?.cancelledText ?? "Elmaradt") + .font(.system(size: 32, weight: .bold, design: .rounded)) + .foregroundColor(.red) + .multilineTextAlignment(.center) + } else { + let labelText: String = { + if mode3 == "newYearEve" { + return "Új év" + } else if mode3 == "beforeSchool" { + return context.state.labels?.timerLabel ?? "Első óra kezdése" + } else if context.state.isBreak { + return context.state.labels?.timerLabel ?? "Szünet vége" + } else { + return context.state.labels?.timerLabel ?? "Óra vége" + } + }() + Text(labelText) + .font(.system(size: 10)) + .foregroundColor(.gray) + Text(timerInterval: context.state.currentTime...context.state.endTime, countsDown: true) + .font(.system(size: 32, weight: .bold, design: .rounded)) + .foregroundColor(.green) + .multilineTextAlignment(.center) + .monospacedDigit() + } } } Spacer() diff --git a/firka/lib/helpers/live_activity_service.dart b/firka/lib/helpers/live_activity_service.dart index 4fe0f398..fe4691b1 100644 --- a/firka/lib/helpers/live_activity_service.dart +++ b/firka/lib/helpers/live_activity_service.dart @@ -434,7 +434,46 @@ class LiveActivityService { final endOfWeek = startOfWeek.add(const Duration(days: 6)); final timetableResponse = await client.getTimeTable(startOfWeek, endOfWeek); - final allLessons = timetableResponse.response ?? []; + List allLessons = timetableResponse.response ?? []; + + final nextMonday = endOfWeek.add(const Duration(days: 1)); + final nextMondayEnd = nextMonday.add(const Duration(days: 1)); + + try { + final nextMondayResponse = await client.getTimeTable(nextMonday, nextMondayEnd); + if (nextMondayResponse.response != null && nextMondayResponse.response!.isNotEmpty) { + final mondayLessons = nextMondayResponse.response!; + mondayLessons.sort((a, b) => a.start.compareTo(b.start)); + final firstLesson = mondayLessons.first; + + final markedLesson = Lesson( + uid: '${firstLesson.uid}__FOR_NOTIFICATION_ONLY', + date: firstLesson.date, + start: firstLesson.start, + end: firstLesson.end, + name: firstLesson.name, + lessonNumber: firstLesson.lessonNumber, + teacher: firstLesson.teacher, + theme: firstLesson.theme, + roomName: firstLesson.roomName, + substituteTeacher: firstLesson.substituteTeacher, + type: firstLesson.type, + state: firstLesson.state, + canStudentEditHomework: firstLesson.canStudentEditHomework, + isHomeworkComplete: firstLesson.isHomeworkComplete, + attachments: firstLesson.attachments, + isDigitalLesson: firstLesson.isDigitalLesson, + digitalSupportDeviceTypeList: firstLesson.digitalSupportDeviceTypeList, + createdAt: firstLesson.createdAt ?? firstLesson.lastModifiedAt ?? DateTime.now(), + lastModifiedAt: firstLesson.lastModifiedAt, + ); + + allLessons.add(markedLesson); + _logger.info('Added first lesson from next Monday (${firstLesson.name}) marked for notification scheduling only'); + } + } catch (e) { + _logger.warning('Could not fetch next Monday first lesson: $e'); + } if (allLessons.isEmpty) { await LiveActivityManager.endAllActivities(); diff --git a/firka/lib/ui/phone/screens/home/home_screen.dart b/firka/lib/ui/phone/screens/home/home_screen.dart index 19837ef2..cc955d6a 100644 --- a/firka/lib/ui/phone/screens/home/home_screen.dart +++ b/firka/lib/ui/phone/screens/home/home_screen.dart @@ -96,6 +96,30 @@ class _HomeScreenState extends FirkaState { }); } + void _setupNotificationListener() { + final notificationChannel = MethodChannel('firka.app/notifications'); + + notificationChannel.setMethodCallHandler((call) async { + if (call.method == 'onNotificationTapped') { + logger.info('Notification tapped: ${call.arguments}'); + + final args = call.arguments as Map?; + if (args == null) return; + + final action = args['action'] as String?; + final route = args['route'] as String?; + + if (action != null || route != null) { + logger.info('Navigating to timetable from notification'); + setState(() { + homeScreenPage = HomePage.timetable; + _pageController.jumpToPage(HomePage.timetable.index); + }); + } + } + }); + } + void prefetch() async { if (_prefetched) return; @@ -245,6 +269,8 @@ class _HomeScreenState extends FirkaState { if (mounted) setState(() {}); }); + _setupNotificationListener(); + prefetch(); _preloadImages(); diff --git a/firka/lib/ui/phone/screens/settings/settings_screen.dart b/firka/lib/ui/phone/screens/settings/settings_screen.dart index 83a35499..f63753fc 100644 --- a/firka/lib/ui/phone/screens/settings/settings_screen.dart +++ b/firka/lib/ui/phone/screens/settings/settings_screen.dart @@ -719,6 +719,31 @@ class _SettingsScreenState extends FirkaState { )); continue; } + if (item is SettingsButton) { + widgets.add(GestureDetector( + child: FirkaCard( + left: [ + item.iconType != null + ? Row( + children: [ + FirkaIconWidget(item.iconType!, item.iconData!, + color: appStyle.colors.accent), + SizedBox(width: 8), + ], + ) + : SizedBox(), + Text(item.title, + style: appStyle.fonts.B_16SB + .apply(color: appStyle.colors.textPrimary)) + ], + ), + onTap: () async { + await item.onTap(); + }, + )); + + continue; + } if (item is SettingsLogs) { final logFileRegex = RegExp(r'^(\d{4})_(\d{2})_(\d{2})\.log$');