From ea2b91ca156c6a022c94acd2ddbc349732a96c46 Mon Sep 17 00:00:00 2001
From: hihihaha <jkristof69420@gmail.com>
Date: Tue, 29 Aug 2023 15:36:23 +0200
Subject: [PATCH] add notification for lesson updates

---
 filcnaplo/lib/database/init.dart              |   2 +-
 .../lib/helpers/notification_helper.dart      | 260 +++++++++++++++++-
 .../lib/helpers/notification_helper.i18n.dart |  15 +
 filcnaplo/lib/models/settings.dart            |  12 +
 filcnaplo_kreta_api/lib/models/lesson.dart    |  10 +
 .../lib/providers/timetable_provider.dart     |  16 +-
 .../settings/notifications_screen.dart        |  26 ++
 .../settings/notifications_screen.i18n.dart   |   5 +-
 8 files changed, 334 insertions(+), 12 deletions(-)

diff --git a/filcnaplo/lib/database/init.dart b/filcnaplo/lib/database/init.dart
index 852b1dc..b256cdc 100644
--- a/filcnaplo/lib/database/init.dart
+++ b/filcnaplo/lib/database/init.dart
@@ -20,7 +20,7 @@ const settingsDB = DatabaseStruct("settings", {
   "grade_color4": int, "grade_color5": int, // grade colors
   "vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
   "notifications": int, "notifications_bitfield": int,
-  "notification_poll_interval": int, "notifications_grades":int, "notifications_absences":int, "notifications_messages": int, // notifications
+  "notification_poll_interval": int, "notifications_grades":int, "notifications_absences":int, "notifications_messages": int, "notifications_lessons":int, // notifications
   "x_filc_id": String, "graph_class_avg": int, "presentation_mode": int,
   "bell_delay": int, "bell_delay_enabled": int,
   "grade_opening_fun": int, "icon_pack": String, "premium_scopes": String,
diff --git a/filcnaplo/lib/helpers/notification_helper.dart b/filcnaplo/lib/helpers/notification_helper.dart
index 598be68..7ee3a39 100644
--- a/filcnaplo/lib/helpers/notification_helper.dart
+++ b/filcnaplo/lib/helpers/notification_helper.dart
@@ -10,9 +10,12 @@ import 'package:filcnaplo_kreta_api/client/api.dart';
 import 'package:filcnaplo_kreta_api/client/client.dart';
 import 'package:filcnaplo_kreta_api/models/absence.dart';
 import 'package:filcnaplo_kreta_api/models/grade.dart';
+import 'package:filcnaplo_kreta_api/models/lesson.dart';
+import 'package:filcnaplo_kreta_api/models/week.dart';
 import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
 import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
 import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message;
+import 'package:i18n_extension/i18n_widget.dart';
 import 'package:intl/intl.dart';
 import 'package:filcnaplo_kreta_api/models/message.dart';
 
@@ -45,6 +48,15 @@ class NotificationsHelper {
 
     return combinedList;
   }
+  String dayTitle(DateTime date) {
+    try {
+      return DateFormat("EEEE", I18n.locale.languageCode)
+          .format(date);
+    } catch (e) {
+      return "Unknown";
+    }
+  }
+
   @pragma('vm:entry-point')
   void backgroundJob() async {
     // initialize providers
@@ -65,7 +77,8 @@ class NotificationsHelper {
       kretaClient.refreshLogin();
       if(settingsProvider.notificationsGradesEnabled) gradeNotification();
       if(settingsProvider.notificationsAbsencesEnabled) absenceNotification();
-      messageNotification();
+      if(settingsProvider.notificationsMessagesEnabled) messageNotification();
+      if(settingsProvider.notificationsLessonsEnabled) lessonNotification();
     }
   }
   
@@ -265,4 +278,247 @@ class NotificationsHelper {
   await database.userStore.storeMessages(combinedmessages, userId: userProvider.id!);
   }
   
-}
+  void lessonNotification() async {
+    // get lesson from api
+    TimetableProvider timetableProvider = TimetableProvider(
+        user: userProvider, database: database, kreta: kretaClient);
+    List<Lesson> storedlessons =
+        timetableProvider.lessons[Week.current()] ?? [];
+    List? apilessons = timetableProvider.getWeek(Week.current()) ?? [];
+    for (Lesson lesson in apilessons) {
+      for (Lesson storedLesson in storedlessons) {
+        if (lesson.id == storedLesson.id) {
+          lesson.isSeen = storedLesson.isSeen;
+        }
+      }
+    }
+    List<Lesson> modifiedlessons = [];
+    if (apilessons != storedlessons) {
+      // remove lessons that are not new
+      apilessons.removeWhere((element) => storedlessons.contains(element));
+      for (Lesson lesson in apilessons) {
+        if (!lesson.isSeen && lesson.isChanged) {
+          lesson.isSeen = true;
+          modifiedlessons.add(lesson);
+          const AndroidNotificationDetails androidNotificationDetails =
+              AndroidNotificationDetails('LESSONS', 'Órák',
+                  channelDescription:
+                      'Értesítés órák elmaradásáról, helyettesítésről',
+                  importance: Importance.max,
+                  priority: Priority.max,
+                  color: const Color(0xFF3D7BF4),
+                  ticker: 'Órák');
+          const NotificationDetails notificationDetails =
+              NotificationDetails(android: androidNotificationDetails);
+          if (userProvider.getUsers().length == 1) {
+            if (lesson.status?.name == "Elmaradt") {
+              switch (I18n.localeStr) {
+                case "en_en":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_canceled".i18n.fill([
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date)
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                case "hu_hu":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_canceled".i18n.fill([
+                          dayTitle(lesson.date),
+                          lesson.lessonIndex,
+                          lesson.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                default:
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_canceled".i18n.fill([
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date)
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+              }
+            } else if (lesson.substituteTeacher?.name != "") {
+              switch (I18n.localeStr) {
+                case "en_en":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_substituted".i18n.fill([
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date),
+                          lesson.substituteTeacher!.isRenamed
+                              ? lesson.substituteTeacher!.renamedTo!
+                              : lesson.substituteTeacher!.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                case "hu_hu":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_substituted".i18n.fill([
+                          dayTitle(lesson.date),
+                          lesson.lessonIndex,
+                          lesson.name,
+                          lesson.substituteTeacher!.isRenamed
+                              ? lesson.substituteTeacher!.renamedTo!
+                              : lesson.substituteTeacher!.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                default:
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_substituted".i18n.fill([
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date),
+                          lesson.substituteTeacher!.isRenamed
+                              ? lesson.substituteTeacher!.renamedTo!
+                              : lesson.substituteTeacher!.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+              }
+            }
+          } else {
+            if (lesson.status?.name == "Elmaradt") {
+              switch (I18n.localeStr) {
+                case "en_en":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_canceled".i18n.fill([
+                          userProvider.displayName!,
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date)
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                case "hu_hu":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_canceled".i18n.fill([
+                          userProvider.displayName!,
+                          dayTitle(lesson.date),
+                          lesson.lessonIndex,
+                          lesson.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                default:
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_canceled".i18n.fill([
+                          userProvider.displayName!,
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date)
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+              }
+            } else if (lesson.substituteTeacher?.name != "") {
+              switch (I18n.localeStr) {
+                case "en_en":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_substituted".i18n.fill([
+                          userProvider.displayName!,
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date),
+                          lesson.substituteTeacher!.isRenamed
+                              ? lesson.substituteTeacher!.renamedTo!
+                              : lesson.substituteTeacher!.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                case "hu_hu":
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_substituted".i18n.fill([
+                          userProvider.displayName!,
+                          dayTitle(lesson.date),
+                          lesson.lessonIndex,
+                          lesson.name,
+                          lesson.substituteTeacher!.isRenamed
+                              ? lesson.substituteTeacher!.renamedTo!
+                              : lesson.substituteTeacher!.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+                default:
+                  {
+                    await flutterLocalNotificationsPlugin.show(
+                        lesson.id.hashCode,
+                        "title_lesson".i18n,
+                        "body_lesson_substituted".i18n.fill([
+                          userProvider.displayName!,
+                          lesson.lessonIndex,
+                          lesson.name,
+                          dayTitle(lesson.date),
+                          lesson.substituteTeacher!.isRenamed
+                              ? lesson.substituteTeacher!.renamedTo!
+                              : lesson.substituteTeacher!.name
+                        ]),
+                        notificationDetails);
+                    break;
+                  }
+              }
+            }
+          }
+        }
+      }
+      // combine modified lesson and storedlesson list and save them to the database
+      List<Lesson> combinedlessons = combineLists(
+        modifiedlessons,
+        storedlessons,
+        (Lesson message) => message.id,
+      );
+      Map<Week, List<Lesson>> timetableLessons = timetableProvider.lessons;
+      timetableLessons[Week.current()] = combinedlessons;
+      await database.userStore
+          .storeLessons(timetableLessons, userId: userProvider.id!);
+    }
+  }
+}
\ No newline at end of file
diff --git a/filcnaplo/lib/helpers/notification_helper.i18n.dart b/filcnaplo/lib/helpers/notification_helper.i18n.dart
index 70f54d9..839646b 100644
--- a/filcnaplo/lib/helpers/notification_helper.i18n.dart
+++ b/filcnaplo/lib/helpers/notification_helper.i18n.dart
@@ -10,6 +10,11 @@ extension Localization on String {
           "title_absence": "Absence recorded",
           "body_absence": "An absence was recorded on %s for %s",
           "body_absence_multiuser": "An absence was recorded for %s on %s for the subject %s",
+          "title_lesson": "Timetable modified",
+          "body_lesson_canceled": "Lesson #%s (%s) has been canceled on %s",
+          "body_lesson_canceled_multiuser": "(%s) Lesson #%s (%s) has been canceled on %s",
+          "body_lesson_substituted": "Lesson #%s (%s) on %s will be substituted by %s",
+          "body_lesson_substituted_multiuser": "(%s) Lesson #%s (%s) on %s will be substituted by %s"
         },
         "hu_hu": {
           "title_grade": "Új jegy",
@@ -18,6 +23,11 @@ extension Localization on String {
           "title_absence": "Új hiányzás",
           "body_absence": "Új hiányzást kaptál %s napon %s tantárgyból",
           "body_absence_multiuser": "%s tanuló új hiányzást kapott %s napon %s tantárgyból",
+          "title_lesson": "Órarend szerkesztve",
+          "body_lesson_canceled": "%s-i %s. óra (%s) elmarad",
+          "body_lesson_canceled_multiuser": "(%s) %s-i %s. óra (%s) elmarad",
+          "body_lesson_substituted": "%s-i %s. (%s) órát %s helyetessíti",
+          "body_lesson_substituted_multiuser": "(%s) %s-i %s. (%s) órát %s helyetessíti"
         },
         "de_de": {
           "title_grade": "Neue Note",
@@ -26,6 +36,11 @@ extension Localization on String {
           "title_absence": "Abwesenheit aufgezeichnet",
           "body_absence": "Auf %s für %s wurde eine Abwesenheit aufgezeichnet",
           "body_absence_multiuser": "Für %s wurde am %s für das Thema Mathematik eine Abwesenheit aufgezeichnet",
+          "title_lesson": "Fahrplan geändert",
+          "body_lesson_canceled": "Lektion Nr. %s (%s) wurde am %s abgesagt",
+          "body_lesson_canceled_multiuser": "(%s) Lektion Nr. %s (%s) wurde am %s abgesagt",
+          "body_lesson_substituted": "Lektion Nr. %s (%s) wird am %s durch %s ersetzt",
+          "body_lesson_substituted_multiuser": "(%s) Lektion Nr. %s (%s) wird am %s durch %s ersetzt"
         },
       };
 
diff --git a/filcnaplo/lib/models/settings.dart b/filcnaplo/lib/models/settings.dart
index 26969ba..9f59887 100644
--- a/filcnaplo/lib/models/settings.dart
+++ b/filcnaplo/lib/models/settings.dart
@@ -34,6 +34,7 @@ class SettingsProvider extends ChangeNotifier {
   bool _notificationsGradesEnabled;
   bool _notificationsAbsencesEnabled;
   bool _notificationsMessagesEnabled;
+  bool _notificationsLessonsEnabled;
   /*
   notificationsBitfield values:
 
@@ -90,6 +91,7 @@ class SettingsProvider extends ChangeNotifier {
     required bool notificationsGradesEnabled,
     required bool notificationsAbsencesEnabled,
     required bool notificationsMessagesEnabled,
+    required bool notificationsLessonsEnabled,
     required int notificationsBitfield,
     required bool developerMode,
     required int notificationPollInterval,
@@ -131,6 +133,7 @@ class SettingsProvider extends ChangeNotifier {
         _notificationsGradesEnabled = notificationsGradesEnabled,
         _notificationsAbsencesEnabled = notificationsAbsencesEnabled,
         _notificationsMessagesEnabled = notificationsMessagesEnabled,
+        _notificationsLessonsEnabled = notificationsLessonsEnabled,
         _notificationsBitfield = notificationsBitfield,
         _developerMode = developerMode,
         _notificationPollInterval = notificationPollInterval,
@@ -190,6 +193,7 @@ class SettingsProvider extends ChangeNotifier {
       notificationsGradesEnabled: map["notifications_grades"] == 1,
       notificationsAbsencesEnabled: map["notifications_absences"] == 1,
       notificationsMessagesEnabled: map["notifications_messages"] == 1,
+      notificationsLessonsEnabled: map["notifications_lessons"] == 1,
       notificationsBitfield: map["notifications_bitfield"],
       notificationPollInterval: map["notification_poll_interval"],
       developerMode: map["developer_mode"] == 1,
@@ -235,6 +239,7 @@ class SettingsProvider extends ChangeNotifier {
       "notifications_grades": _notificationsGradesEnabled ? 1 : 0,
       "notifications_absences": _notificationsAbsencesEnabled ? 1 : 0,
       "notifications_messages": _notificationsMessagesEnabled ? 1 : 0,
+      "notifications_lessons": _notificationsLessonsEnabled ? 1 : 0,
       "notifications_bitfield": _notificationsBitfield,
       "developer_mode": _developerMode ? 1 : 0,
       "grade_color1": _gradeColors[0].value,
@@ -291,6 +296,7 @@ class SettingsProvider extends ChangeNotifier {
       notificationsGradesEnabled: true,
       notificationsAbsencesEnabled: true,
       notificationsMessagesEnabled: true,
+      notificationsLessonsEnabled: true,
       notificationsBitfield: 255,
       developerMode: false,
       notificationPollInterval: 1,
@@ -335,6 +341,7 @@ class SettingsProvider extends ChangeNotifier {
   bool get notificationsGradesEnabled => _notificationsGradesEnabled;
   bool get notificationsAbsencesEnabled => _notificationsAbsencesEnabled;
   bool get notificationsMessagesEnabled => _notificationsMessagesEnabled;
+  bool get notificationsLessonsEnabled => _notificationsLessonsEnabled;
   int get notificationsBitfield => _notificationsBitfield;
   bool get developerMode => _developerMode;
   int get notificationPollInterval => _notificationPollInterval;
@@ -381,6 +388,7 @@ class SettingsProvider extends ChangeNotifier {
     bool? notificationsGradesEnabled,
     bool? notificationsAbsencesEnabled,
     bool? notificationsMessagesEnabled,
+    bool? notificationsLessonsEnabled,
     int? notificationsBitfield,
     bool? developerMode,
     int? notificationPollInterval,
@@ -444,6 +452,10 @@ class SettingsProvider extends ChangeNotifier {
         notificationsMessagesEnabled != _notificationsMessagesEnabled) {
       _notificationsMessagesEnabled = notificationsMessagesEnabled;
     }
+    if (notificationsLessonsEnabled != null &&
+        notificationsLessonsEnabled != _notificationsLessonsEnabled) {
+      _notificationsLessonsEnabled = notificationsLessonsEnabled;
+    }
     if (notificationsBitfield != null &&
         notificationsBitfield != _notificationsBitfield) {
       _notificationsBitfield = notificationsBitfield;
diff --git a/filcnaplo_kreta_api/lib/models/lesson.dart b/filcnaplo_kreta_api/lib/models/lesson.dart
index 0ac9ab2..e232b76 100644
--- a/filcnaplo_kreta_api/lib/models/lesson.dart
+++ b/filcnaplo_kreta_api/lib/models/lesson.dart
@@ -25,6 +25,7 @@ class Lesson {
   String name;
   bool online;
   bool isEmpty;
+  bool isSeen;
 
   Lesson({
     this.status,
@@ -49,7 +50,15 @@ class Lesson {
     this.online = false,
     this.isEmpty = false,
     this.json,
+    this.isSeen = false,
   });
+  @override
+  bool operator ==(Object other) =>
+      identical(this, other) ||
+      other is Lesson && runtimeType == other.runtimeType && id == other.id;
+
+  @override
+  int get hashCode => id.hashCode;
 
   factory Lesson.fromJson(Map json) {
     return Lesson(
@@ -90,6 +99,7 @@ class Lesson {
       online: json["IsDigitalisOra"] ?? false,
       isEmpty: json['isEmpty'] ?? false,
       json: json,
+      isSeen: false
     );
   }
 
diff --git a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
index 841a35f..1e31308 100644
--- a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
+++ b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
@@ -8,7 +8,7 @@ import 'package:filcnaplo_kreta_api/models/week.dart';
 import 'package:flutter/material.dart';
 
 class TimetableProvider with ChangeNotifier {
-  Map<Week, List<Lesson>> _lessons = {};
+  Map<Week, List<Lesson>> lessons = {};
   late final UserProvider _user;
   late final DatabaseProvider _database;
   late final KretaClient _kreta;
@@ -29,7 +29,7 @@ class TimetableProvider with ChangeNotifier {
     // Load lessons from the database
     if (userId != null) {
       var dbLessons = await _database.userQuery.getLessons(userId: userId);
-      _lessons = dbLessons;
+      lessons = dbLessons;
       await convertBySettings();
     }
   }
@@ -45,7 +45,7 @@ class TimetableProvider with ChangeNotifier {
             ? await _database.userQuery.renamedTeachers(userId: _user.id!)
             : {};
 
-    for (Lesson lesson in _lessons.values.expand((e) => e)) {
+    for (Lesson lesson in lessons.values.expand((e) => e)) {
       lesson.subject.renamedTo = renamedSubjects.isNotEmpty
           ? renamedSubjects[lesson.subject.id]
           : null;
@@ -57,7 +57,7 @@ class TimetableProvider with ChangeNotifier {
     notifyListeners();
   }
 
-  List<Lesson>? getWeek(Week week) => _lessons[week];
+  List<Lesson>? getWeek(Week week) => lessons[week];
 
   // Fetches Lessons from the Kreta API then stores them in the database
   Future<void> fetch({Week? week}) async {
@@ -68,11 +68,11 @@ class TimetableProvider with ChangeNotifier {
     List? lessonsJson = await _kreta
         .getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
     if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}";
-    List<Lesson> lessons = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
+    List<Lesson> lessonsList = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
 
-    if (lessons.isEmpty && _lessons.isEmpty) return;
+    if (lessons.isEmpty && lessons.isEmpty) return;
 
-    _lessons[week] = lessons;
+    lessons[week] = lessonsList;
 
     await store();
     await convertBySettings();
@@ -85,7 +85,7 @@ class TimetableProvider with ChangeNotifier {
     String userId = user.id;
 
     // -TODO: clear indexes with weeks outside of the current school year
-    await _database.userStore.storeLessons(_lessons, userId: userId);
+    await _database.userStore.storeLessons(lessons, userId: userId);
   }
 
   // Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart b/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart
index b1ea8a1..c8a2f49 100644
--- a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart
+++ b/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart
@@ -142,6 +142,32 @@ class NotificationsScreen extends StatelessWidget {
                             ),
                           ],
                         ),
+                ),
+                SwitchListTile(
+                  value: settings.notificationsLessonsEnabled,
+                  onChanged: (v) => {settings.update(notificationsLessonsEnabled: v)},
+                  title: Row(
+                          children: [
+                            const SizedBox(width: 8),
+                            settings.notificationsLessonsEnabled
+                          ? const Icon(FeatherIcons.calendar)
+                          : Icon(FeatherIcons.calendar,
+                              color:
+                                  AppColors.of(context).text.withOpacity(.25)),
+                            const SizedBox(width: 23.0),
+                            Expanded(
+                              child: Text(
+                                "lessons".i18n,
+                                style: TextStyle(
+                                  fontWeight: FontWeight.w600,
+                                  fontSize: 16.0,
+                                  color: AppColors.of(context).text.withOpacity(
+                                      settings.notificationsLessonsEnabled ? 1.0 : .5),
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
                 )
               ]),
             ))));
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart b/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart
index 6dccf41..c9d0087 100644
--- a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart
+++ b/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart
@@ -8,6 +8,7 @@ extension SettingsLocalization on String {
           "grades": "Grades",
           "absences": "Absences",
           "messages": "Messages",
+          "lessons": "Lessons"
           
         },
         "hu_hu": {
@@ -15,12 +16,14 @@ extension SettingsLocalization on String {
           "grades": "Jegyek",
           "absences": "Hiányzások",
           "messages": "Üzenetek",
+          "lessons": "Órák"
         },
         "de_de": {
           "notifications_screen": "Mitteilung",
           "grades": "Noten",
           "absences": "Fehlen",
-          "messages": "Nachrichten"
+          "messages": "Nachrichten",
+          "lessons": "Unterricht"
         },
       };