commit
91255182d2
1286
.idea/libraries/Dart_Packages.xml
generated
Normal file
1286
.idea/libraries/Dart_Packages.xml
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
.idea/libraries/Dart_SDK.xml
generated
Normal file
27
.idea/libraries/Dart_SDK.xml
generated
Normal file
@ -0,0 +1,27 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Dart SDK">
|
||||
<CLASSES>
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/async" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/cli" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/collection" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/convert" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/core" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/developer" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/ffi" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/html" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/indexed_db" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/io" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/isolate" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/js" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/js_util" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/math" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/mirrors" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/svg" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/typed_data" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/web_audio" />
|
||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/web_gl" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Android API 33, extension level 3 Platform" project-jdk-type="Android SDK" />
|
||||
</project>
|
@ -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
|
||||
"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,
|
||||
|
@ -1,35 +1,90 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/database/init.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/helpers/notification_helper.i18n.dart';
|
||||
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:flutter_local_notifications/flutter_local_notifications.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';
|
||||
|
||||
class NotificationsHelper {
|
||||
late DatabaseProvider database;
|
||||
late SettingsProvider settingsProvider;
|
||||
late UserProvider userProvider;
|
||||
late KretaClient kretaClient;
|
||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
|
||||
List<T> combineLists<T, K>(List<T> list1, List<T> list2, K Function(T) keyExtractor,) {
|
||||
Set<K> uniqueKeys = Set<K>();
|
||||
List<T> combinedList = [];
|
||||
|
||||
for (T item in list1) {
|
||||
K key = keyExtractor(item);
|
||||
if (!uniqueKeys.contains(key)) {
|
||||
uniqueKeys.add(key);
|
||||
combinedList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (T item in list2) {
|
||||
K key = keyExtractor(item);
|
||||
if (!uniqueKeys.contains(key)) {
|
||||
uniqueKeys.add(key);
|
||||
combinedList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
DatabaseProvider database = DatabaseProvider();
|
||||
database = DatabaseProvider();
|
||||
var db = await initDB(database);
|
||||
await database.init();
|
||||
SettingsProvider settingsProvider =
|
||||
settingsProvider =
|
||||
await database.query.getSettings(database);
|
||||
UserProvider userProvider = await database.query.getUsers(settingsProvider);
|
||||
userProvider = await database.query.getUsers(settingsProvider);
|
||||
|
||||
if (userProvider.id != null && settingsProvider.notificationsEnabled) {
|
||||
// refresh grades
|
||||
// refresh kreta login
|
||||
final status = StatusProvider();
|
||||
final kretaClient = KretaClient(
|
||||
kretaClient = KretaClient(
|
||||
user: userProvider, settings: settingsProvider, status: status);
|
||||
kretaClient.refreshLogin();
|
||||
GradeProvider gradeProvider = GradeProvider(
|
||||
if(settingsProvider.notificationsGradesEnabled) gradeNotification();
|
||||
if(settingsProvider.notificationsAbsencesEnabled) absenceNotification();
|
||||
if(settingsProvider.notificationsMessagesEnabled) messageNotification();
|
||||
if(settingsProvider.notificationsLessonsEnabled) lessonNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void gradeNotification() async {
|
||||
// fetch grades
|
||||
GradeProvider gradeProvider = GradeProvider(
|
||||
settings: settingsProvider,
|
||||
user: userProvider,
|
||||
database: database,
|
||||
@ -45,39 +100,425 @@ class NotificationsHelper {
|
||||
// if grade is not a normal grade (1-5), don't show it
|
||||
if ([1, 2, 3, 4, 5].contains(grade.value.value)) {
|
||||
// if the grade was added over a week ago, don't show it to avoid notification spam
|
||||
if (grade.seenDate.isAfter(lastSeenGrade) &&
|
||||
grade.date.difference(DateTime.now()).inDays * -1 < 7) {
|
||||
if (grade.seenDate.isAfter(lastSeenGrade) && grade.date.difference(DateTime.now()).inDays * -1 < 7) {
|
||||
// send notificiation about new grade
|
||||
const AndroidNotificationDetails androidNotificationDetails =
|
||||
AndroidNotificationDetails(
|
||||
'GRADES',
|
||||
'Jegyek',
|
||||
channelDescription: 'Értesítés jegyek beírásakor',
|
||||
importance: Importance.max,
|
||||
priority: Priority.max,
|
||||
color: Color(0xFF3D7BF4),
|
||||
ticker: 'Jegyek',
|
||||
groupKey: 'refilc.notifications.GRADES_GROUP',
|
||||
);
|
||||
const NotificationDetails notificationDetails =
|
||||
NotificationDetails(android: androidNotificationDetails);
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
// probably shouldn't use a random int
|
||||
Random().nextInt(432234 * 2),
|
||||
"title".i18n,
|
||||
"body".i18n.fill([
|
||||
grade.value.value.toString(),
|
||||
grade.subject.isRenamed &&
|
||||
settingsProvider.renamedSubjectsEnabled
|
||||
? grade.subject.renamedTo!
|
||||
: grade.subject.name
|
||||
]),
|
||||
notificationDetails);
|
||||
}
|
||||
}
|
||||
AndroidNotificationDetails('GRADES', 'Jegyek',
|
||||
channelDescription: 'Értesítés jegyek beírásakor',
|
||||
importance: Importance.max,
|
||||
priority: Priority.max,
|
||||
color: const Color(0xFF3D7BF4),
|
||||
ticker: 'Jegyek');
|
||||
const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails);
|
||||
if(userProvider.getUsers().length == 1) {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
grade.id.hashCode,
|
||||
"title_grade".i18n,
|
||||
"body_grade".i18n.fill([
|
||||
grade.value.value.toString(),
|
||||
grade.subject.isRenamed &&
|
||||
settingsProvider.renamedSubjectsEnabled
|
||||
? grade.subject.renamedTo!
|
||||
: grade.subject.name
|
||||
]),
|
||||
notificationDetails);
|
||||
} else { // multiple users are added, also display student name
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
grade.id.hashCode,
|
||||
"title_grade".i18n,
|
||||
"body_grade_multiuser".i18n.fill([
|
||||
userProvider.displayName!,
|
||||
grade.value.value.toString(),
|
||||
grade.subject.isRenamed &&
|
||||
settingsProvider.renamedSubjectsEnabled
|
||||
? grade.subject.renamedTo!
|
||||
: grade.subject.name
|
||||
]),
|
||||
notificationDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// set grade seen status
|
||||
gradeProvider.seenAll();
|
||||
}
|
||||
void absenceNotification() async {
|
||||
// get absences from api
|
||||
List? absenceJson = await kretaClient.getAPI(KretaAPI.absences(userProvider.instituteCode ?? ""));
|
||||
List<Absence> storedAbsences = await database.userQuery.getAbsences(userId: userProvider.id!);
|
||||
if(absenceJson == null) {
|
||||
return;
|
||||
}
|
||||
// format api absences to correct format while preserving isSeen value
|
||||
List<Absence> absences = absenceJson.map((e) {
|
||||
Absence apiAbsence = Absence.fromJson(e);
|
||||
Absence storedAbsence = storedAbsences.firstWhere(
|
||||
(stored) => stored.id == apiAbsence.id,
|
||||
orElse: () => apiAbsence);
|
||||
apiAbsence.isSeen = storedAbsence.isSeen;
|
||||
return apiAbsence;
|
||||
}).toList();
|
||||
List<Absence> modifiedAbsences = [];
|
||||
if(absences != storedAbsences) {
|
||||
// remove absences that are not new
|
||||
absences.removeWhere((element) => storedAbsences.contains(element));
|
||||
for(Absence absence in absences) {
|
||||
if(!absence.isSeen) {
|
||||
absence.isSeen = true;
|
||||
modifiedAbsences.add(absence);
|
||||
const AndroidNotificationDetails androidNotificationDetails =
|
||||
AndroidNotificationDetails('ABSENCES', 'Hiányzások',
|
||||
channelDescription: 'Értesítés hiányzások beírásakor',
|
||||
importance: Importance.max,
|
||||
priority: Priority.max,
|
||||
color: const Color(0xFF3D7BF4),
|
||||
ticker: 'Hiányzások');
|
||||
const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails);
|
||||
if(userProvider.getUsers().length == 1) {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
absence.id.hashCode,
|
||||
"title_absence".i18n,
|
||||
"body_absence".i18n.fill([
|
||||
DateFormat("yyyy-MM-dd").format(absence.date),
|
||||
absence.subject.isRenamed &&
|
||||
settingsProvider.renamedSubjectsEnabled
|
||||
? absence.subject.renamedTo!
|
||||
: absence.subject.name
|
||||
]),
|
||||
notificationDetails);
|
||||
} else {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
absence.id.hashCode,
|
||||
"title_absence".i18n,
|
||||
"body_absence_multiuser".i18n.fill([
|
||||
userProvider.displayName!,
|
||||
DateFormat("yyyy-MM-dd").format(absence.date),
|
||||
absence.subject.isRenamed &&
|
||||
settingsProvider.renamedSubjectsEnabled
|
||||
? absence.subject.renamedTo!
|
||||
: absence.subject.name
|
||||
]),
|
||||
notificationDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// combine modified absences and storedabsences list and save them to the database
|
||||
List<Absence> combinedAbsences = combineLists(
|
||||
modifiedAbsences,
|
||||
storedAbsences,
|
||||
(Absence absence) => absence.id,
|
||||
);
|
||||
await database.userStore.storeAbsences(combinedAbsences, userId: userProvider.id!);
|
||||
}
|
||||
|
||||
void messageNotification() async {
|
||||
// get messages from api
|
||||
List? messageJson = await kretaClient.getAPI(KretaAPI.messages("beerkezett"));
|
||||
List<Message> storedmessages = await database.userQuery.getMessages(userId: userProvider.id!);
|
||||
if(messageJson == null) {
|
||||
return;
|
||||
}
|
||||
// format api messages to correct format while preserving isSeen value
|
||||
// Parse messages
|
||||
List<Message> messages = [];
|
||||
await Future.wait(List.generate(messageJson.length, (index) {
|
||||
return () async {
|
||||
Map message = messageJson!.cast<Map>()[index];
|
||||
Map? innerMessageJson = await kretaClient.getAPI(KretaAPI.message(message["azonosito"].toString()));
|
||||
if (innerMessageJson != null) messages.add(Message.fromJson(innerMessageJson, forceType: MessageType.inbox));
|
||||
}();
|
||||
}));
|
||||
|
||||
for(Message message in messages) {
|
||||
for(Message storedMessage in storedmessages) {
|
||||
if(message.id == storedMessage.id) {
|
||||
message.isSeen = storedMessage.isSeen;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Message> modifiedmessages = [];
|
||||
if(messages != storedmessages) {
|
||||
// remove messages that are not new
|
||||
messages.removeWhere((element) => storedmessages.contains(element));
|
||||
for(Message message in messages) {
|
||||
if(!message.isSeen) {
|
||||
message.isSeen = true;
|
||||
modifiedmessages.add(message);
|
||||
const AndroidNotificationDetails androidNotificationDetails =
|
||||
AndroidNotificationDetails('MESSAGES', 'Üzenetek',
|
||||
channelDescription: 'Értesítés kapott üzenetekkor',
|
||||
importance: Importance.max,
|
||||
priority: Priority.max,
|
||||
color: const Color(0xFF3D7BF4),
|
||||
ticker: 'Üzenetek');
|
||||
const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails);
|
||||
if(userProvider.getUsers().length == 1) {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
message.id.hashCode,
|
||||
message.author,
|
||||
message.content.replaceAll(RegExp(r'<[^>]*>'), ''),
|
||||
notificationDetails);
|
||||
} else {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
message.id.hashCode,
|
||||
"(${userProvider.displayName!}) ${message.author}",
|
||||
message.content.replaceAll(RegExp(r'<[^>]*>'), ''),
|
||||
notificationDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// combine modified messages and storedmessages list and save them to the database
|
||||
List<Message> combinedmessages = combineLists(
|
||||
modifiedmessages,
|
||||
storedmessages,
|
||||
(Message message) => message.id,
|
||||
);
|
||||
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!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,16 +4,43 @@ extension Localization on String {
|
||||
static final _t = Translations.byLocale("hu_hu") +
|
||||
{
|
||||
"en_en": {
|
||||
"title": "New grade",
|
||||
"body": "You got a %s in %s"
|
||||
"title_grade": "New grade",
|
||||
"body_grade": "You got a %s in %s",
|
||||
"body_grade_multiuser": "%s got a %s in %s",
|
||||
"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": "Új jegy",
|
||||
"body": "%s-st kaptál %s tantárgyból"
|
||||
"title_grade": "Új jegy",
|
||||
"body_grade": "%s-st kaptál %s tantárgyból",
|
||||
"body_grade_multiuser": "%s tanuló %s-st kapott %s tantárgyból",
|
||||
"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 helyettesíti",
|
||||
"body_lesson_substituted_multiuser": "(%s) %s-i %s. (%s) órát %s helyettesíti"
|
||||
},
|
||||
"de_de": {
|
||||
"title": "Neue Note",
|
||||
"body": "Du hast eine %s in %s"
|
||||
"title_grade": "Neue Note",
|
||||
"body_grade": "Du hast eine %s in %s",
|
||||
"body_grade_multiuser": "%s hast eine %s in %s",
|
||||
"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"
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool _newsEnabled;
|
||||
String _seenNews;
|
||||
bool _notificationsEnabled;
|
||||
bool _notificationsGradesEnabled;
|
||||
bool _notificationsAbsencesEnabled;
|
||||
bool _notificationsMessagesEnabled;
|
||||
bool _notificationsLessonsEnabled;
|
||||
/*
|
||||
notificationsBitfield values:
|
||||
|
||||
@ -84,6 +88,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
required bool newsEnabled,
|
||||
required String seenNews,
|
||||
required bool notificationsEnabled,
|
||||
required bool notificationsGradesEnabled,
|
||||
required bool notificationsAbsencesEnabled,
|
||||
required bool notificationsMessagesEnabled,
|
||||
required bool notificationsLessonsEnabled,
|
||||
required int notificationsBitfield,
|
||||
required bool developerMode,
|
||||
required int notificationPollInterval,
|
||||
@ -122,6 +130,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
_newsEnabled = newsEnabled,
|
||||
_seenNews = seenNews,
|
||||
_notificationsEnabled = notificationsEnabled,
|
||||
_notificationsGradesEnabled = notificationsGradesEnabled,
|
||||
_notificationsAbsencesEnabled = notificationsAbsencesEnabled,
|
||||
_notificationsMessagesEnabled = notificationsMessagesEnabled,
|
||||
_notificationsLessonsEnabled = notificationsLessonsEnabled,
|
||||
_notificationsBitfield = notificationsBitfield,
|
||||
_developerMode = developerMode,
|
||||
_notificationPollInterval = notificationPollInterval,
|
||||
@ -178,6 +190,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
newsEnabled: map["news"] == 1,
|
||||
seenNews: map["seen_news"],
|
||||
notificationsEnabled: map["notifications"] == 1,
|
||||
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,
|
||||
@ -220,6 +236,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
"news": _newsEnabled ? 1 : 0,
|
||||
"seen_news": _seenNews,
|
||||
"notifications": _notificationsEnabled ? 1 : 0,
|
||||
"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,
|
||||
@ -273,6 +293,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
newsEnabled: true,
|
||||
seenNews: '',
|
||||
notificationsEnabled: true,
|
||||
notificationsGradesEnabled: true,
|
||||
notificationsAbsencesEnabled: true,
|
||||
notificationsMessagesEnabled: true,
|
||||
notificationsLessonsEnabled: true,
|
||||
notificationsBitfield: 255,
|
||||
developerMode: false,
|
||||
notificationPollInterval: 1,
|
||||
@ -314,6 +338,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool get newsEnabled => _newsEnabled;
|
||||
List<String> get seenNews => _seenNews.split(',');
|
||||
bool get notificationsEnabled => _notificationsEnabled;
|
||||
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;
|
||||
@ -357,6 +385,10 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool? newsEnabled,
|
||||
String? seenNewsId,
|
||||
bool? notificationsEnabled,
|
||||
bool? notificationsGradesEnabled,
|
||||
bool? notificationsAbsencesEnabled,
|
||||
bool? notificationsMessagesEnabled,
|
||||
bool? notificationsLessonsEnabled,
|
||||
int? notificationsBitfield,
|
||||
bool? developerMode,
|
||||
int? notificationPollInterval,
|
||||
@ -408,6 +440,22 @@ class SettingsProvider extends ChangeNotifier {
|
||||
notificationsEnabled != _notificationsEnabled) {
|
||||
_notificationsEnabled = notificationsEnabled;
|
||||
}
|
||||
if (notificationsGradesEnabled != null &&
|
||||
notificationsGradesEnabled != _notificationsGradesEnabled) {
|
||||
_notificationsGradesEnabled = notificationsGradesEnabled;
|
||||
}
|
||||
if (notificationsAbsencesEnabled != null &&
|
||||
notificationsAbsencesEnabled != _notificationsAbsencesEnabled) {
|
||||
_notificationsAbsencesEnabled = notificationsAbsencesEnabled;
|
||||
}
|
||||
if (notificationsMessagesEnabled != null &&
|
||||
notificationsMessagesEnabled != _notificationsMessagesEnabled) {
|
||||
_notificationsMessagesEnabled = notificationsMessagesEnabled;
|
||||
}
|
||||
if (notificationsLessonsEnabled != null &&
|
||||
notificationsLessonsEnabled != _notificationsLessonsEnabled) {
|
||||
_notificationsLessonsEnabled = notificationsLessonsEnabled;
|
||||
}
|
||||
if (notificationsBitfield != null &&
|
||||
notificationsBitfield != _notificationsBitfield) {
|
||||
_notificationsBitfield = notificationsBitfield;
|
||||
|
@ -89,7 +89,9 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
|
||||
|
||||
// Grades
|
||||
case FilterType.grades:
|
||||
gradeProvider.seenAll();
|
||||
if(!settingsProvider.gradeOpeningFun) {
|
||||
gradeProvider.seenAll();
|
||||
}
|
||||
items = grade_filter.getWidgets(
|
||||
gradeProvider.grades, gradeProvider.lastSeenDate);
|
||||
if (settingsProvider.gradeOpeningFun) {
|
||||
|
@ -192,6 +192,7 @@ class GradeValueWidget extends StatelessWidget {
|
||||
this.outline = false,
|
||||
this.complemented = false,
|
||||
this.nocolor = false,
|
||||
this.color,
|
||||
}) : super(key: key);
|
||||
|
||||
final GradeValue value;
|
||||
@ -202,6 +203,7 @@ class GradeValueWidget extends StatelessWidget {
|
||||
final bool outline;
|
||||
final bool complemented;
|
||||
final bool nocolor;
|
||||
final Color? color;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -209,7 +211,7 @@ class GradeValueWidget extends StatelessWidget {
|
||||
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
||||
|
||||
Color color =
|
||||
gradeColor(context: context, value: value.value, nocolor: nocolor);
|
||||
this.color ?? gradeColor(context: context, value: value.value, nocolor: nocolor);
|
||||
Widget valueText;
|
||||
final percentage = value.percentage;
|
||||
|
||||
|
@ -18,6 +18,14 @@ class Absence {
|
||||
DateTime lessonEnd;
|
||||
int? lessonIndex;
|
||||
String group;
|
||||
bool isSeen;
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Absence && runtimeType == other.runtimeType && id == other.id;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
Absence({
|
||||
required this.id,
|
||||
@ -35,6 +43,7 @@ class Absence {
|
||||
this.lessonIndex,
|
||||
required this.group,
|
||||
this.json,
|
||||
this.isSeen = false,
|
||||
});
|
||||
|
||||
factory Absence.fromJson(Map json) {
|
||||
@ -80,6 +89,7 @@ class Absence {
|
||||
lessonIndex: lessonIndex,
|
||||
group:
|
||||
json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
|
||||
isSeen: false,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ class Message {
|
||||
MessageType? type;
|
||||
List<Recipient> recipients;
|
||||
List<Attachment> attachments;
|
||||
bool isSeen;
|
||||
|
||||
Message({
|
||||
required this.id,
|
||||
@ -32,7 +33,15 @@ class Message {
|
||||
this.replyId,
|
||||
this.conversationId,
|
||||
this.json,
|
||||
this.isSeen = false,
|
||||
});
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Message && runtimeType == other.runtimeType && id == other.id;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
factory Message.fromJson(Map json, {MessageType? forceType}) {
|
||||
Map message = json["uzenet"];
|
||||
@ -69,6 +78,7 @@ class Message {
|
||||
replyId: message["elozoUzenetAzonosito"],
|
||||
conversationId: message["beszelgetesAzonosito"],
|
||||
json: json,
|
||||
isSeen: false,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -0,0 +1,175 @@
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||
import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||
import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'notifications_screen.i18n.dart';
|
||||
|
||||
class MenuNotifications extends StatelessWidget {
|
||||
const MenuNotifications({Key? key, required this.settings}) : super(key: key);
|
||||
|
||||
final SettingsProvider settings;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0),
|
||||
onPressed: () {
|
||||
Navigator.of(context, rootNavigator: true).push(
|
||||
CupertinoPageRoute(builder: (context) => NotificationsScreen()),
|
||||
);
|
||||
},
|
||||
title: Text(
|
||||
"notifications_screen".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(settings.notificationsEnabled ? 1.0 : .5)),
|
||||
),
|
||||
leading: settings.notificationsEnabled
|
||||
? const Icon(FeatherIcons.messageSquare)
|
||||
: Icon(FeatherIcons.messageSquare,
|
||||
color: AppColors.of(context).text.withOpacity(.25)),
|
||||
trailingDivider: true,
|
||||
trailing: Switch(
|
||||
onChanged: (v) async {
|
||||
settings.update(notificationsEnabled: v);
|
||||
},
|
||||
value: settings.notificationsEnabled,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationsScreen extends StatelessWidget {
|
||||
NotificationsScreen({super.key});
|
||||
late SettingsProvider settings;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
settings = Provider.of<SettingsProvider>(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: BackButton(color: AppColors.of(context).text),
|
||||
title: Text(
|
||||
"notifications_screen".i18n,
|
||||
style: TextStyle(color: AppColors.of(context).text),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Panel(
|
||||
child: Column(children: [
|
||||
SwitchListTile(
|
||||
value: settings.notificationsGradesEnabled,
|
||||
onChanged: (v) => {settings.update(notificationsGradesEnabled: v)},
|
||||
title: Row(
|
||||
children: [
|
||||
GradeValueWidget(GradeValue(5, "", "", 100), fill: true, size: 30, color: settings.gradeColors[4].withOpacity(
|
||||
settings.notificationsGradesEnabled ? 1.0 : .5)),
|
||||
const SizedBox(width: 14.0),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"grades".i18n,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsGradesEnabled ? 1.0 : .5),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: settings.notificationsAbsencesEnabled,
|
||||
onChanged: (v) => {settings.update(notificationsAbsencesEnabled: v)},
|
||||
title: Row(
|
||||
children: [
|
||||
const SizedBox(width: 8),
|
||||
settings.notificationsAbsencesEnabled
|
||||
? const Icon(FeatherIcons.clock)
|
||||
: Icon(FeatherIcons.clock,
|
||||
color:
|
||||
AppColors.of(context).text.withOpacity(.25)),
|
||||
const SizedBox(width: 23.0),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"absences".i18n,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsAbsencesEnabled ? 1.0 : .5),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: settings.notificationsMessagesEnabled,
|
||||
onChanged: (v) => {settings.update(notificationsMessagesEnabled: v)},
|
||||
title: Row(
|
||||
children: [
|
||||
const SizedBox(width: 8),
|
||||
settings.notificationsMessagesEnabled
|
||||
? const Icon(FeatherIcons.messageSquare)
|
||||
: Icon(FeatherIcons.messageSquare,
|
||||
color:
|
||||
AppColors.of(context).text.withOpacity(.25)),
|
||||
const SizedBox(width: 23.0),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"messages".i18n,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsMessagesEnabled ? 1.0 : .5),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
]),
|
||||
))));
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
|
||||
extension SettingsLocalization on String {
|
||||
static final _t = Translations.byLocale("hu_hu") +
|
||||
{
|
||||
"en_en": {
|
||||
"notifications_screen": "Notifications",
|
||||
"grades": "Grades",
|
||||
"absences": "Absences",
|
||||
"messages": "Messages",
|
||||
"lessons": "Lessons"
|
||||
|
||||
},
|
||||
"hu_hu": {
|
||||
"notifications_screen": "Értesítések",
|
||||
"grades": "Jegyek",
|
||||
"absences": "Hiányzások",
|
||||
"messages": "Üzenetek",
|
||||
"lessons": "Órák"
|
||||
},
|
||||
"de_de": {
|
||||
"notifications_screen": "Mitteilung",
|
||||
"grades": "Noten",
|
||||
"absences": "Fehlen",
|
||||
"messages": "Nachrichten",
|
||||
"lessons": "Unterricht"
|
||||
},
|
||||
};
|
||||
|
||||
String get i18n => localize(this, _t);
|
||||
String fill(List<Object> params) => localizeFill(this, params);
|
||||
String plural(int value) => localizePlural(value, this, _t);
|
||||
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
||||
}
|
@ -27,6 +27,7 @@ import 'package:filcnaplo_mobile_ui/screens/news/news_screen.dart';
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_tile.dart';
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_view.dart';
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/debug/subject_icon_gallery.dart';
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/notifications_screen.dart';
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/privacy_view.dart';
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_helper.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -453,41 +454,7 @@ class _SettingsScreenState extends State<SettingsScreen>
|
||||
),
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: SwitchListTile(
|
||||
value: settings.notificationsEnabled,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
contentPadding: const EdgeInsets.only(left: 12.0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0)),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(FeatherIcons.messageSquare,
|
||||
color: settings.notificationsEnabled
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(.25)),
|
||||
const SizedBox(width: 14.0),
|
||||
Text(
|
||||
"notifications".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsEnabled ? 1.0 : .5),
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 5,
|
||||
),
|
||||
BetaChip(
|
||||
disabled: !settings.notificationsEnabled,
|
||||
),
|
||||
],
|
||||
),
|
||||
onChanged: (value) =>
|
||||
settings.update(notificationsEnabled: value),
|
||||
),
|
||||
child: MenuNotifications(settings: settings)
|
||||
),
|
||||
],
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user