forked from firka/student-legacy
commit
a199f919b6
@ -66,7 +66,12 @@ const userDataDB = DatabaseStruct("user_data", {
|
||||
// renamed teachers // non kreta data
|
||||
"renamed_teachers": String,
|
||||
// "subject_lesson_count": String, // non kreta data
|
||||
// notifications and surprise grades // non kreta data
|
||||
"last_seen_grade": int,
|
||||
"last_seen_surprisegrade": int,
|
||||
"last_seen_absence": int,
|
||||
"last_seen_message": int,
|
||||
"last_seen_lesson": int,
|
||||
// goal planning // non kreta data
|
||||
"goal_plans": String,
|
||||
"goal_averages": String,
|
||||
@ -129,7 +134,11 @@ Future<Database> initDB(DatabaseProvider database) async {
|
||||
// renamed teachers // non kreta data
|
||||
"renamed_teachers": "{}",
|
||||
// "subject_lesson_count": "{}", // non kreta data
|
||||
"last_seen_grade": 0,
|
||||
"last_seen_grade": DateTime.now().millisecondsSinceEpoch,
|
||||
"last_seen_surprisegrade": 0,
|
||||
"last_seen_absence": DateTime.now().millisecondsSinceEpoch,
|
||||
"last_seen_message": DateTime.now().millisecondsSinceEpoch,
|
||||
"last_seen_lesson": DateTime.now().millisecondsSinceEpoch,
|
||||
// goal planning // non kreta data
|
||||
"goal_plans": "{}",
|
||||
"goal_averages": "{}",
|
||||
@ -207,3 +216,4 @@ Future<void> migrateDB(
|
||||
print("INFO: Database migrated");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'package:refilc/api/providers/database_provider.dart';
|
||||
import 'package:refilc/models/linked_account.dart';
|
||||
import 'package:refilc/helpers/notification_helper.dart';
|
||||
import 'package:refilc/models/self_note.dart';
|
||||
import 'package:refilc/models/subject_lesson_count.dart';
|
||||
import 'package:refilc/models/user.dart';
|
||||
@ -213,11 +214,11 @@ class UserDatabaseQuery {
|
||||
return lessonCount;
|
||||
}
|
||||
|
||||
Future<DateTime> lastSeenGrade({required String userId}) async {
|
||||
Future<DateTime> lastSeen({required String userId, required LastSeenCategory category}) async {
|
||||
List<Map> userData =
|
||||
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||
if (userData.isEmpty) return DateTime(0);
|
||||
int? lastSeenDate = userData.elementAt(0)["last_seen_grade"] as int?;
|
||||
int? lastSeenDate = userData.elementAt(0)["last_seen_${category.name}"] as int?;
|
||||
if (lastSeenDate == null) return DateTime(0);
|
||||
DateTime lastSeen = DateTime.fromMillisecondsSinceEpoch(lastSeenDate);
|
||||
return lastSeen;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'package:refilc/models/linked_account.dart';
|
||||
import 'package:refilc/helpers/notification_helper.dart';
|
||||
import 'package:refilc/models/self_note.dart';
|
||||
import 'package:refilc/models/subject_lesson_count.dart';
|
||||
import 'package:refilc_kreta_api/models/week.dart';
|
||||
@ -129,12 +130,13 @@ class UserDatabaseStore {
|
||||
where: "id = ?", whereArgs: [userId]);
|
||||
}
|
||||
|
||||
Future<void> storeLastSeenGrade(DateTime date,
|
||||
{required String userId}) async {
|
||||
Future<void> storeLastSeen(DateTime date,
|
||||
{required String userId, required LastSeenCategory category}) async {
|
||||
int lastSeenDate = date.millisecondsSinceEpoch;
|
||||
await db.update("user_data", {"last_seen_grade": lastSeenDate},
|
||||
await db.update("user_data", {"last_seen_${category.name}": lastSeenDate},
|
||||
where: "id = ?", whereArgs: [userId]);
|
||||
}
|
||||
|
||||
|
||||
// renamed things
|
||||
Future<void> storeRenamedSubjects(Map<String, String> subjects,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
import 'package:refilc/api/providers/database_provider.dart';
|
||||
|
||||
extension Localization on String {
|
||||
static final _t = Translations.byLocale("hu_hu") +
|
||||
@ -43,8 +44,19 @@ extension Localization on String {
|
||||
"body_lesson_substituted_multiuser": "(%s) Lektion Nr. %s (%s) wird am %s durch %s ersetzt"
|
||||
},
|
||||
};
|
||||
String get i18n {
|
||||
// very hacky way to get app language in notifications
|
||||
// i18n does not like being in background functions (it cannot retrieve locale sometimes)
|
||||
final DatabaseProvider databaseProvider = DatabaseProvider();
|
||||
databaseProvider.init().then((value) {
|
||||
databaseProvider.query.getSettings(databaseProvider).then((settings) {
|
||||
return localize(this, _t, locale: "${settings.language}_${settings.language.toUpperCase()}");
|
||||
});
|
||||
});
|
||||
|
||||
String get i18n => localize(this, _t);
|
||||
|
||||
return 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);
|
||||
|
@ -10,6 +10,8 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:refilc/app.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:refilc/utils/navigation_service.dart';
|
||||
import 'package:refilc/utils/service_locator.dart';
|
||||
import 'package:refilc_mobile_ui/screens/error_screen.dart';
|
||||
import 'package:refilc_mobile_ui/screens/error_report_screen.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
@ -23,12 +25,20 @@ void main() async {
|
||||
// ignore: deprecated_member_use
|
||||
binding.renderView.automaticSystemUiAdjustment = false;
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
// navigation
|
||||
setupLocator();
|
||||
|
||||
// Startup
|
||||
Startup startup = Startup();
|
||||
await startup.start();
|
||||
|
||||
// Custom error page
|
||||
ErrorWidget.builder = errorBuilder;
|
||||
|
||||
// initialize stripe key
|
||||
stripe.Stripe.publishableKey =
|
||||
'pk_test_51Oo7iUBS0FxsTGxKjGZSQqzDKWHY5ZFYM9XeI0qSdIh2w8jWy6GhHlYpT7GLTzgpl1xhE5YP4BXpA4gMZqPmgMId00cGFYFzbh';
|
||||
|
||||
|
||||
BackgroundFetch.registerHeadlessTask(backgroundHeadlessTask);
|
||||
|
||||
@ -53,6 +63,9 @@ class Startup {
|
||||
settings = await database.query.getSettings(database);
|
||||
user = await database.query.getUsers(settings);
|
||||
|
||||
// Set all notification categories to seen to avoid having notifications that the user has already seen in the app
|
||||
NotificationsHelper().setAllCategoriesSeen(user);
|
||||
|
||||
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
||||
// Notifications setup
|
||||
if (!kIsWeb) {
|
||||
@ -113,6 +126,7 @@ class Startup {
|
||||
// Initialize notifications
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
initializationSettings,
|
||||
onDidReceiveNotificationResponse: NotificationsHelper().onDidReceiveNotificationResponse,
|
||||
);
|
||||
}
|
||||
|
||||
|
9
refilc/lib/utils/navigation_service.dart
Normal file
9
refilc/lib/utils/navigation_service.dart
Normal file
@ -0,0 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NavigationService {
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
Future<dynamic> navigateTo(String routeName) {
|
||||
return navigatorKey.currentState!.pushNamed(routeName);
|
||||
}
|
||||
}
|
8
refilc/lib/utils/service_locator.dart
Normal file
8
refilc/lib/utils/service_locator.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:refilc/utils/navigation_service.dart';
|
||||
|
||||
GetIt locator = GetIt.instance;
|
||||
|
||||
void setupLocator() {
|
||||
locator.registerLazySingleton(() => NavigationService());
|
||||
}
|
@ -77,6 +77,8 @@ dependencies:
|
||||
extension_google_sign_in_as_googleapis_auth: ^2.0.12
|
||||
maps_launcher: ^2.2.0
|
||||
google_fonts: ^6.1.0
|
||||
flutter_stripe: ^10.0.0
|
||||
get_it: ^7.6.7
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^3.0.1
|
||||
@ -166,6 +168,7 @@ flutter:
|
||||
weight: 500
|
||||
|
||||
|
||||
|
||||
flutter_launcher_icons:
|
||||
image_path: assets/icons/ic_android.png
|
||||
android: true
|
||||
|
@ -50,6 +50,7 @@ class Absence {
|
||||
DateTime lessonStart;
|
||||
DateTime lessonEnd;
|
||||
int? lessonIndex;
|
||||
bool isSeen = json["isSeen"] ?? false;
|
||||
if (json["Ora"] != null) {
|
||||
lessonStart = json["Ora"]["KezdoDatum"] != null
|
||||
? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal()
|
||||
@ -62,7 +63,6 @@ class Absence {
|
||||
lessonStart = DateTime(0);
|
||||
lessonEnd = DateTime(0);
|
||||
}
|
||||
|
||||
return Absence(
|
||||
id: json["Uid"],
|
||||
date: json["Datum"] != null
|
||||
@ -89,7 +89,7 @@ class Absence {
|
||||
lessonIndex: lessonIndex,
|
||||
group:
|
||||
json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
|
||||
isSeen: false,
|
||||
isSeen: json["isSeen"] ?? false,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:refilc/api/providers/user_provider.dart';
|
||||
import 'package:refilc/api/providers/database_provider.dart';
|
||||
import 'package:refilc/helpers/notification_helper.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/models/user.dart';
|
||||
import 'package:refilc_kreta_api/client/api.dart';
|
||||
@ -49,7 +50,7 @@ class GradeProvider with ChangeNotifier {
|
||||
String? userId = _user.id;
|
||||
if (userId != null) {
|
||||
final userStore = _database.userStore;
|
||||
userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
|
||||
userStore.storeLastSeen(DateTime.now(), userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
_lastSeen = DateTime.now();
|
||||
}
|
||||
}
|
||||
@ -58,7 +59,7 @@ class GradeProvider with ChangeNotifier {
|
||||
String? userId = _user.id;
|
||||
if (userId != null) {
|
||||
final userStore = _database.userStore;
|
||||
userStore.storeLastSeenGrade(DateTime(1969), userId: userId);
|
||||
userStore.storeLastSeen(DateTime(1969), userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
_lastSeen = DateTime(1969);
|
||||
}
|
||||
}
|
||||
@ -74,7 +75,7 @@ class GradeProvider with ChangeNotifier {
|
||||
await convertBySettings();
|
||||
_groupAvg = await userQuery.getGroupAverages(userId: userId);
|
||||
notifyListeners();
|
||||
DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
|
||||
DateTime lastSeenDB = await userQuery.lastSeen(userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
if (lastSeenDB.millisecondsSinceEpoch == 0 ||
|
||||
lastSeenDB.year == 0 ||
|
||||
!_settings.gradeOpeningFun) {
|
||||
|
@ -5,6 +5,8 @@ import 'package:refilc/helpers/quick_actions.dart';
|
||||
import 'package:refilc/icons/filc_icons.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/theme/observer.dart';
|
||||
import 'package:refilc/utils/navigation_service.dart';
|
||||
import 'package:refilc/utils/service_locator.dart';
|
||||
import 'package:refilc_kreta_api/client/client.dart';
|
||||
import 'package:refilc_kreta_api/providers/grade_provider.dart';
|
||||
import 'package:refilc_mobile_ui/common/system_chrome.dart';
|
||||
@ -45,7 +47,7 @@ class NavigationScreenState extends State<NavigationScreen>
|
||||
with WidgetsBindingObserver {
|
||||
late NavigationRoute selected;
|
||||
List<String> initializers = [];
|
||||
final _navigatorState = GlobalKey<NavigatorState>();
|
||||
final _navigatorState = locator<NavigationService>().navigatorKey;
|
||||
|
||||
late SettingsProvider settings;
|
||||
late NewsProvider newsProvider;
|
||||
|
@ -1,12 +1,17 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:refilc/api/providers/database_provider.dart';
|
||||
import 'package:refilc/api/providers/user_provider.dart';
|
||||
import 'package:refilc/helpers/notification_helper.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/models/user.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:refilc_mobile_ui/common/beta_chip.dart';
|
||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
||||
import 'package:refilc_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 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
|
||||
import 'notifications_screen.i18n.dart';
|
||||
|
||||
class MenuNotifications extends StatelessWidget {
|
||||
@ -53,6 +58,19 @@ class MenuNotifications extends StatelessWidget {
|
||||
class NotificationsScreen extends StatelessWidget {
|
||||
const NotificationsScreen({super.key});
|
||||
|
||||
// Set all notification categories as seen to avoid spamming the user with notifications when they turn on notifications
|
||||
void setAll(BuildContext context, DateTime date) {
|
||||
DatabaseProvider database =
|
||||
Provider.of<DatabaseProvider>(context, listen: false);
|
||||
User? user = Provider.of<UserProvider>(context, listen: false).user;
|
||||
if (user != null) {
|
||||
for (LastSeenCategory category in LastSeenCategory.values) {
|
||||
database.userStore
|
||||
.storeLastSeen(date, userId: user.id, category: category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SettingsProvider settings = Provider.of<SettingsProvider>(context);
|
||||
@ -69,151 +87,188 @@ class NotificationsScreen extends StatelessWidget {
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
|
||||
child: Panel(
|
||||
child: Column(
|
||||
children: [
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: SwitchListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0)),
|
||||
value: settings.notificationsGradesEnabled,
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsGradesEnabled: v),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(
|
||||
FeatherIcons.bookmark,
|
||||
color: settings.notificationsGradesEnabled
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: AppColors.of(context).text.withOpacity(.25),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: Column(
|
||||
children: [
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
|
||||
onPressed: () {
|
||||
settings.update(
|
||||
notificationsGradesEnabled:
|
||||
!settings.notificationsGradesEnabled);
|
||||
setAll(context, DateTime.now());
|
||||
},
|
||||
title: Text(
|
||||
"grades".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsGradesEnabled ? .95 : .25),
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
FeatherIcons.bookmark,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsGradesEnabled ? .95 : .25),
|
||||
),
|
||||
trailing: Switch(
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsGradesEnabled: v),
|
||||
value: settings.notificationsGradesEnabled,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: SwitchListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0)),
|
||||
value: settings.notificationsAbsencesEnabled,
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsAbsencesEnabled: v),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(
|
||||
FeatherIcons.clock,
|
||||
color: settings.notificationsAbsencesEnabled
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: AppColors.of(context).text.withOpacity(.25),
|
||||
),
|
||||
const SizedBox(width: 14.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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
|
||||
onPressed: () {
|
||||
settings.update(
|
||||
notificationsAbsencesEnabled:
|
||||
!settings.notificationsAbsencesEnabled);
|
||||
setAll(context, DateTime.now());
|
||||
},
|
||||
title: Text(
|
||||
"absences".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsAbsencesEnabled ? .95 : .25),
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
FeatherIcons.clock,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsAbsencesEnabled ? .95 : .25),
|
||||
),
|
||||
trailing: Switch(
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsAbsencesEnabled: v),
|
||||
value: settings.notificationsAbsencesEnabled,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: SwitchListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0)),
|
||||
value: settings.notificationsMessagesEnabled,
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsMessagesEnabled: v),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(
|
||||
FeatherIcons.messageSquare,
|
||||
color: settings.notificationsMessagesEnabled
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: AppColors.of(context).text.withOpacity(.25),
|
||||
),
|
||||
const SizedBox(width: 14.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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
|
||||
onPressed: () {
|
||||
settings.update(
|
||||
notificationsMessagesEnabled:
|
||||
!settings.notificationsMessagesEnabled);
|
||||
setAll(context, DateTime.now());
|
||||
},
|
||||
title: Text(
|
||||
"messages".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsMessagesEnabled ? .95 : .25),
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
FeatherIcons.messageSquare,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsMessagesEnabled ? .95 : .25),
|
||||
),
|
||||
trailing: Switch(
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsMessagesEnabled: v),
|
||||
value: settings.notificationsMessagesEnabled,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: SwitchListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0)),
|
||||
value: settings.notificationsLessonsEnabled,
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsLessonsEnabled: v),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(
|
||||
FeatherIcons.calendar,
|
||||
color: settings.notificationsLessonsEnabled
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: AppColors.of(context).text.withOpacity(.25),
|
||||
),
|
||||
const SizedBox(width: 14.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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
|
||||
onPressed: () {
|
||||
settings.update(
|
||||
notificationsLessonsEnabled:
|
||||
!settings.notificationsLessonsEnabled);
|
||||
setAll(context, DateTime.now());
|
||||
},
|
||||
title: Text(
|
||||
"lessons".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsLessonsEnabled ? .95 : .25),
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
FeatherIcons.bookmark,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settings.notificationsLessonsEnabled ? .95 : .25),
|
||||
),
|
||||
trailing: Switch(
|
||||
onChanged: (v) =>
|
||||
settings.update(notificationsLessonsEnabled: v),
|
||||
value: settings.notificationsLessonsEnabled,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
// only used for debugging, pressing **will** cause notification spam
|
||||
kDebugMode
|
||||
? SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 9.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
PanelButton(
|
||||
onPressed: () => setAll(
|
||||
context, DateTime(1970, 1, 1, 0, 0, 0, 0, 0)),
|
||||
title: Text("set_all_as_unseen".i18n),
|
||||
leading: Icon(
|
||||
FeatherIcons.mail,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(0.95),
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(4.0)),
|
||||
)
|
||||
],
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -8,7 +8,8 @@ extension SettingsLocalization on String {
|
||||
"grades": "Grades",
|
||||
"absences": "Absences",
|
||||
"messages": "Messages",
|
||||
"lessons": "Lessons"
|
||||
"lessons": "Lessons",
|
||||
"set_all_as_unseen": "Set all as unseen",
|
||||
|
||||
},
|
||||
"hu_hu": {
|
||||
@ -16,14 +17,16 @@ extension SettingsLocalization on String {
|
||||
"grades": "Jegyek",
|
||||
"absences": "Hiányzások",
|
||||
"messages": "Üzenetek",
|
||||
"lessons": "Órák"
|
||||
"lessons": "Órák",
|
||||
"set_all_as_unseen": "Összes kategória beállítása olvasatlannak",
|
||||
},
|
||||
"de_de": {
|
||||
"notifications_screen": "Mitteilung",
|
||||
"grades": "Noten",
|
||||
"absences": "Fehlen",
|
||||
"messages": "Nachrichten",
|
||||
"lessons": "Unterricht"
|
||||
"lessons": "Unterricht",
|
||||
"set_all_as_unseen": "Alle als ungelesen einstellen",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -66,9 +66,10 @@ dependencies:
|
||||
google_fonts: ^6.1.0
|
||||
flutter_any_logo: ^1.1.1
|
||||
custom_sliding_segmented_control: ^1.8.1
|
||||
|
||||
get_it: ^7.6.7
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^3.0.1
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
uses-material-design: true
|
||||
|
Loading…
x
Reference in New Issue
Block a user