Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
176243b881 | ||
|
|
ed02a340d0 | ||
|
|
2877f4fc5c | ||
|
|
fceb3bf31a | ||
|
|
9883d081ff | ||
|
|
db5a9fb197 | ||
|
|
93438ce3df | ||
|
|
95bca64fb8 | ||
|
|
7821e10869 | ||
|
|
cede3c3129 | ||
|
|
528ee862b9 | ||
|
|
518932c260 | ||
|
|
281b9cf6c4 |
23
.gitignore
vendored
@@ -25,3 +25,26 @@ doc/api/
|
|||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
*.txt
|
*.txt
|
||||||
|
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||||
|
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||||
|
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||||
|
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/dynamic_color
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/flutter_acrylic
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/share_plus_windows
|
||||||
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows
|
||||||
|
filcnaplo/windows/flutter/ephemeral/generated_config.cmake
|
||||||
|
filcnaplo/windows/flutter/generated_plugin_registrant.cc
|
||||||
|
filcnaplo/windows/flutter/generated_plugin_registrant.h
|
||||||
|
filcnaplo/windows/flutter/generated_plugins.cmake
|
||||||
|
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||||
|
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||||
|
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||||
|
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||||
|
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||||
|
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||||
|
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||||
|
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<p align=center>
|
<p align=center>
|
||||||
<img src="https://media.discordapp.net/attachments/1111727410677825596/1111790518964326510/reFilc_Logo2.png?width=671&height=671" width=150>
|
<img src="https://media.discordapp.net/attachments/1111727410677825596/1113217167513624646/reFilc_Logo_Squircle.png?width=671&height=671" width=150>
|
||||||
<h1 align=center><b>reFilc</b></h1>
|
<h1 align=center><b>reFilc</b></h1>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -37,6 +37,6 @@ Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a relea
|
|||||||
|
|
||||||
**annon:** a Filc napló készítője (ez az app a Filcen alapul)
|
**annon:** a Filc napló készítője (ez az app a Filcen alapul)
|
||||||
|
|
||||||
**kima, chromium, peighter, mog, WolfY:** a fejlesztői csapat
|
**kima, mog, WolfY:** fő fejlesztők
|
||||||
|
|
||||||
**Regő, Pearoo:** weboldal design és community management
|
**Regő, Pearoo:** weboldal design és community management
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
BIN
filcnaplo/assets/icons/ic_android.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
@@ -3,6 +3,8 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array/>
|
<array>
|
||||||
|
<string>group.refilcnaplo.livecard</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array/>
|
<array>
|
||||||
|
<string>group.refilcnaplo.livecard</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -13,7 +13,14 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:live_activities/live_activities.dart';
|
import 'package:live_activities/live_activities.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card.i18n.dart';
|
import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card.i18n.dart';
|
||||||
|
|
||||||
enum LiveCardState { empty, duringLesson, duringBreak, morning, afternoon, night }
|
enum LiveCardState {
|
||||||
|
empty,
|
||||||
|
duringLesson,
|
||||||
|
duringBreak,
|
||||||
|
morning,
|
||||||
|
afternoon,
|
||||||
|
night
|
||||||
|
}
|
||||||
|
|
||||||
class LiveCardProvider extends ChangeNotifier {
|
class LiveCardProvider extends ChangeNotifier {
|
||||||
Lesson? currentLesson;
|
Lesson? currentLesson;
|
||||||
@@ -42,14 +49,17 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
_latestActivityId = value.isNotEmpty ? value.first : null;
|
_latestActivityId = value.isNotEmpty ? value.first : null;
|
||||||
});
|
});
|
||||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
||||||
_delay = settings.bellDelayEnabled ? Duration(seconds: settings.bellDelay) : Duration.zero;
|
_delay = settings.bellDelayEnabled
|
||||||
|
? Duration(seconds: settings.bellDelay)
|
||||||
|
: Duration.zero;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_timer.cancel();
|
_timer.cancel();
|
||||||
if (_latestActivityId != null && Platform.isIOS) _liveActivitiesPlugin.endActivity(_latestActivityId!);
|
if (_latestActivityId != null && Platform.isIOS)
|
||||||
|
_liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,14 +88,25 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
switch (currentState) {
|
switch (currentState) {
|
||||||
case LiveCardState.duringLesson:
|
case LiveCardState.duringLesson:
|
||||||
return {
|
return {
|
||||||
"icon": currentLesson != null ? SubjectIcon.resolveName(subject: currentLesson?.subject) : "book",
|
"icon": currentLesson != null
|
||||||
"index": currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
||||||
"title": currentLesson != null ? ShortSubject.resolve(subject: currentLesson?.subject).capital() : "",
|
: "book",
|
||||||
|
"index":
|
||||||
|
currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||||
|
"title": currentLesson != null
|
||||||
|
? ShortSubject.resolve(subject: currentLesson?.subject).capital()
|
||||||
|
: "",
|
||||||
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
"description": currentLesson?.description ?? "",
|
"description": currentLesson?.description ?? "",
|
||||||
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||||
"endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
_delay.inMilliseconds)
|
||||||
"nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject).capital() : "",
|
.toString(),
|
||||||
|
"endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) -
|
||||||
|
_delay.inMilliseconds)
|
||||||
|
.toString(),
|
||||||
|
"nextSubject": nextLesson != null
|
||||||
|
? ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||||
|
: "",
|
||||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
};
|
};
|
||||||
case LiveCardState.duringBreak:
|
case LiveCardState.duringBreak:
|
||||||
@@ -101,10 +122,19 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
return {
|
return {
|
||||||
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
||||||
"title": "Szünet",
|
"title": "Szünet",
|
||||||
"description": "go $diff".i18n.fill([diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room]),
|
"description": "go $diff".i18n.fill([
|
||||||
"startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room
|
||||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
]),
|
||||||
"nextSubject": (nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject) : "").capital(),
|
"startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) -
|
||||||
|
_delay.inMilliseconds)
|
||||||
|
.toString(),
|
||||||
|
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||||
|
_delay.inMilliseconds)
|
||||||
|
.toString(),
|
||||||
|
"nextSubject": (nextLesson != null
|
||||||
|
? ShortSubject.resolve(subject: nextLesson?.subject)
|
||||||
|
: "")
|
||||||
|
.capital(),
|
||||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
"index": "",
|
"index": "",
|
||||||
"subtitle": "",
|
"subtitle": "",
|
||||||
@@ -119,15 +149,25 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
final cmap = toMap();
|
final cmap = toMap();
|
||||||
if (!mapEquals(cmap, _lastActivity)) {
|
if (!mapEquals(cmap, _lastActivity)) {
|
||||||
_lastActivity = cmap;
|
_lastActivity = cmap;
|
||||||
|
try {
|
||||||
if (_lastActivity.isNotEmpty) {
|
if (_lastActivity.isNotEmpty) {
|
||||||
if (_latestActivityId == null) {
|
if (_latestActivityId == null) {
|
||||||
_liveActivitiesPlugin.createActivity(_lastActivity).then((value) => _latestActivityId = value);
|
_liveActivitiesPlugin
|
||||||
|
.createActivity(_lastActivity)
|
||||||
|
.then((value) => _latestActivityId = value);
|
||||||
} else {
|
} else {
|
||||||
_liveActivitiesPlugin.updateActivity(_latestActivityId!, _lastActivity);
|
_liveActivitiesPlugin.updateActivity(
|
||||||
|
_latestActivityId!, _lastActivity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_latestActivityId != null) _liveActivitiesPlugin.endActivity(_latestActivityId!);
|
if (_latestActivityId != null) {
|
||||||
|
_liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
print('ERROR: Unable to create or update iOS LiveCard!');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,19 +179,28 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
today = _today(_timetable);
|
today = _today(_timetable);
|
||||||
}
|
}
|
||||||
|
|
||||||
_delay = _settings.bellDelayEnabled ? Duration(seconds: _settings.bellDelay) : Duration.zero;
|
_delay = _settings.bellDelayEnabled
|
||||||
|
? Duration(seconds: _settings.bellDelay)
|
||||||
|
: Duration.zero;
|
||||||
|
|
||||||
final now = _now().add(_delay);
|
final now = _now().add(_delay);
|
||||||
|
|
||||||
// Filter cancelled lessons #20
|
// Filter cancelled lessons #20
|
||||||
// Filter label lessons #128
|
// Filter label lessons #128
|
||||||
today = today.where((lesson) => lesson.status?.name != "Elmaradt" && lesson.subject.id != '' && !lesson.isEmpty).toList();
|
today = today
|
||||||
|
.where((lesson) =>
|
||||||
|
lesson.status?.name != "Elmaradt" &&
|
||||||
|
lesson.subject.id != '' &&
|
||||||
|
!lesson.isEmpty)
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (today.isNotEmpty) {
|
if (today.isNotEmpty) {
|
||||||
// sort
|
// sort
|
||||||
today.sort((a, b) => a.start.compareTo(b.start));
|
today.sort((a, b) => a.start.compareTo(b.start));
|
||||||
|
|
||||||
final _lesson = today.firstWhere((l) => l.start.isBefore(now) && l.end.isAfter(now), orElse: () => Lesson.fromJson({}));
|
final _lesson = today.firstWhere(
|
||||||
|
(l) => l.start.isBefore(now) && l.end.isAfter(now),
|
||||||
|
orElse: () => Lesson.fromJson({}));
|
||||||
|
|
||||||
if (_lesson.start.year != 0) {
|
if (_lesson.start.year != 0) {
|
||||||
currentLesson = _lesson;
|
currentLesson = _lesson;
|
||||||
@@ -159,7 +208,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
currentLesson = null;
|
currentLesson = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final _next = today.firstWhere((l) => l.start.isAfter(now), orElse: () => Lesson.fromJson({}));
|
final _next = today.firstWhere((l) => l.start.isAfter(now),
|
||||||
|
orElse: () => Lesson.fromJson({}));
|
||||||
nextLessons = today.where((l) => l.start.isAfter(now)).toList();
|
nextLessons = today.where((l) => l.start.isAfter(now)).toList();
|
||||||
|
|
||||||
if (_next.start.year != 0) {
|
if (_next.start.year != 0) {
|
||||||
@@ -168,7 +218,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
nextLesson = null;
|
nextLesson = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final _prev = today.lastWhere((l) => l.end.isBefore(now), orElse: () => Lesson.fromJson({}));
|
final _prev = today.lastWhere((l) => l.end.isBefore(now),
|
||||||
|
orElse: () => Lesson.fromJson({}));
|
||||||
|
|
||||||
if (_prev.start.year != 0) {
|
if (_prev.start.year != 0) {
|
||||||
prevLesson = _prev;
|
prevLesson = _prev;
|
||||||
@@ -198,7 +249,10 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
Duration get delay => _delay;
|
Duration get delay => _delay;
|
||||||
|
|
||||||
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
bool _sameDate(DateTime a, DateTime b) =>
|
||||||
|
(a.year == b.year && a.month == b.month && a.day == b.day);
|
||||||
|
|
||||||
List<Lesson> _today(TimetableProvider p) => (p.getWeek(Week.current()) ?? []).where((l) => _sameDate(l.date, _now())).toList();
|
List<Lesson> _today(TimetableProvider p) => (p.getWeek(Week.current()) ?? [])
|
||||||
|
.where((l) => _sameDate(l.date, _now()))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:filcnaplo/models/config.dart';
|
|||||||
import 'package:filcnaplo/theme/observer.dart';
|
import 'package:filcnaplo/theme/observer.dart';
|
||||||
import 'package:filcnaplo/theme/theme.dart';
|
import 'package:filcnaplo/theme/theme.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
@@ -22,13 +23,18 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart' as mobile;
|
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart' as mobile;
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart' as mobile;
|
import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart' as mobile;
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart' as mobile;
|
import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart' as mobile;
|
||||||
import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart' as mobile;
|
import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart'
|
||||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart' as mobile;
|
as mobile;
|
||||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart' as mobile;
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart'
|
||||||
|
as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart'
|
||||||
|
as mobile;
|
||||||
|
|
||||||
// Desktop UI
|
// Desktop UI
|
||||||
import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart' as desktop;
|
import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart'
|
||||||
import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart' as desktop;
|
as desktop;
|
||||||
|
import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart'
|
||||||
|
as desktop;
|
||||||
import 'package:filcnaplo_desktop_ui/screens/login/login_route.dart' as desktop;
|
import 'package:filcnaplo_desktop_ui/screens/login/login_route.dart' as desktop;
|
||||||
|
|
||||||
// Providers
|
// Providers
|
||||||
@@ -36,7 +42,6 @@ import 'package:filcnaplo/models/settings.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
|
||||||
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
|
||||||
@@ -52,7 +57,12 @@ class App extends StatelessWidget {
|
|||||||
final UserProvider user;
|
final UserProvider user;
|
||||||
final DatabaseProvider database;
|
final DatabaseProvider database;
|
||||||
|
|
||||||
const App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key);
|
const App(
|
||||||
|
{Key? key,
|
||||||
|
required this.database,
|
||||||
|
required this.settings,
|
||||||
|
required this.user})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -65,7 +75,8 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
final status = StatusProvider();
|
final status = StatusProvider();
|
||||||
final kreta = KretaClient(user: user, settings: settings, status: status);
|
final kreta = KretaClient(user: user, settings: settings, status: status);
|
||||||
final timetable = TimetableProvider(user: user, database: database, kreta: kreta);
|
final timetable =
|
||||||
|
TimetableProvider(user: user, database: database, kreta: kreta);
|
||||||
final premium = PremiumProvider(settings: settings);
|
final premium = PremiumProvider(settings: settings);
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
@@ -83,23 +94,44 @@ class App extends StatelessWidget {
|
|||||||
ChangeNotifierProvider<StatusProvider>(create: (_) => status),
|
ChangeNotifierProvider<StatusProvider>(create: (_) => status),
|
||||||
Provider<KretaClient>(create: (_) => kreta),
|
Provider<KretaClient>(create: (_) => kreta),
|
||||||
Provider<DatabaseProvider>(create: (context) => database),
|
Provider<DatabaseProvider>(create: (context) => database),
|
||||||
ChangeNotifierProvider<ThemeModeObserver>(create: (context) => ThemeModeObserver(initialTheme: settings.theme)),
|
ChangeNotifierProvider<ThemeModeObserver>(
|
||||||
ChangeNotifierProvider<NewsProvider>(create: (context) => NewsProvider(context: context)),
|
create: (context) =>
|
||||||
ChangeNotifierProvider<UpdateProvider>(create: (context) => UpdateProvider(context: context)),
|
ThemeModeObserver(initialTheme: settings.theme)),
|
||||||
|
ChangeNotifierProvider<NewsProvider>(
|
||||||
|
create: (context) => NewsProvider(context: context)),
|
||||||
|
ChangeNotifierProvider<UpdateProvider>(
|
||||||
|
create: (context) => UpdateProvider(context: context)),
|
||||||
|
|
||||||
// User data providers
|
// User data providers
|
||||||
ChangeNotifierProvider<GradeProvider>(create: (_) => GradeProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
ChangeNotifierProvider<GradeProvider>(
|
||||||
|
create: (_) => GradeProvider(
|
||||||
|
settings: settings,
|
||||||
|
user: user,
|
||||||
|
database: database,
|
||||||
|
kreta: kreta)),
|
||||||
ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
|
ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
|
||||||
ChangeNotifierProvider<ExamProvider>(create: (context) => ExamProvider(context: context)),
|
ChangeNotifierProvider<ExamProvider>(
|
||||||
ChangeNotifierProvider<HomeworkProvider>(create: (context) => HomeworkProvider(context: context)),
|
create: (context) => ExamProvider(context: context)),
|
||||||
ChangeNotifierProvider<MessageProvider>(create: (context) => MessageProvider(context: context)),
|
ChangeNotifierProvider<HomeworkProvider>(
|
||||||
ChangeNotifierProvider<NoteProvider>(create: (context) => NoteProvider(context: context)),
|
create: (context) => HomeworkProvider(context: context)),
|
||||||
ChangeNotifierProvider<EventProvider>(create: (context) => EventProvider(context: context)),
|
ChangeNotifierProvider<MessageProvider>(
|
||||||
ChangeNotifierProvider<AbsenceProvider>(create: (context) => AbsenceProvider(context: context)),
|
create: (context) => MessageProvider(context: context)),
|
||||||
|
ChangeNotifierProvider<NoteProvider>(
|
||||||
|
create: (context) => NoteProvider(context: context)),
|
||||||
|
ChangeNotifierProvider<EventProvider>(
|
||||||
|
create: (context) => EventProvider(context: context)),
|
||||||
|
ChangeNotifierProvider<AbsenceProvider>(
|
||||||
|
create: (context) => AbsenceProvider(context: context)),
|
||||||
|
|
||||||
ChangeNotifierProvider<GradeCalculatorProvider>(
|
ChangeNotifierProvider<GradeCalculatorProvider>(
|
||||||
create: (_) => GradeCalculatorProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
create: (_) => GradeCalculatorProvider(
|
||||||
ChangeNotifierProvider<LiveCardProvider>(create: (context) => LiveCardProvider(timetable: timetable, settings: settings))
|
settings: settings,
|
||||||
|
user: user,
|
||||||
|
database: database,
|
||||||
|
kreta: kreta)),
|
||||||
|
ChangeNotifierProvider<LiveCardProvider>(
|
||||||
|
create: (context) =>
|
||||||
|
LiveCardProvider(timetable: timetable, settings: settings))
|
||||||
],
|
],
|
||||||
child: Consumer<ThemeModeObserver>(
|
child: Consumer<ThemeModeObserver>(
|
||||||
builder: (context, themeMode, child) {
|
builder: (context, themeMode, child) {
|
||||||
@@ -110,12 +142,15 @@ class App extends StatelessWidget {
|
|||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
// Limit font size scaling to 1.0
|
// Limit font size scaling to 1.0
|
||||||
double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0);
|
double textScaleFactor =
|
||||||
|
min(MediaQuery.of(context).textScaleFactor, 1.0);
|
||||||
|
|
||||||
return I18n(
|
return I18n(
|
||||||
initialLocale: Locale(settings.language, settings.language.toUpperCase()),
|
initialLocale: Locale(
|
||||||
|
settings.language, settings.language.toUpperCase()),
|
||||||
child: MediaQuery(
|
child: MediaQuery(
|
||||||
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaleFactor: textScaleFactor),
|
||||||
child: child ?? Container(),
|
child: child ?? Container(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -148,7 +183,8 @@ class App extends StatelessWidget {
|
|||||||
return locale;
|
return locale;
|
||||||
},
|
},
|
||||||
onGenerateRoute: (settings) => rootNavigator(settings),
|
onGenerateRoute: (settings) => rootNavigator(settings),
|
||||||
initialRoute: user.getUsers().isNotEmpty ? "navigation" : "login",
|
initialRoute:
|
||||||
|
user.getUsers().isNotEmpty ? "navigation" : "login",
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -162,7 +198,8 @@ class App extends StatelessWidget {
|
|||||||
if (Platform.isAndroid || Platform.isIOS) {
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
switch (route.name) {
|
switch (route.name) {
|
||||||
case "login_back":
|
case "login_back":
|
||||||
return CupertinoPageRoute(builder: (context) => const mobile.LoginScreen(back: true));
|
return CupertinoPageRoute(
|
||||||
|
builder: (context) => const mobile.LoginScreen(back: true));
|
||||||
case "login":
|
case "login":
|
||||||
return _rootRoute(const mobile.LoginScreen());
|
return _rootRoute(const mobile.LoginScreen());
|
||||||
case "navigation":
|
case "navigation":
|
||||||
@@ -175,7 +212,8 @@ class App extends StatelessWidget {
|
|||||||
} else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
|
} else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
|
||||||
switch (route.name) {
|
switch (route.name) {
|
||||||
case "login_back":
|
case "login_back":
|
||||||
return CupertinoPageRoute(builder: (context) => const desktop.LoginScreen(back: true));
|
return CupertinoPageRoute(
|
||||||
|
builder: (context) => const desktop.LoginScreen(back: true));
|
||||||
case "login":
|
case "login":
|
||||||
return _rootRoute(const desktop.LoginScreen());
|
return _rootRoute(const desktop.LoginScreen());
|
||||||
case "navigation":
|
case "navigation":
|
||||||
|
|||||||
@@ -148,12 +148,12 @@ flutter:
|
|||||||
style: italic
|
style: italic
|
||||||
|
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
image_path: assets/icons/ic_launcher.png
|
image_path: assets/icons/ic_android.png
|
||||||
android: true
|
android: true
|
||||||
adaptive_icon_background: "#3D7BF4"
|
adaptive_icon_background: "#3D7BF4"
|
||||||
adaptive_icon_foreground: assets/icons/ic_launcher_foreground.png
|
adaptive_icon_foreground: assets/icons/ic_android.png
|
||||||
ios: true
|
ios: false
|
||||||
remove_alpha_ios: true
|
remove_alpha_ios: false
|
||||||
|
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
color: "#3D7BF4"
|
color: "#3D7BF4"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:filcnaplo_kreta_api/client/api.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/group_average.dart';
|
import 'package:filcnaplo_kreta_api/models/group_average.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.i18n.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class GradeProvider with ChangeNotifier {
|
class GradeProvider with ChangeNotifier {
|
||||||
@@ -21,7 +22,8 @@ class GradeProvider with ChangeNotifier {
|
|||||||
|
|
||||||
// Public
|
// Public
|
||||||
List<Grade> get grades => _grades;
|
List<Grade> get grades => _grades;
|
||||||
DateTime get lastSeenDate => _settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
|
DateTime get lastSeenDate =>
|
||||||
|
_settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
|
||||||
String get groups => _groups;
|
String get groups => _groups;
|
||||||
List<GroupAverage> get groupAverages => _groupAvg;
|
List<GroupAverage> get groupAverages => _groupAvg;
|
||||||
|
|
||||||
@@ -65,7 +67,9 @@ class GradeProvider with ChangeNotifier {
|
|||||||
_groupAvg = await userQuery.getGroupAverages(userId: userId);
|
_groupAvg = await userQuery.getGroupAverages(userId: userId);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
|
DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
|
||||||
if (lastSeenDB.millisecondsSinceEpoch == 0 || lastSeenDB.year == 0 || !_settings.gradeOpeningFun) {
|
if (lastSeenDB.millisecondsSinceEpoch == 0 ||
|
||||||
|
lastSeenDB.year == 0 ||
|
||||||
|
!_settings.gradeOpeningFun) {
|
||||||
_lastSeen = DateTime.now();
|
_lastSeen = DateTime.now();
|
||||||
await seenAll();
|
await seenAll();
|
||||||
} else {
|
} else {
|
||||||
@@ -77,13 +81,25 @@ class GradeProvider with ChangeNotifier {
|
|||||||
|
|
||||||
// good student mode, renamed subjects
|
// good student mode, renamed subjects
|
||||||
Future<void> convertBySettings() async {
|
Future<void> convertBySettings() async {
|
||||||
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled ? await _database.userQuery.renamedSubjects(userId: _user.user!.id) : {};
|
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
|
||||||
|
? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
|
||||||
|
: {};
|
||||||
|
|
||||||
for (Grade grade in _grades) {
|
for (Grade grade in _grades) {
|
||||||
grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
|
//grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
|
||||||
grade.value.value = _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
|
grade.subject.renamedTo = null;
|
||||||
grade.value.valueName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtek"] ?? "";
|
if (renamedSubjects.isNotEmpty) {
|
||||||
grade.value.shortName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtekelesRovidNev"] ?? "";
|
grade.subject.name =
|
||||||
|
renamedSubjects[grade.subject.id] ?? grade.subject.name;
|
||||||
|
}
|
||||||
|
grade.value.value =
|
||||||
|
_settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
|
||||||
|
grade.value.valueName = _settings.goodStudent
|
||||||
|
? "Jeles".i18n
|
||||||
|
: grade.json!["SzovegesErtek"].i18n ?? "";
|
||||||
|
grade.value.shortName = _settings.goodStudent
|
||||||
|
? "Jeles".i18n
|
||||||
|
: grade.json!["SzovegesErtekelesRovidNev"].i18n ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -102,12 +118,16 @@ class GradeProvider with ChangeNotifier {
|
|||||||
if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
|
if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
|
||||||
|
|
||||||
List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
|
List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
|
||||||
if (groupsJson == null || groupsJson.isEmpty) throw "Cannot fetch Groups for User ${user.id}";
|
if (groupsJson == null || groupsJson.isEmpty)
|
||||||
|
throw "Cannot fetch Groups for User ${user.id}";
|
||||||
_groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
|
_groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
|
||||||
|
|
||||||
List? groupAvgJson = await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
|
List? groupAvgJson =
|
||||||
if (groupAvgJson == null) throw "Cannot fetch Class Averages for User ${user.id}";
|
await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
|
||||||
final groupAvgs = groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
|
if (groupAvgJson == null)
|
||||||
|
throw "Cannot fetch Class Averages for User ${user.id}";
|
||||||
|
final groupAvgs =
|
||||||
|
groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
|
||||||
await storeGroupAvg(groupAvgs);
|
await storeGroupAvg(groupAvgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
filcnaplo_kreta_api/lib/providers/grade_provider.i18n.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
|
extension Localization on String {
|
||||||
|
static final _t = Translations.byLocale("hu_hu") +
|
||||||
|
{
|
||||||
|
"en_en": {
|
||||||
|
"Elégtelen": "Fail",
|
||||||
|
"Elégséges": "Warning but passing",
|
||||||
|
"Közepes": "Passed",
|
||||||
|
"Jó": "Good",
|
||||||
|
"Jeles": "Excellent"
|
||||||
|
},
|
||||||
|
"hu_hu": {
|
||||||
|
"Elégtelen": "Elégtelen",
|
||||||
|
"Elégséges": "Elégséges",
|
||||||
|
"Közepes": "Közepes",
|
||||||
|
"Jó": "Jó",
|
||||||
|
"Jeles": "Jeles"
|
||||||
|
},
|
||||||
|
"de_de": {
|
||||||
|
"Elégtelen": "Ungenügend",
|
||||||
|
"Elégséges": "Mangelhaft",
|
||||||
|
"Közepes": "Ausreichend",
|
||||||
|
"Jó": "Befriedigend",
|
||||||
|
"Jeles": "Gut"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -6,7 +6,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
|
||||||
class HomeworkTile extends StatelessWidget {
|
class HomeworkTile extends StatelessWidget {
|
||||||
const HomeworkTile(this.homework, {Key? key, this.onTap, this.padding, this.censored = false}) : super(key: key);
|
const HomeworkTile(this.homework,
|
||||||
|
{Key? key, this.onTap, this.padding, this.censored = false})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Homework homework;
|
final Homework homework;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
@@ -24,7 +26,8 @@ class HomeworkTile extends StatelessWidget {
|
|||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
|
shape:
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
|
||||||
leading: SizedBox(
|
leading: SizedBox(
|
||||||
width: 44,
|
width: 44,
|
||||||
height: 44,
|
height: 44,
|
||||||
@@ -38,7 +41,8 @@ class HomeworkTile extends StatelessWidget {
|
|||||||
: Padding(
|
: Padding(
|
||||||
padding: const EdgeInsets.only(top: 2.0),
|
padding: const EdgeInsets.only(top: 2.0),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
SubjectIcon.resolveVariant(subjectName: homework.subjectName, context: context),
|
SubjectIcon.resolveVariant(
|
||||||
|
subjectName: homework.subjectName, context: context),
|
||||||
size: 28.0,
|
size: 28.0,
|
||||||
color: AppColors.of(context).text.withOpacity(.75),
|
color: AppColors.of(context).text.withOpacity(.75),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
|||||||
import 'package:filcnaplo_mobile_ui/screens/news/news_tile.dart';
|
import 'package:filcnaplo_mobile_ui/screens/news/news_tile.dart';
|
||||||
import 'package:filcnaplo/models/news.dart';
|
import 'package:filcnaplo/models/news.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart';
|
import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/news_provider.dart';
|
import 'package:filcnaplo/api/providers/news_provider.dart';
|
||||||
@@ -24,24 +25,28 @@ class NewsScreen extends StatelessWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
leading: BackButton(color: AppColors.of(context).text),
|
leading: BackButton(color: AppColors.of(context).text),
|
||||||
title: Text("News", style: TextStyle(color: AppColors.of(context).text)),
|
title: Text("news".i18n,
|
||||||
|
style: TextStyle(color: AppColors.of(context).text)),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: RefreshIndicator(
|
child: RefreshIndicator(
|
||||||
onRefresh: () => newsProvider.fetch(),
|
onRefresh: () => newsProvider.fetch(),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
physics: const BouncingScrollPhysics(
|
||||||
|
parent: AlwaysScrollableScrollPhysics()),
|
||||||
itemCount: max(news.length, 1),
|
itemCount: max(news.length, 1),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (news.isNotEmpty) {
|
if (news.isNotEmpty) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24.0, vertical: 12.0),
|
||||||
child: Panel(
|
child: Panel(
|
||||||
child: Material(
|
child: Material(
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: NewsTile(
|
child: NewsTile(
|
||||||
news[index],
|
news[index],
|
||||||
onTap: () => NewsView.show(news[index], context: context, force: true),
|
onTap: () => NewsView.show(news[index],
|
||||||
|
context: context, force: true),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ import 'package:filcnaplo/utils/format.dart';
|
|||||||
import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
|
||||||
|
|
||||||
class SettingsHelper {
|
class SettingsHelper {
|
||||||
static const Map<String, String> langMap = {"en": "🇬🇧 English", "hu": "🇭🇺 Magyar", "de": "🇩🇪 Deutsch"};
|
static const Map<String, String> langMap = {
|
||||||
|
"en": "🇬🇧 English",
|
||||||
|
"hu": "🇭🇺 Magyar",
|
||||||
|
"de": "🇩🇪 Deutsch"
|
||||||
|
};
|
||||||
|
|
||||||
static const Map<Pages, String> pageTitle = {
|
static const Map<Pages, String> pageTitle = {
|
||||||
Pages.home: "home",
|
Pages.home: "home",
|
||||||
@@ -47,9 +51,11 @@ class SettingsHelper {
|
|||||||
VibrationStrength.strong: "vstrong",
|
VibrationStrength.strong: "vstrong",
|
||||||
};
|
};
|
||||||
|
|
||||||
static Map<Pages, String> localizedPageTitles() => pageTitle.map((key, value) => MapEntry(key, ScreensLocalization(value).i18n));
|
static Map<Pages, String> localizedPageTitles() => pageTitle
|
||||||
|
.map((key, value) => MapEntry(key, ScreensLocalization(value).i18n));
|
||||||
static Map<VibrationStrength, String> localizedVibrationTitles() =>
|
static Map<VibrationStrength, String> localizedVibrationTitles() =>
|
||||||
vibrationTitle.map((key, value) => MapEntry(key, SettingsLocalization(value).i18n));
|
vibrationTitle
|
||||||
|
.map((key, value) => MapEntry(key, SettingsLocalization(value).i18n));
|
||||||
|
|
||||||
static void language(BuildContext context) {
|
static void language(BuildContext context) {
|
||||||
showBottomSheetMenu(
|
showBottomSheetMenu(
|
||||||
@@ -58,7 +64,8 @@ class SettingsHelper {
|
|||||||
String lang = langMap.keys.toList()[index];
|
String lang = langMap.keys.toList()[index];
|
||||||
return BottomSheetMenuItem(
|
return BottomSheetMenuItem(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Provider.of<SettingsProvider>(context, listen: false).update(language: lang);
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.update(language: lang);
|
||||||
I18n.of(context).locale = Locale(lang, lang.toUpperCase());
|
I18n.of(context).locale = Locale(lang, lang.toUpperCase());
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
if (Platform.isAndroid || Platform.isIOS) {
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
@@ -81,6 +88,19 @@ class SettingsHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void uwuMode(BuildContext context, value) {
|
||||||
|
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
if (value) {
|
||||||
|
I18n.of(context).locale = const Locale('uw', 'UW');
|
||||||
|
} else {
|
||||||
|
I18n.of(context).locale =
|
||||||
|
Locale(settings.language, settings.language.toUpperCase());
|
||||||
|
}
|
||||||
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
|
setupQuickActions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void iconPack(BuildContext context) {
|
static void iconPack(BuildContext context) {
|
||||||
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
showBottomSheetMenu(
|
showBottomSheetMenu(
|
||||||
@@ -122,16 +142,20 @@ class SettingsHelper {
|
|||||||
items: List.generate(Pages.values.length, (index) {
|
items: List.generate(Pages.values.length, (index) {
|
||||||
return BottomSheetMenuItem(
|
return BottomSheetMenuItem(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Provider.of<SettingsProvider>(context, listen: false).update(startPage: Pages.values[index]);
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.update(startPage: Pages.values[index]);
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
},
|
},
|
||||||
title: Row(
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(pageIcons[Pages.values[index]], size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
Icon(pageIcons[Pages.values[index]],
|
||||||
|
size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
||||||
const SizedBox(width: 16.0),
|
const SizedBox(width: 16.0),
|
||||||
Text(localizedPageTitles()[Pages.values[index]] ?? ""),
|
Text(localizedPageTitles()[Pages.values[index]] ?? ""),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
if (Pages.values[index] == Provider.of<SettingsProvider>(context, listen: false).startPage)
|
if (Pages.values[index] ==
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.startPage)
|
||||||
Icon(
|
Icon(
|
||||||
Icons.check_circle,
|
Icons.check_circle,
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
@@ -165,7 +189,8 @@ class SettingsHelper {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 16.0),
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
child: Icon(FeatherIcons.smartphone, size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
child: Icon(FeatherIcons.smartphone,
|
||||||
|
size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
||||||
),
|
),
|
||||||
Text(SettingsLocalization("system").i18n),
|
Text(SettingsLocalization("system").i18n),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
@@ -183,7 +208,8 @@ class SettingsHelper {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 16.0),
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
child: Icon(FeatherIcons.sun, size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
child: Icon(FeatherIcons.sun,
|
||||||
|
size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
||||||
),
|
),
|
||||||
Text(SettingsLocalization("light").i18n),
|
Text(SettingsLocalization("light").i18n),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
@@ -201,7 +227,8 @@ class SettingsHelper {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 16.0),
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
child: Icon(FeatherIcons.moon, size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
child: Icon(FeatherIcons.moon,
|
||||||
|
size: 20.0, color: Theme.of(context).colorScheme.secondary),
|
||||||
),
|
),
|
||||||
Text(SettingsLocalization("dark").i18n),
|
Text(SettingsLocalization("dark").i18n),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
@@ -219,7 +246,8 @@ class SettingsHelper {
|
|||||||
static void accentColor(BuildContext context) {
|
static void accentColor(BuildContext context) {
|
||||||
Navigator.of(context, rootNavigator: true).push(
|
Navigator.of(context, rootNavigator: true).push(
|
||||||
PageRouteBuilder(
|
PageRouteBuilder(
|
||||||
pageBuilder: (context, _, __) => const PremiumCustomAccentColorSetting(),
|
pageBuilder: (context, _, __) =>
|
||||||
|
const PremiumCustomAccentColorSetting(),
|
||||||
transitionDuration: Duration.zero,
|
transitionDuration: Duration.zero,
|
||||||
reverseTransitionDuration: Duration.zero,
|
reverseTransitionDuration: Duration.zero,
|
||||||
),
|
),
|
||||||
@@ -241,7 +269,8 @@ class SettingsHelper {
|
|||||||
|
|
||||||
return BottomSheetMenuItem(
|
return BottomSheetMenuItem(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Provider.of<SettingsProvider>(context, listen: false).update(vibrate: value);
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.update(vibrate: value);
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
},
|
},
|
||||||
title: Row(
|
title: Row(
|
||||||
@@ -250,14 +279,18 @@ class SettingsHelper {
|
|||||||
width: 12.0,
|
width: 12.0,
|
||||||
height: 12.0,
|
height: 12.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.secondary.withOpacity((index + 1) / (vibrationTitle.length + 1)),
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondary
|
||||||
|
.withOpacity((index + 1) / (vibrationTitle.length + 1)),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16.0),
|
const SizedBox(width: 16.0),
|
||||||
Text(localizedVibrationTitles()[value] ?? "?"),
|
Text(localizedVibrationTitles()[value] ?? "?"),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
if (value == Provider.of<SettingsProvider>(context, listen: false).vibrate)
|
if (value ==
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false).vibrate)
|
||||||
Icon(
|
Icon(
|
||||||
Icons.check_circle,
|
Icons.check_circle,
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
@@ -291,7 +324,8 @@ class _RoundingSettingState extends State<RoundingSetting> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
rounding = Provider.of<SettingsProvider>(context, listen: false).rounding / 10;
|
rounding =
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false).rounding / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -336,12 +370,14 @@ class _RoundingSettingState extends State<RoundingSetting> {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Text("4.5", style: TextStyle(fontSize: 26.0, fontWeight: FontWeight.w500)),
|
const Text("4.5",
|
||||||
|
style: TextStyle(fontSize: 26.0, fontWeight: FontWeight.w500)),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24.0),
|
padding: EdgeInsets.symmetric(horizontal: 24.0),
|
||||||
child: Icon(FeatherIcons.arrowRight, color: Colors.grey),
|
child: Icon(FeatherIcons.arrowRight, color: Colors.grey),
|
||||||
),
|
),
|
||||||
GradeValueWidget(GradeValue(roundingResult, "", "", 100), fill: true, size: 32.0),
|
GradeValueWidget(GradeValue(roundingResult, "", "", 100),
|
||||||
|
fill: true, size: 32.0),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
@@ -349,7 +385,8 @@ class _RoundingSettingState extends State<RoundingSetting> {
|
|||||||
child: MaterialActionButton(
|
child: MaterialActionButton(
|
||||||
child: Text(SettingsLocalization("done").i18n),
|
child: Text(SettingsLocalization("done").i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Provider.of<SettingsProvider>(context, listen: false).update(rounding: (rounding * 10).toInt());
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.update(rounding: (rounding * 10).toInt());
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -367,15 +404,24 @@ class BellDelaySetting extends StatefulWidget {
|
|||||||
State<BellDelaySetting> createState() => _BellDelaySettingState();
|
State<BellDelaySetting> createState() => _BellDelaySettingState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BellDelaySettingState extends State<BellDelaySetting> with SingleTickerProviderStateMixin {
|
class _BellDelaySettingState extends State<BellDelaySetting>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
late TabController _tabController;
|
late TabController _tabController;
|
||||||
late Duration currentDelay;
|
late Duration currentDelay;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_tabController = TabController(length: 2, vsync: this, initialIndex: Provider.of<SettingsProvider>(context, listen: false).bellDelay > 0 ? 1 : 0);
|
_tabController = TabController(
|
||||||
currentDelay = Duration(seconds: Provider.of<SettingsProvider>(context, listen: false).bellDelay);
|
length: 2,
|
||||||
|
vsync: this,
|
||||||
|
initialIndex:
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false).bellDelay > 0
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
|
currentDelay = Duration(
|
||||||
|
seconds:
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false).bellDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -416,7 +462,10 @@ class _BellDelaySettingState extends State<BellDelaySetting> with SingleTickerPr
|
|||||||
),
|
),
|
||||||
Text(SettingsLocalization("sync_help").i18n,
|
Text(SettingsLocalization("sync_help").i18n,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(.75))),
|
style: TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.75))),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 12.0, top: 6.0),
|
padding: const EdgeInsets.only(bottom: 12.0, top: 6.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -425,21 +474,25 @@ class _BellDelaySettingState extends State<BellDelaySetting> with SingleTickerPr
|
|||||||
backgroundColor: AppColors.of(context).filc,
|
backgroundColor: AppColors.of(context).filc,
|
||||||
child: Text(SettingsLocalization("sync").i18n),
|
child: Text(SettingsLocalization("sync").i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final lessonProvider = Provider.of<TimetableProvider>(context, listen: false);
|
final lessonProvider =
|
||||||
|
Provider.of<TimetableProvider>(context, listen: false);
|
||||||
|
|
||||||
Duration? closest;
|
Duration? closest;
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
for (var lesson in lessonProvider.getWeek(Week.current()) ?? []) {
|
for (var lesson
|
||||||
|
in lessonProvider.getWeek(Week.current()) ?? []) {
|
||||||
Duration sdiff = lesson.start.difference(now);
|
Duration sdiff = lesson.start.difference(now);
|
||||||
Duration ediff = lesson.end.difference(now);
|
Duration ediff = lesson.end.difference(now);
|
||||||
|
|
||||||
if (closest == null || sdiff.abs() < closest.abs()) closest = sdiff;
|
if (closest == null || sdiff.abs() < closest.abs())
|
||||||
|
closest = sdiff;
|
||||||
if (ediff.abs() < closest.abs()) closest = ediff;
|
if (ediff.abs() < closest.abs()) closest = ediff;
|
||||||
}
|
}
|
||||||
if (closest != null) {
|
if (closest != null) {
|
||||||
if (closest.inHours.abs() >= 1) return;
|
if (closest.inHours.abs() >= 1) return;
|
||||||
currentDelay = closest;
|
currentDelay = closest;
|
||||||
Provider.of<SettingsProvider>(context, listen: false).update(bellDelay: currentDelay.inSeconds);
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.update(bellDelay: currentDelay.inSeconds);
|
||||||
_tabController.index = currentDelay.inSeconds > 0 ? 1 : 0;
|
_tabController.index = currentDelay.inSeconds > 0 ? 1 : 0;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@@ -449,7 +502,8 @@ class _BellDelaySettingState extends State<BellDelaySetting> with SingleTickerPr
|
|||||||
child: Text(SettingsLocalization("done").i18n),
|
child: Text(SettingsLocalization("done").i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
//Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt());
|
//Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt());
|
||||||
Provider.of<SettingsProvider>(context, listen: false).update(bellDelay: currentDelay.inSeconds);
|
Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.update(bellDelay: currentDelay.inSeconds);
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -513,8 +567,11 @@ class _GradeColorsSettingState extends State<GradeColorsSetting> {
|
|||||||
children: [
|
children: [
|
||||||
MaterialActionButton(
|
MaterialActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
List<Color> colors = List.castFrom(settings.gradeColors);
|
List<Color> colors =
|
||||||
var defaultColors = SettingsProvider.defaultSettings().gradeColors;
|
List.castFrom(settings.gradeColors);
|
||||||
|
var defaultColors =
|
||||||
|
SettingsProvider.defaultSettings()
|
||||||
|
.gradeColors;
|
||||||
colors[index] = defaultColors[index];
|
colors[index] = defaultColors[index];
|
||||||
settings.update(gradeColors: colors);
|
settings.update(gradeColors: colors);
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
@@ -523,9 +580,11 @@ class _GradeColorsSettingState extends State<GradeColorsSetting> {
|
|||||||
),
|
),
|
||||||
MaterialActionButton(
|
MaterialActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
List<Color> colors = List.castFrom(settings.gradeColors);
|
List<Color> colors =
|
||||||
|
List.castFrom(settings.gradeColors);
|
||||||
colors[index] = currentColor.withAlpha(255);
|
colors[index] = currentColor.withAlpha(255);
|
||||||
settings.update(gradeColors: settings.gradeColors);
|
settings.update(
|
||||||
|
gradeColors: settings.gradeColors);
|
||||||
Navigator.of(context).maybePop();
|
Navigator.of(context).maybePop();
|
||||||
},
|
},
|
||||||
child: Text(SettingsLocalization("done").i18n),
|
child: Text(SettingsLocalization("done").i18n),
|
||||||
@@ -536,7 +595,8 @@ class _GradeColorsSettingState extends State<GradeColorsSetting> {
|
|||||||
]),
|
]),
|
||||||
).then((value) => setState(() {}));
|
).then((value) => setState(() {}));
|
||||||
},
|
},
|
||||||
child: GradeValueWidget(GradeValue(index + 1, "", "", 0), fill: true, size: 36.0),
|
child: GradeValueWidget(GradeValue(index + 1, "", "", 0),
|
||||||
|
fill: true, size: 36.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -51,11 +51,10 @@ class SettingsScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _SettingsScreenState extends State<SettingsScreen>
|
class _SettingsScreenState extends State<SettingsScreen>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
int devmodeCountdown = 3;
|
int devmodeCountdown = 5;
|
||||||
bool __ss = false; // secret settings
|
bool __ss = false; // secret settings
|
||||||
|
|
||||||
late Future<Map> futureRelease =
|
Future<Map>? futureRelease;
|
||||||
Provider.of<UpdateProvider>(context).installedVersion();
|
|
||||||
|
|
||||||
late UserProvider user;
|
late UserProvider user;
|
||||||
late UpdateProvider updateProvider;
|
late UpdateProvider updateProvider;
|
||||||
@@ -153,7 +152,9 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
futureRelease = Provider.of<UpdateProvider>(context).installedVersion();
|
futureRelease = Provider.of<UpdateProvider>(context).installedVersion();
|
||||||
|
});
|
||||||
_hideContainersController = AnimationController(
|
_hideContainersController = AnimationController(
|
||||||
vsync: this, duration: const Duration(milliseconds: 200));
|
vsync: this, duration: const Duration(milliseconds: 200));
|
||||||
}
|
}
|
||||||
@@ -528,14 +529,34 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
contentPadding: const EdgeInsets.only(left: 12.0),
|
contentPadding: const EdgeInsets.only(left: 12.0),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12.0)),
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
title: const Text("Presentation Mode",
|
title: Text("presentation".i18n,
|
||||||
style: TextStyle(fontWeight: FontWeight.w500)),
|
style:
|
||||||
|
const TextStyle(fontWeight: FontWeight.w500)),
|
||||||
onChanged: (v) =>
|
onChanged: (v) =>
|
||||||
settings.update(presentationMode: v),
|
settings.update(presentationMode: v),
|
||||||
value: settings.presentationMode,
|
value: settings.presentationMode,
|
||||||
activeColor: Theme.of(context).colorScheme.secondary,
|
activeColor: Theme.of(context).colorScheme.secondary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// UwU-fied mode (why????)
|
||||||
|
// Material(
|
||||||
|
// type: MaterialType.transparency,
|
||||||
|
// child: SwitchListTile(
|
||||||
|
// contentPadding: const EdgeInsets.only(left: 12.0),
|
||||||
|
// shape: RoundedRectangleBorder(
|
||||||
|
// borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
// title: Text("uwufymode".i18n,
|
||||||
|
// style:
|
||||||
|
// const TextStyle(fontWeight: FontWeight.w500)),
|
||||||
|
// onChanged: (v) {
|
||||||
|
// SettingsHelper.uwuMode(context, v);
|
||||||
|
// setState(() {});
|
||||||
|
// },
|
||||||
|
// value: settings.presentationMode,
|
||||||
|
// activeColor: Theme.of(context).colorScheme.secondary,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ extension SettingsLocalization on String {
|
|||||||
"Background Color": "Background Color",
|
"Background Color": "Background Color",
|
||||||
"Highlight Color": "Highlight Color",
|
"Highlight Color": "Highlight Color",
|
||||||
"Adaptive Theme": "Adaptive Theme",
|
"Adaptive Theme": "Adaptive Theme",
|
||||||
|
"presentation": "Presentation mode",
|
||||||
|
"uwufymode": "UwU-fied mode (hungarian)",
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"personal_details": "Személyes információk",
|
"personal_details": "Személyes információk",
|
||||||
@@ -126,6 +128,8 @@ extension SettingsLocalization on String {
|
|||||||
"Background Color": "Háttér színe",
|
"Background Color": "Háttér színe",
|
||||||
"Highlight Color": "Panelek színe",
|
"Highlight Color": "Panelek színe",
|
||||||
"Adaptive Theme": "Adaptív téma",
|
"Adaptive Theme": "Adaptív téma",
|
||||||
|
"presentation": "Bemutató mód",
|
||||||
|
"uwufymode": "UwU mód (magyar)",
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"personal_details": "Persönliche Angaben",
|
"personal_details": "Persönliche Angaben",
|
||||||
@@ -187,6 +191,8 @@ extension SettingsLocalization on String {
|
|||||||
"Background Color": "Background Color",
|
"Background Color": "Background Color",
|
||||||
"Highlight Color": "Highlight Color",
|
"Highlight Color": "Highlight Color",
|
||||||
"Adaptive Theme": "Adaptive Theme",
|
"Adaptive Theme": "Adaptive Theme",
|
||||||
|
"presentation": "Präsentationsmodus",
|
||||||
|
"uwufymode": "UwU-Modus (ungarisch)",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:i18n_extension/i18n_widget.dart';
|
import 'package:i18n_extension/i18n_widget.dart';
|
||||||
|
|
||||||
class PremiumFSTimetable extends StatefulWidget {
|
class PremiumFSTimetable extends StatefulWidget {
|
||||||
const PremiumFSTimetable({Key? key, required this.controller}) : super(key: key);
|
const PremiumFSTimetable({Key? key, required this.controller})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final TimetableController controller;
|
final TimetableController controller;
|
||||||
|
|
||||||
@@ -45,16 +46,21 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
final everyLesson = days.expand((x) => x).toList();
|
final everyLesson = days.expand((x) => x).toList();
|
||||||
everyLesson.sort((a, b) => a.start.compareTo(b.start));
|
everyLesson.sort((a, b) => a.start.compareTo(b.start));
|
||||||
|
|
||||||
final int maxLessonCount = days.fold(0, (a, b) => math.max(a, b.where((l) => l.subject.id != "" || l.isEmpty).length));
|
final int maxLessonCount = days.fold(
|
||||||
|
0,
|
||||||
|
(a, b) => math.max(
|
||||||
|
a, b.where((l) => l.subject.id != "" || l.isEmpty).length));
|
||||||
|
|
||||||
final int minIndex = int.tryParse(everyLesson.first.lessonIndex) ?? 0;
|
final int minIndex = int.tryParse(everyLesson.first.lessonIndex) ?? 0;
|
||||||
final int maxIndex = int.tryParse(everyLesson.last.lessonIndex) ?? maxLessonCount;
|
final int maxIndex =
|
||||||
|
int.tryParse(everyLesson.last.lessonIndex) ?? maxLessonCount;
|
||||||
|
|
||||||
const prefixw = 40;
|
const prefixw = 40;
|
||||||
const padding = prefixw + 6 * 2;
|
const padding = prefixw + 6 * 2;
|
||||||
final colw = (MediaQuery.of(context).size.width - padding) / days.length;
|
final colw = (MediaQuery.of(context).size.width - padding) / days.length;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
appBar: buildAppBar(),
|
||||||
body: ListView.builder(
|
body: ListView.builder(
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 24.0),
|
padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 24.0),
|
||||||
@@ -63,7 +69,10 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
List<Widget> columns = [];
|
List<Widget> columns = [];
|
||||||
|
|
||||||
for (int dayIndex = -1; dayIndex < days.length; dayIndex++) {
|
for (int dayIndex = -1; dayIndex < days.length; dayIndex++) {
|
||||||
final dayOffset = dayIndex == -1 ? 0 : (int.tryParse(days[dayIndex].first.lessonIndex) ?? 0) - minIndex;
|
final dayOffset = dayIndex == -1
|
||||||
|
? 0
|
||||||
|
: (int.tryParse(days[dayIndex].first.lessonIndex) ?? 0) -
|
||||||
|
minIndex;
|
||||||
final lessonIndex = index - 1;
|
final lessonIndex = index - 1;
|
||||||
|
|
||||||
if (dayIndex == -1) {
|
if (dayIndex == -1) {
|
||||||
@@ -75,7 +84,9 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"${minIndex + lessonIndex}.",
|
"${minIndex + lessonIndex}.",
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.secondary),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).colorScheme.secondary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@@ -85,12 +96,15 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final lessons = days[dayIndex].where((l) => l.subject.id != "" || l.isEmpty).toList();
|
final lessons = days[dayIndex]
|
||||||
|
.where((l) => l.subject.id != "" || l.isEmpty)
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (lessons.isEmpty) continue;
|
if (lessons.isEmpty) continue;
|
||||||
if (lessonIndex >= lessons.length) continue;
|
if (lessonIndex >= lessons.length) continue;
|
||||||
|
|
||||||
if (dayIndex >= days.length || (lessonIndex + dayOffset) >= lessons.length) {
|
if (dayIndex >= days.length ||
|
||||||
|
(lessonIndex + dayOffset) >= lessons.length) {
|
||||||
columns.add(SizedBox(width: colw));
|
columns.add(SizedBox(width: colw));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -100,8 +114,11 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
width: colw,
|
width: colw,
|
||||||
height: 40.0,
|
height: 40.0,
|
||||||
child: Text(
|
child: Text(
|
||||||
DateFormat("EEEE", I18n.of(context).locale.languageCode).format(lessons.first.date).capital(),
|
DateFormat("EEEE", I18n.of(context).locale.languageCode)
|
||||||
style: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
|
.format(lessons.first.date)
|
||||||
|
.capital(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 24.0, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
@@ -113,11 +130,14 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Icon(FeatherIcons.slash, size: 18.0, color: AppColors.of(context).text.withOpacity(.3)),
|
Icon(FeatherIcons.slash,
|
||||||
|
size: 18.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.3)),
|
||||||
const SizedBox(width: 8.0),
|
const SizedBox(width: 8.0),
|
||||||
Text(
|
Text(
|
||||||
"Lyukas óra",
|
"Lyukas óra",
|
||||||
style: TextStyle(color: AppColors.of(context).text.withOpacity(.3)),
|
style: TextStyle(
|
||||||
|
color: AppColors.of(context).text.withOpacity(.3)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -139,16 +159,27 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
SubjectIcon.resolveVariant(context: context, subject: lessons[lessonIndex - dayOffset].subject),
|
SubjectIcon.resolveVariant(
|
||||||
|
context: context,
|
||||||
|
subject: lessons[lessonIndex - dayOffset].subject),
|
||||||
size: 18.0,
|
size: 18.0,
|
||||||
color: AppColors.of(context).text.withOpacity(.7),
|
color: AppColors.of(context).text.withOpacity(.7),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8.0),
|
const SizedBox(width: 8.0),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
lessons[lessonIndex - dayOffset].subject.renamedTo ?? lessons[lessonIndex - dayOffset].subject.name.capital(),
|
lessons[lessonIndex - dayOffset].subject.renamedTo ??
|
||||||
|
lessons[lessonIndex - dayOffset]
|
||||||
|
.subject
|
||||||
|
.name
|
||||||
|
.capital(),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: TextStyle(fontStyle: lessons[lessonIndex - dayOffset].subject.isRenamed ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontStyle: lessons[lessonIndex - dayOffset]
|
||||||
|
.subject
|
||||||
|
.isRenamed
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
overflow: TextOverflow.clip,
|
overflow: TextOverflow.clip,
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
),
|
),
|
||||||
@@ -160,7 +191,9 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
padding: const EdgeInsets.only(left: 26.0),
|
padding: const EdgeInsets.only(left: 26.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
lessons[lessonIndex - dayOffset].room,
|
lessons[lessonIndex - dayOffset].room,
|
||||||
style: TextStyle(color: AppColors.of(context).text.withOpacity(.5), overflow: TextOverflow.ellipsis),
|
style: TextStyle(
|
||||||
|
color: AppColors.of(context).text.withOpacity(.5),
|
||||||
|
overflow: TextOverflow.ellipsis),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -176,4 +209,14 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AppBar buildAppBar() {
|
||||||
|
return AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
actions: const [
|
||||||
|
BackButton(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||