Compare commits

...

34 Commits
4.0.2 ... 4.0.4

Author SHA1 Message Date
Márton Kiss
e31d0753d1 Merge pull request #8 from TMarccci/master
I think I fixed this
2023-06-09 16:55:05 +02:00
Tihanyi Marcell
526c66f358 I think I fixed this 2023-06-09 16:53:28 +02:00
Kima
d6833a952d changed version string 2023-06-09 16:40:53 +02:00
Kima
4760761bb7 Merge branch 'master' of github.com:refilc/naplo 2023-06-09 16:25:34 +02:00
Kima
a33e6dae3b fixed auto-update error bug 2023-06-09 16:25:31 +02:00
Márton Kiss
d393181f10 Update grade_provider.dart 2023-06-09 16:06:17 +02:00
Márton Kiss
12df8b82c7 Merge pull request #7 from TMarccci/master
Handle disabled Live Activity, i18n AverageSelector won't update, ...
2023-06-09 16:02:05 +02:00
Tihanyi Marcell
1c7eba7af3 Appgroup id: not refilc2 2023-06-09 15:44:37 +02:00
Tihanyi Marcell
d39cdaef10 Fixed i18n wont update to AverageSelector 2023-06-09 14:22:15 +02:00
Tihanyi Marcell
cc40fb9c0f Ignore disabled live activity 2023-06-09 11:13:35 +02:00
Tihanyi Marcell
85c6d548ad Ignore null and - i18n 2023-06-09 11:08:00 +02:00
Kima
8dbf605450 added black accent color 2023-06-08 21:28:28 +02:00
Kima
2f418a7c1a updated version string 2023-06-08 21:19:46 +02:00
Kima
5f0c82f54c added grade value translations 2023-06-08 21:18:20 +02:00
Kima
4e659308e5 fixed subject rename at homeworks 2023-06-08 20:38:10 +02:00
Kima
50e24bde17 added disable fading to all filter/tab bars 2023-06-08 20:07:17 +02:00
Márton Kiss
31f7c6a465 Merge pull request #6 from Monke14/bug-fixes
some fixes - by Monke14
2023-06-08 20:01:22 +02:00
Márton Kiss
e734579249 Merge branch 'master' into bug-fixes 2023-06-08 19:59:57 +02:00
Márton Kiss
2cff46d628 Merge pull request #5 from TMarccci/master
fixed lot of things - by TMarccci
2023-06-08 19:56:35 +02:00
Kima
87f3f93177 started creating end-year summary and stb 2023-06-08 19:53:50 +02:00
hihihaha
30733caa4a remove home screen tabbar fade 2023-06-08 16:18:39 +02:00
hihihaha
4e30a550e1 fix chart overflow 2023-06-08 16:18:08 +02:00
hihihaha
cb687d6b10 add themed icon 2023-06-08 16:17:56 +02:00
hihihaha
6c6d3a7cd8 fix english translations 2023-06-08 16:17:46 +02:00
Tihanyi Marcell
da06e400e1 Login add " ", Comment rename 2023-06-08 13:47:40 +02:00
Tihanyi Marcell
87b8cbb60f HotFix 2023-06-08 12:59:09 +02:00
Tihanyi Marcell
8bac300585 goalPlanner remove 2023-06-08 12:54:46 +02:00
Tihanyi Marcell
da7d2b9333 Fixed: Settings UI, Live Act, Class Avg 2023-06-08 12:44:47 +02:00
Kima
e1f84caf19 changed refilc bday strings 2023-06-07 21:27:56 +02:00
Kima
274da2b766 ok 2023-06-07 21:21:35 +02:00
Kima
35aba35801 Merge branch 'master' of github.com:refilc/naplo 2023-06-07 20:50:48 +02:00
Kima
964e002c46 added og filc color to accents 2023-06-07 20:50:45 +02:00
Márton Kiss
d3318e10ab fixed download counter in readme 2023-06-07 20:22:41 +02:00
Kima
4c43369d59 updated version string 2023-06-07 19:22:55 +02:00
43 changed files with 502 additions and 274 deletions

2
.gitignore vendored
View File

@@ -48,3 +48,5 @@ filcnaplo/linux/flutter/generated_plugin_registrant.cc
filcnaplo/linux/flutter/generated_plugin_registrant.h filcnaplo/linux/flutter/generated_plugin_registrant.h
filcnaplo/linux/flutter/generated_plugins.cmake filcnaplo/linux/flutter/generated_plugins.cmake
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
.vscode/

2
.vscode/launch.json vendored
View File

@@ -27,7 +27,7 @@
"cwd": "filcnaplo", "cwd": "filcnaplo",
"request": "launch", "request": "launch",
"type": "dart", "type": "dart",
"flutterMode": "release" "flutterMode": "debug"
} }
] ]
} }

View File

@@ -5,7 +5,7 @@
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez - tanulóktól, tanulóknak. #### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez - tanulóktól, tanulóknak.
[![Downloads](https://img.shields.io/github/downloads-pre/refilc/naplo/latest/total?color=%23&label=Downloads&logo=github&sort=semver)](https://github.com/refilc/naplo/releases)   [![discord](https://img.shields.io/discord/1111649116020285532?label=Discord)](http://dc.refilc.hu) [![Downloads](https://img.shields.io/github/downloads-pre/refilc/naplo/total?color=%23&label=Downloads&logo=github&sort=semver)](https://github.com/refilc/naplo/releases)   [![discord](https://img.shields.io/discord/1111649116020285532?label=Discord)](http://dc.refilc.hu)
## Setup ## Setup

View File

@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon> </adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 916 B

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 KiB

View File

@@ -1,6 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "reFilc_Logo.png",
"idiom" : "universal", "idiom" : "universal",
"platform" : "ios", "platform" : "ios",
"size" : "1024x1024" "size" : "1024x1024"

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 KiB

View File

@@ -13,7 +13,7 @@ class LessonData {
var nextRoom: String var nextRoom: String
init?() { init?() {
let sharedDefault = UserDefaults(suiteName: "group.filcnaplo.livecard")! let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
self.icon = sharedDefault.string(forKey: "icon")! self.icon = sharedDefault.string(forKey: "icon")!
self.index = sharedDefault.string(forKey: "index")! self.index = sharedDefault.string(forKey: "index")!

View File

@@ -68,8 +68,6 @@ struct LockScreenLiveActivityView: View {
.monospacedDigit() .monospacedDigit()
.padding(.trailing, CGFloat(24)) .padding(.trailing, CGFloat(24))
} }
.activitySystemActionForegroundColor(.teal)
.activityBackgroundTint(.teal)
} }
} }

View File

@@ -57,14 +57,14 @@ Future loginApi({
String nonceStr = await Provider.of<KretaClient>(context, listen: false) String nonceStr = await Provider.of<KretaClient>(context, listen: false)
.getAPI(KretaAPI.nonce, json: false); .getAPI(KretaAPI.nonce, json: false);
Nonce nonce = getNonce(nonceStr, username, instituteCode); Nonce nonce = getNonce(nonceStr, username.replaceAll(' ', '') + ' ', instituteCode);
headers.addAll(nonce.header()); headers.addAll(nonce.header());
Map? res = await Provider.of<KretaClient>(context, listen: false) Map? res = await Provider.of<KretaClient>(context, listen: false)
.postAPI(KretaAPI.login, .postAPI(KretaAPI.login,
headers: headers, headers: headers,
body: User.loginBody( body: User.loginBody(
username: username, username: username.replaceAll(' ', '') + ' ',
password: password, password: password,
instituteCode: instituteCode, instituteCode: instituteCode,
)); ));
@@ -83,7 +83,7 @@ Future loginApi({
.getAPI(KretaAPI.student(instituteCode)); .getAPI(KretaAPI.student(instituteCode));
Student student = Student.fromJson(studentJson!); Student student = Student.fromJson(studentJson!);
var user = User( var user = User(
username: username, username: username.replaceAll(' ', '') + ' ',
password: password, password: password,
instituteCode: instituteCode, instituteCode: instituteCode,
name: student.name, name: student.name,

View File

@@ -44,10 +44,20 @@ class LiveCardProvider extends ChangeNotifier {
required SettingsProvider settings, required SettingsProvider settings,
}) : _timetable = timetable, }) : _timetable = timetable,
_settings = settings { _settings = settings {
_liveActivitiesPlugin.init(appGroupId: "group.filcnaplo.livecard"); // Check if live card is enabled .areActivitiesEnabled()
_liveActivitiesPlugin.getAllActivitiesIds().then((value) { _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
_latestActivityId = value.isNotEmpty ? value.first : null; // Console log
print("Live card enabled: $value");
if (value) {
_liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
_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 _delay = settings.bellDelayEnabled
? Duration(seconds: settings.bellDelay) ? Duration(seconds: settings.bellDelay)
@@ -58,8 +68,15 @@ class LiveCardProvider extends ChangeNotifier {
@override @override
void dispose() { void dispose() {
_timer.cancel(); _timer.cancel();
if (_latestActivityId != null && Platform.isIOS) if (Platform.isIOS) {
_liveActivitiesPlugin.endActivity(_latestActivityId!); _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
if (value) {
if (_latestActivityId != null) {
_liveActivitiesPlugin.endActivity(_latestActivityId!);
}
}
});
}
super.dispose(); super.dispose();
} }
@@ -146,30 +163,34 @@ class LiveCardProvider extends ChangeNotifier {
void update() async { void update() async {
if (Platform.isIOS) { if (Platform.isIOS) {
final cmap = toMap(); _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
if (!mapEquals(cmap, _lastActivity)) { if (value) {
_lastActivity = cmap; final cmap = toMap();
try { if (!mapEquals(cmap, _lastActivity)) {
if (_lastActivity.isNotEmpty) { _lastActivity = cmap;
if (_latestActivityId == null) { try {
_liveActivitiesPlugin if (_lastActivity.isNotEmpty) {
.createActivity(_lastActivity) if (_latestActivityId == null) {
.then((value) => _latestActivityId = value); _liveActivitiesPlugin
} else { .createActivity(_lastActivity)
_liveActivitiesPlugin.updateActivity( .then((value) => _latestActivityId = value);
_latestActivityId!, _lastActivity); } else {
_liveActivitiesPlugin.updateActivity(
_latestActivityId!, _lastActivity);
}
} else {
if (_latestActivityId != null) {
_liveActivitiesPlugin.endActivity(_latestActivityId!);
}
}
} catch (e) {
if (kDebugMode) {
print('ERROR: Unable to create or update iOS LiveCard!');
}
} }
} else {
if (_latestActivityId != null) {
_liveActivitiesPlugin.endActivity(_latestActivityId!);
}
}
} catch (e) {
if (kDebugMode) {
print('ERROR: Unable to create or update iOS LiveCard!');
} }
} }
} });
} }
List<Lesson> today = _today(_timetable); List<Lesson> today = _today(_timetable);

View File

@@ -19,13 +19,15 @@ extension UpdateHelper on Release {
updateCallback!(-1, UpdateState.preparing); updateCallback!(-1, UpdateState.preparing);
String downloads = await StorageHelper.downloadsPath(); String downloads = await StorageHelper.downloadsPath();
File apk = File("$downloads/filcnaplo-$version.apk"); File apk = File("$downloads/refilc-$version.apk");
if (!await apk.exists()) { if (!await apk.exists()) {
updateCallback(-1, UpdateState.downloading); updateCallback(-1, UpdateState.downloading);
var bytes = await download(updateCallback: updateCallback); var bytes = await download(updateCallback: updateCallback);
if (!await StorageHelper.write(apk.path, bytes)) throw "failed to write apk: permission denied"; if (!await StorageHelper.write(apk.path, bytes)) {
throw "failed to write apk: permission denied";
}
} }
updateCallback(-1, UpdateState.installing); updateCallback(-1, UpdateState.installing);
@@ -50,7 +52,8 @@ extension UpdateHelper on Release {
var completer = Completer<Uint8List>(); var completer = Completer<Uint8List>();
response?.stream.listen((List<int> chunk) { response?.stream.listen((List<int> chunk) {
updateCallback!(downloaded / (response.contentLength ?? 0), UpdateState.downloading); updateCallback!(
downloaded / (response.contentLength ?? 0), UpdateState.downloading);
chunks.add(chunk); chunks.add(chunk);
downloaded += chunk.length; downloaded += chunk.length;

View File

@@ -10,6 +10,8 @@ enum AccentColor {
red, red,
pink, pink,
purple, purple,
none,
ogfilc,
adaptive, adaptive,
custom custom
} }
@@ -24,6 +26,8 @@ Map<AccentColor, Color> accentColorMap = {
AccentColor.red: Colors.red.shade300, AccentColor.red: Colors.red.shade300,
AccentColor.pink: Colors.pink.shade300, AccentColor.pink: Colors.pink.shade300,
AccentColor.purple: Colors.purple.shade300, AccentColor.purple: Colors.purple.shade300,
//AccentColor.none: Colors.black,
AccentColor.ogfilc: const Color(0xff20AC9B),
AccentColor.adaptive: const Color(0xFF3D7BF4), AccentColor.adaptive: const Color(0xFF3D7BF4),
AccentColor.custom: const Color(0xFF3D7BF4), AccentColor.custom: const Color(0xFF3D7BF4),
}; };

View File

@@ -15,7 +15,8 @@ import 'package:provider/provider.dart';
import 'lesson_tile.i18n.dart'; import 'lesson_tile.i18n.dart';
class LessonTile extends StatelessWidget { class LessonTile extends StatelessWidget {
const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false}) : super(key: key); const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false})
: super(key: key);
final Lesson lesson; final Lesson lesson;
final bool swapDesc; final bool swapDesc;
@@ -34,7 +35,9 @@ class LessonTile extends StatelessWidget {
if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = "."; if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
var now = DateTime.now(); var now = DateTime.now();
if (lesson.start.isBefore(now) && lesson.end.isAfter(now) && lesson.status?.name != "Elmaradt") { if (lesson.start.isBefore(now) &&
lesson.end.isAfter(now) &&
lesson.status?.name != "Elmaradt") {
fillLeading = true; fillLeading = true;
} }
@@ -62,7 +65,8 @@ class LessonTile extends StatelessWidget {
if (lesson.homeworkId != "") { if (lesson.homeworkId != "") {
Homework homework = Provider.of<HomeworkProvider>(context, listen: false) Homework homework = Provider.of<HomeworkProvider>(context, listen: false)
.homework .homework
.firstWhere((h) => h.id == lesson.homeworkId, orElse: () => Homework.fromJson({})); .firstWhere((h) => h.id == lesson.homeworkId,
orElse: () => Homework.fromJson({}));
if (homework.id != "") { if (homework.id != "") {
subtiles.add(LessonSubtile( subtiles.add(LessonSubtile(
@@ -74,11 +78,16 @@ class LessonTile extends StatelessWidget {
} }
if (lesson.exam != "") { if (lesson.exam != "") {
Exam exam = Provider.of<ExamProvider>(context, listen: false).exams.firstWhere((t) => t.id == lesson.exam, orElse: () => Exam.fromJson({})); Exam exam = Provider.of<ExamProvider>(context, listen: false)
.exams
.firstWhere((t) => t.id == lesson.exam,
orElse: () => Exam.fromJson({}));
if (exam.id != "") { if (exam.id != "") {
subtiles.add(LessonSubtile( subtiles.add(LessonSubtile(
type: LessonSubtileType.exam, type: LessonSubtileType.exam,
title: exam.description != "" ? exam.description : exam.mode?.description ?? "exam".i18n, title: exam.description != ""
? exam.description
: exam.mode?.description ?? "exam".i18n,
onPressed: () => ExamView.show(exam, context: context), onPressed: () => ExamView.show(exam, context: context),
)); ));
} }
@@ -87,7 +96,10 @@ class LessonTile extends StatelessWidget {
String description = ''; String description = '';
String room = ''; String room = '';
final cleanDesc = lesson.description.specialChars().toLowerCase().replaceAll(lesson.subject.name.specialChars().toLowerCase(), ''); final cleanDesc = lesson.description
.specialChars()
.toLowerCase()
.replaceAll(lesson.subject.name.specialChars().toLowerCase(), '');
if (!swapDesc) { if (!swapDesc) {
if (cleanDesc != "") { if (cleanDesc != "") {
@@ -131,16 +143,23 @@ class LessonTile extends StatelessWidget {
// onLongPress: kDebugMode ? () => log(jsonEncode(lesson.json)) : null, // onLongPress: kDebugMode ? () => log(jsonEncode(lesson.json)) : null,
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
contentPadding: const EdgeInsets.symmetric(horizontal: 4.0), contentPadding: const EdgeInsets.symmetric(horizontal: 4.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)), shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
title: Text( title: Text(
!lesson.isEmpty ? lesson.subject.renamedTo ?? lesson.subject.name.capital() : "empty".i18n, !lesson.isEmpty
? lesson.subject.renamedTo ??
lesson.subject.name.capital()
: "empty".i18n,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 15.5, fontSize: 15.5,
color: AppColors.of(context).text.withOpacity(!lesson.isEmpty ? 1.0 : 0.5), color: AppColors.of(context)
fontStyle: lesson.subject.isRenamed ? FontStyle.italic : null), .text
.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
fontStyle:
lesson.subject.isRenamed ? FontStyle.italic : null),
), ),
subtitle: description != "" subtitle: description != ""
? Text( ? Text(
@@ -175,12 +194,20 @@ class LessonTile extends StatelessWidget {
offset: const Offset(-12.0, -2.0), offset: const Offset(-12.0, -2.0),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: fillLeading ? Theme.of(context).colorScheme.secondary.withOpacity(.3) : const Color(0x00000000), color: fillLeading
? Theme.of(context)
.colorScheme
.secondary
.withOpacity(.3)
: const Color(0x00000000),
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
boxShadow: [ boxShadow: [
if (fillLeading) if (fillLeading)
BoxShadow( BoxShadow(
color: Theme.of(context).colorScheme.secondary.withOpacity(.25), color: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.25),
blurRadius: 6.0, blurRadius: 6.0,
) )
], ],
@@ -210,7 +237,9 @@ class LessonTile extends StatelessWidget {
maxLines: 2, maxLines: 2,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.of(context).text.withOpacity(.75), color: AppColors.of(context)
.text
.withOpacity(.75),
), ),
), ),
), ),
@@ -225,7 +254,9 @@ class LessonTile extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.of(context).text.withOpacity(.9), color: AppColors.of(context)
.text
.withOpacity(.9),
), ),
), ),
], ],
@@ -249,7 +280,9 @@ class LessonTile extends StatelessWidget {
enum LessonSubtileType { homework, exam, absence } enum LessonSubtileType { homework, exam, absence }
class LessonSubtile extends StatelessWidget { class LessonSubtile extends StatelessWidget {
const LessonSubtile({Key? key, this.onPressed, required this.title, required this.type}) : super(key: key); const LessonSubtile(
{Key? key, this.onPressed, required this.title, required this.type})
: super(key: key);
final Function()? onPressed; final Function()? onPressed;
final String title; final String title;
@@ -285,7 +318,8 @@ class LessonSubtile extends StatelessWidget {
Center( Center(
child: SizedBox( child: SizedBox(
width: 30.0, width: 30.0,
child: Icon(icon, color: iconColor.withOpacity(.75), size: 20.0), child:
Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
), ),
), ),
Expanded( Expanded(
@@ -295,7 +329,9 @@ class LessonSubtile extends StatelessWidget {
title.escapeHtml(), title.escapeHtml(),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(.65)), style: TextStyle(
fontWeight: FontWeight.w500,
color: AppColors.of(context).text.withOpacity(.65)),
), ),
), ),
), ),

View File

@@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
homepage: https://refilc.hu homepage: https://refilc.hu
publish_to: "none" publish_to: "none"
version: 4.0.1+205 version: 4.0.4+212
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"

View File

@@ -169,7 +169,7 @@ class KretaClient {
Map? loginRes = await postAPI(KretaAPI.login, Map? loginRes = await postAPI(KretaAPI.login,
headers: headers, headers: headers,
body: User.loginBody( body: User.loginBody(
username: loginUser.username, username: loginUser.username.replaceAll(' ', '') + ' ',
password: loginUser.password, password: loginUser.password,
instituteCode: loginUser.instituteCode, instituteCode: loginUser.instituteCode,
)); ));

View File

@@ -1,5 +1,7 @@
import 'package:filcnaplo_kreta_api/client/api.dart'; import 'package:filcnaplo_kreta_api/client/api.dart';
import 'subject.dart';
class Homework { class Homework {
Map? json; Map? json;
DateTime date; DateTime date;
@@ -9,7 +11,7 @@ class Homework {
bool homeworkEnabled; bool homeworkEnabled;
String teacher; String teacher;
String content; String content;
String subjectName; Subject subject;
String group; String group;
List<HomeworkAttachment> attachments; List<HomeworkAttachment> attachments;
String id; String id;
@@ -22,7 +24,7 @@ class Homework {
required this.homeworkEnabled, required this.homeworkEnabled,
required this.teacher, required this.teacher,
required this.content, required this.content,
required this.subjectName, required this.subject,
required this.group, required this.group,
required this.attachments, required this.attachments,
required this.id, required this.id,
@@ -32,16 +34,27 @@ class Homework {
factory Homework.fromJson(Map json) { factory Homework.fromJson(Map json) {
return Homework( return Homework(
id: json["Uid"] ?? "", id: json["Uid"] ?? "",
date: json["RogzitesIdopontja"] != null ? DateTime.parse(json["RogzitesIdopontja"]).toLocal() : DateTime(0), date: json["RogzitesIdopontja"] != null
lessonDate: json["FeladasDatuma"] != null ? DateTime.parse(json["FeladasDatuma"]).toLocal() : DateTime(0), ? DateTime.parse(json["RogzitesIdopontja"]).toLocal()
deadline: json["HataridoDatuma"] != null ? DateTime.parse(json["HataridoDatuma"]).toLocal() : DateTime(0), : DateTime(0),
lessonDate: json["FeladasDatuma"] != null
? DateTime.parse(json["FeladasDatuma"]).toLocal()
: DateTime(0),
deadline: json["HataridoDatuma"] != null
? DateTime.parse(json["HataridoDatuma"]).toLocal()
: DateTime(0),
byTeacher: json["IsTanarRogzitette"] ?? true, byTeacher: json["IsTanarRogzitette"] ?? true,
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false, homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
teacher: (json["RogzitoTanarNeve"] ?? "").trim(), teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
content: (json["Szoveg"] ?? "").trim(), content: (json["Szoveg"] ?? "").trim(),
subjectName: json["TantargyNeve"] ?? "", subject: Subject.fromJson(json["Tantargy"] ?? {}),
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "", group: json["OsztalyCsoport"] != null
attachments: ((json["Csatolmanyok"] ?? []) as List).cast<Map>().map((Map json) => HomeworkAttachment.fromJson(json)).toList(), ? json["OsztalyCsoport"]["Uid"] ?? ""
: "",
attachments: ((json["Csatolmanyok"] ?? []) as List)
.cast<Map>()
.map((Map json) => HomeworkAttachment.fromJson(json))
.toList(),
json: json, json: json,
); );
} }
@@ -53,7 +66,8 @@ class HomeworkAttachment {
String name; String name;
String type; String type;
HomeworkAttachment({required this.id, this.name = "", this.type = "", this.json}); HomeworkAttachment(
{required this.id, this.name = "", this.type = "", this.json});
factory HomeworkAttachment.fromJson(Map json) { factory HomeworkAttachment.fromJson(Map json) {
return HomeworkAttachment( return HomeworkAttachment(
@@ -64,6 +78,8 @@ class HomeworkAttachment {
); );
} }
String downloadUrl(String iss) => KretaAPI.downloadHomeworkAttachments(iss, id, type); String downloadUrl(String iss) =>
bool get isImage => name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png"); KretaAPI.downloadHomeworkAttachments(iss, id, type);
bool get isImage =>
name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
} }

View File

@@ -86,20 +86,21 @@ class GradeProvider with ChangeNotifier {
: {}; : {};
for (Grade grade in _grades) { for (Grade grade in _grades) {
//grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null; grade.subject.renamedTo =
grade.subject.renamedTo = null; renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
if (renamedSubjects.isNotEmpty) {
grade.subject.name =
renamedSubjects[grade.subject.id] ?? grade.subject.name;
}
grade.value.value = grade.value.value =
_settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0; _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
grade.value.valueName = _settings.goodStudent grade.value.valueName = _settings.goodStudent
? "Jeles".i18n ? "Jeles".i18n
: grade.json!["SzovegesErtek"].i18n ?? ""; : '${grade.json!["SzovegesErtek"]}'
.replaceAll(RegExp(r'[(]+[12345]?[)]'), '')
.i18n;
grade.value.shortName = _settings.goodStudent grade.value.shortName = _settings.goodStudent
? "Jeles".i18n ? "Jeles".i18n
: grade.json!["SzovegesErtekelesRovidNev"].i18n ?? ""; : '${grade.json!["SzovegesErtekelesRovidNev"]}' != "null" && '${grade.json!["SzovegesErtekelesRovidNev"]}' != "-" && '${grade.json!["SzovegesErtekelesRovidNev"]}'.replaceAll(RegExp(r'[0123456789]+[%]?'), '') != ""
? '${grade.json!["SzovegesErtekelesRovidNev"]}'.i18n
: grade.value.valueName;
} }
notifyListeners(); notifyListeners();

View File

@@ -1,5 +1,6 @@
import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart';
import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/models/user.dart'; import 'package:filcnaplo/models/user.dart';
import 'package:filcnaplo_kreta_api/client/api.dart'; import 'package:filcnaplo_kreta_api/client/api.dart';
import 'package:filcnaplo_kreta_api/client/client.dart'; import 'package:filcnaplo_kreta_api/client/client.dart';
@@ -8,6 +9,12 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class HomeworkProvider with ChangeNotifier { class HomeworkProvider with ChangeNotifier {
// Private
late final SettingsProvider _settings;
late final UserProvider _user;
late final DatabaseProvider _database;
// Public
late List<Homework> _homework; late List<Homework> _homework;
late BuildContext _context; late BuildContext _context;
List<Homework> get homework => _homework; List<Homework> get homework => _homework;
@@ -27,25 +34,54 @@ class HomeworkProvider with ChangeNotifier {
// Load homework from the database // Load homework from the database
if (userId != null) { if (userId != null) {
var dbHomework = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getHomework(userId: userId); var dbHomework =
await Provider.of<DatabaseProvider>(_context, listen: false)
.userQuery
.getHomework(userId: userId);
_homework = dbHomework; _homework = dbHomework;
notifyListeners(); await convertBySettings();
} }
} }
Future<void> convertBySettings() async {
Map<String, String> renamedSubjects =
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
? await _database.userQuery.renamedSubjects(userId: _user.id!)
: {};
for (Homework homework in _homework) {
homework.subject.renamedTo = renamedSubjects.isNotEmpty
? renamedSubjects[homework.subject.id]
: null;
}
notifyListeners();
}
// Fetches Homework from the Kreta API then stores them in the database // Fetches Homework from the Kreta API then stores them in the database
Future<void> fetch({DateTime? from, bool db = true}) async { Future<void> fetch({DateTime? from, bool db = true}) async {
User? user = Provider.of<UserProvider>(_context, listen: false).user; User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot fetch Homework for User null"; if (user == null) throw "Cannot fetch Homework for User null";
String iss = user.instituteCode; String iss = user.instituteCode;
List? homeworkJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.homework(iss, start: from)); List? homeworkJson = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.homework(iss, start: from));
if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}"; if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}";
List<Homework> homework = []; List<Homework> homework = [];
await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async { await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
Map? e = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.homework(iss, id: hw["Uid"])); Map? e = await Provider.of<KretaClient>(_context, listen: false)
if (e != null) homework.add(Homework.fromJson(e)); .getAPI(KretaAPI.homework(iss, id: hw["Uid"]));
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
: {};
if (e != null) {
Homework hw = Homework.fromJson(e);
hw.subject.renamedTo =
renamedSubjects.isNotEmpty ? renamedSubjects[hw.subject.id] : null;
homework.add(hw);
}
}); });
if (homework.isEmpty && _homework.isEmpty) return; if (homework.isEmpty && _homework.isEmpty) return;
@@ -60,6 +96,8 @@ class HomeworkProvider with ChangeNotifier {
User? user = Provider.of<UserProvider>(_context, listen: false).user; User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot store Homework for User null"; if (user == null) throw "Cannot store Homework for User null";
String userId = user.id; String userId = user.id;
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeHomework(homework, userId: userId); await Provider.of<DatabaseProvider>(_context, listen: false)
.userStore
.storeHomework(homework, userId: userId);
} }
} }

View File

@@ -42,7 +42,7 @@ class HomeworkTile extends StatelessWidget {
padding: const EdgeInsets.only(top: 2.0), padding: const EdgeInsets.only(top: 2.0),
child: Icon( child: Icon(
SubjectIcon.resolveVariant( SubjectIcon.resolveVariant(
subjectName: homework.subjectName, context: context), subjectName: homework.subject.name, context: context),
size: 28.0, size: 28.0,
color: AppColors.of(context).text.withOpacity(.75), color: AppColors.of(context).text.withOpacity(.75),
), ),
@@ -62,7 +62,7 @@ class HomeworkTile extends StatelessWidget {
], ],
) )
: Text( : Text(
homework.subjectName.capital(), homework.subject.renamedTo ?? homework.subject.name.capital(),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.w600), style: const TextStyle(fontWeight: FontWeight.w600),

View File

@@ -40,11 +40,12 @@ class HomeworkView extends StatelessWidget {
// Header // Header
ListTile( ListTile(
leading: Icon( leading: Icon(
SubjectIcon.resolveVariant(subjectName: homework.subjectName, context: context), SubjectIcon.resolveVariant(
subjectName: homework.subject.name, context: context),
size: 36.0, size: 36.0,
), ),
title: Text( title: Text(
homework.subjectName.capital(), homework.subject.renamedTo ?? homework.subject.name.capital(),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.w600), style: const TextStyle(fontWeight: FontWeight.w600),
@@ -62,9 +63,13 @@ class HomeworkView extends StatelessWidget {
), ),
// Details // Details
if (homework.deadline.year != 0) Detail(title: "deadline".i18n, description: homework.deadline.format(context)), if (homework.deadline.year != 0)
Detail(
title: "deadline".i18n,
description: homework.deadline.format(context)),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0, vertical: 6.0), padding:
const EdgeInsets.symmetric(horizontal: 18.0, vertical: 6.0),
child: SelectableLinkify( child: SelectableLinkify(
text: homework.content.escapeHtml(), text: homework.content.escapeHtml(),
options: const LinkifyOptions(looseUrl: true, removeWww: true), options: const LinkifyOptions(looseUrl: true, removeWww: true),

View File

@@ -182,11 +182,15 @@ class _AbsencesPageState extends State<AbsencesPage>
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
), ),
bottom: FilterBar(items: [ bottom: FilterBar(
Tab(text: "Absences".i18n), items: [
Tab(text: "Delays".i18n), Tab(text: "Absences".i18n),
Tab(text: "Misses".i18n), Tab(text: "Delays".i18n),
], controller: _tabController, disableFading: true), Tab(text: "Misses".i18n),
],
controller: _tabController,
disableFading: true,
),
), ),
], ],
body: TabBarView( body: TabBarView(

View File

@@ -20,9 +20,6 @@ import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_pro
import 'package:filcnaplo_mobile_ui/pages/grades/grades_count.dart'; import 'package:filcnaplo_mobile_ui/pages/grades/grades_count.dart';
import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart'; import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart'; import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
import 'package:filcnaplo_premium/models/premium_scopes.dart';
import 'package:filcnaplo_premium/providers/premium_provider.dart';
import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart'; import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
@@ -75,8 +72,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch); final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
final maxGradeDate = gradeDates.fold(0, max); final maxGradeDate = gradeDates.fold(0, max);
final minGradeDate = gradeDates.fold(0, min); final minGradeDate = gradeDates.fold(0, min);
if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
return false; // naplo/#78 return false; // naplo/#78
}
return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1; return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
} }
@@ -214,25 +212,25 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
gradeCalc(context); gradeCalc(context);
}, },
), ),
FloatingActionButton.small( // FloatingActionButton.small(
child: const Icon(FeatherIcons.flag, size: 20.0), // child: const Icon(FeatherIcons.flag, size: 20.0),
backgroundColor: Theme.of(context).colorScheme.secondary, // backgroundColor: Theme.of(context).colorScheme.secondary,
onPressed: () { // onPressed: () {
if (!Provider.of<PremiumProvider>(context, listen: false) // if (!Provider.of<PremiumProvider>(context, listen: false)
.hasScope(PremiumScopes.goalPlanner)) { // .hasScope(PremiumScopes.goalPlanner)) {
PremiumLockedFeatureUpsell.show( // PremiumLockedFeatureUpsell.show(
context: context, feature: PremiumFeature.goalplanner); // context: context, feature: PremiumFeature.goalplanner);
return; // return;
} // }
ScaffoldMessenger.of(context).showSnackBar( // ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Hamarosan..."))); // const SnackBar(content: Text("Hamarosan...")));
//Navigator.of(context).push(CupertinoPageRoute( // Navigator.of(context).push(CupertinoPageRoute(
//builder: (context) => PremiumGoalplannerNewGoalScreen( // builder: (context) => PremiumGoalplannerNewGoalScreen(
// subject: widget.subject))); // subject: widget.subject)));
}, // },
), // ),
], ],
), ),
), ),

View File

@@ -270,6 +270,7 @@ class _GradeGraphState extends State<GradeGraph> {
tData.sort((a, b) => a.writeDate.compareTo(b.writeDate)); tData.sort((a, b) => a.writeDate.compareTo(b.writeDate));
return tData.first.writeDate.add(const Duration(days: 120)).isBefore(tData.last.writeDate) ? 2.0 : 1.0; return tData.first.writeDate.add(const Duration(days: 120)).isBefore(tData.last.writeDate) ? 2.0 : 1.0;
}(), }(),
checkToShowTitle: (double minValue, double maxValue, SideTitles sideTitles, double appliedInterval, double value) { if (value == maxValue || value == minValue) return false; return true; },
), ),
leftTitles: SideTitles( leftTitles: SideTitles(
showTitles: true, showTitles: true,

View File

@@ -249,6 +249,7 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
Tab(text: "Absences".i18n), Tab(text: "Absences".i18n),
], ],
controller: _tabController, controller: _tabController,
disableFading: true,
onTap: (i) async { onTap: (i) async {
int selectedPage = int selectedPage =
_pageController.page!.round(); _pageController.page!.round();

View File

@@ -11,7 +11,7 @@ extension Localization on String {
"happybirthday": "🎂 Happy birthday, %s!", "happybirthday": "🎂 Happy birthday, %s!",
"merryxmas": "🎄 Merry Christmas, %s!", "merryxmas": "🎄 Merry Christmas, %s!",
"happynewyear": "🎉 Happy New Year, %s!", "happynewyear": "🎉 Happy New Year, %s!",
"refilcopen": "🎈 Welcome in reFilc, %s!", "refilcopen": "🎈 reFilc is 1 year old, %s!",
"empty": "Nothing to see here.", "empty": "Nothing to see here.",
"All": "All", "All": "All",
"Grades": "Grades", "Grades": "Grades",
@@ -30,7 +30,7 @@ extension Localization on String {
"happybirthday": "🎂 Boldog születésnapot, %s!", "happybirthday": "🎂 Boldog születésnapot, %s!",
"merryxmas": "🎄 Boldog Karácsonyt, %s!", "merryxmas": "🎄 Boldog Karácsonyt, %s!",
"happynewyear": "🎉 Boldog új évet, %s!", "happynewyear": "🎉 Boldog új évet, %s!",
"refilcopen": "🎈 Üdv a reFilc-ben, %s!", "refilcopen": "🎈 1 éves a reFilc, %s!",
"empty": "Nincs itt semmi látnivaló.", "empty": "Nincs itt semmi látnivaló.",
"All": "Összes", "All": "Összes",
"Grades": "Jegyek", "Grades": "Jegyek",
@@ -49,7 +49,7 @@ extension Localization on String {
"happybirthday": "🎂 Alles Gute zum Geburtstag, %s!", "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
"merryxmas": "🎄 Frohe Weihnachten, %s!", "merryxmas": "🎄 Frohe Weihnachten, %s!",
"happynewyear": "🎉 Frohes neues Jahr, %s!", "happynewyear": "🎉 Frohes neues Jahr, %s!",
"refilcopen": "🎈 Willkommen bei reFilc, %s!", "refilcopen": "🎈 reFilc ist 1 Jahr alt, %s!",
"empty": "Hier gibt es nichts zu sehen.", "empty": "Hier gibt es nichts zu sehen.",
"All": "Alles", "All": "Alles",
"Grades": "Noten", "Grades": "Noten",

View File

@@ -90,12 +90,16 @@ class _MessagesPageState extends State<MessagesPage>
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
), ),
bottom: FilterBar(items: [ bottom: FilterBar(
Tab(text: "Inbox".i18n), items: [
Tab(text: "Sent".i18n), Tab(text: "Inbox".i18n),
Tab(text: "Trash".i18n), Tab(text: "Sent".i18n),
Tab(text: "Draft".i18n), Tab(text: "Trash".i18n),
], controller: tabController), Tab(text: "Draft".i18n),
],
controller: tabController,
disableFading: true,
),
), ),
], ],
body: TabBarView( body: TabBarView(

View File

@@ -2,7 +2,8 @@ import 'package:filcnaplo_kreta_api/models/school.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SchoolInputTile extends StatelessWidget { class SchoolInputTile extends StatelessWidget {
const SchoolInputTile({Key? key, required this.school, this.onTap}) : super(key: key); const SchoolInputTile({Key? key, required this.school, this.onTap})
: super(key: key);
final School school; final School school;
final Function()? onTap; final Function()? onTap;

View File

@@ -173,8 +173,7 @@ class NavigationScreenState extends State<NavigationScreen>
@override @override
void didChangePlatformBrightness() { void didChangePlatformBrightness() {
if (settings.theme == ThemeMode.system) { if (settings.theme == ThemeMode.system) {
Brightness? brightness = Brightness? brightness = MediaQuery.of(context).platformBrightness;
WidgetsBinding.instance.window.platformBrightness;
Provider.of<ThemeModeObserver>(context, listen: false).changeTheme( Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(
brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark); brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark);
} }

View File

@@ -634,7 +634,7 @@ class _SettingsScreenState extends State<SettingsScreen>
? Theme.of(context).colorScheme.secondary ? Theme.of(context).colorScheme.secondary
: AppColors.of(context).text.withOpacity(.25), : AppColors.of(context).text.withOpacity(.25),
), ),
const SizedBox(width: 24.0), const SizedBox(width: 14.0),
Expanded( Expanded(
child: Text( child: Text(
"graph_class_avg".i18n, "graph_class_avg".i18n,
@@ -679,7 +679,7 @@ class _SettingsScreenState extends State<SettingsScreen>
? Theme.of(context).colorScheme.secondary ? Theme.of(context).colorScheme.secondary
: AppColors.of(context).text.withOpacity(.25), : AppColors.of(context).text.withOpacity(.25),
), ),
const SizedBox(width: 24.0), const SizedBox(width: 14.0),
Expanded( Expanded(
child: Text( child: Text(
"news".i18n, "news".i18n,
@@ -724,7 +724,7 @@ class _SettingsScreenState extends State<SettingsScreen>
? Theme.of(context).colorScheme.secondary ? Theme.of(context).colorScheme.secondary
: AppColors.of(context).text.withOpacity(.25), : AppColors.of(context).text.withOpacity(.25),
), ),
const SizedBox(width: 24.0), const SizedBox(width: 14.0),
Expanded( Expanded(
child: Text( child: Text(
"surprise_grades".i18n, "surprise_grades".i18n,

View File

@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
class GradesBody extends StatelessWidget {
const GradesBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column();
}
}

View File

@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
class PersonalityBody extends StatelessWidget {
const PersonalityBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column();
}
}

View File

@@ -0,0 +1,55 @@
import 'package:flutter/material.dart';
import 'pages/grades_page.dart';
class SummaryScreen extends StatefulWidget {
final String currentPage;
const SummaryScreen({Key? key, this.currentPage = 'personality'})
: super(key: key);
@override
_SummaryScreenState createState() => _SummaryScreenState();
}
class _SummaryScreenState extends State<SummaryScreen> {
final LinearGradient _backgroundGradient = const LinearGradient(
colors: [
Color(0xff1d56ac),
Color(0xff170a3d),
],
begin: Alignment(-0.8, -1.0),
end: Alignment(0.8, 1.0),
stops: [-1.0, 1.0],
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(gradient: _backgroundGradient),
child: Container(
decoration: BoxDecoration(gradient: _backgroundGradient),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: SafeArea(
child: Padding(
padding: EdgeInsets.only(
left: 24.0,
right: 24.0,
top: 26.0 + MediaQuery.of(context).padding.top,
bottom: 52.0,
),
child: widget.currentPage == 'grades'
? const GradesBody()
: widget.currentPage == 'lessons'
? const GradesBody()
: widget.currentPage == 'allsum'
? const GradesBody()
: const GradesBody(),
),
),
),
),
);
}
}

View File

@@ -0,0 +1,15 @@
import 'package:i18n_extension/i18n_extension.dart';
extension SettingsLocalization on String {
static final _t = Translations.byLocale("hu_hu") +
{
"en_en": {},
"hu_hu": {},
"de_de": {},
};
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);
}

View File

@@ -9,44 +9,55 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
final Map<int, String> avgDropItems = { final Map<int, String> avgDropItems = {
0: "annual_average".i18n, 0: "annual_average",
90: "3_months_average".i18n, 90: "3_months_average",
30: "30_days_average".i18n, 30: "30_days_average",
14: "14_days_average".i18n, 14: "14_days_average",
7: "7_days_average".i18n, 7: "7_days_average",
}; };
class PremiumAverageSelector extends StatelessWidget { class PremiumAverageSelector extends StatefulWidget {
const PremiumAverageSelector({Key? key, this.onChanged, required this.value}) : super(key: key); const PremiumAverageSelector({Key? key, this.onChanged, required this.value}) : super(key: key);
final Function(int?)? onChanged; final Function(int?)? onChanged;
final int value; final int value;
@override
_PremiumAverageSelectorState createState() => _PremiumAverageSelectorState();
}
class _PremiumAverageSelectorState extends State<PremiumAverageSelector> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<DropdownMenuItem<int>> dropdownItems = avgDropItems.keys.map((item) {
return DropdownMenuItem<int>(
value: item,
child: Text(
avgDropItems[item]!.i18n,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: AppColors.of(context).text,
),
overflow: TextOverflow.ellipsis,
),
);
}).toList();
return DropdownButton2<int>( return DropdownButton2<int>(
items: avgDropItems.keys items: dropdownItems,
.map((item) => DropdownMenuItem<int>(
value: item,
child: Text(
avgDropItems[item] ?? "",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: AppColors.of(context).text,
),
overflow: TextOverflow.ellipsis,
),
))
.toList(),
onChanged: (int? value) { onChanged: (int? value) {
if (Provider.of<PremiumProvider>(context, listen: false).hasScope(PremiumScopes.gradeStats)) { if (Provider.of<PremiumProvider>(context, listen: false).hasScope(PremiumScopes.gradeStats)) {
if (onChanged != null) onChanged!(value); if (widget.onChanged != null) {
setState(() {
widget.onChanged!(value);
});
}
} else { } else {
PremiumLockedFeatureUpsell.show(context: context, feature: PremiumFeature.gradestats); PremiumLockedFeatureUpsell.show(context: context, feature: PremiumFeature.gradestats);
} }
}, },
value: value, value: widget.value,
iconSize: 14, iconSize: 14,
iconEnabledColor: AppColors.of(context).text, iconEnabledColor: AppColors.of(context).text,
iconDisabledColor: AppColors.of(context).text, iconDisabledColor: AppColors.of(context).text,
@@ -71,11 +82,13 @@ class PremiumAverageSelector extends StatelessWidget {
height: 30, height: 30,
child: Row( child: Row(
children: [ children: [
Text(avgDropItems[value] ?? "", Text(
style: Theme.of(context) avgDropItems[widget.value]!.i18n,
.textTheme style: Theme.of(context)
.titleSmall! .textTheme
.copyWith(fontWeight: FontWeight.w600, color: AppColors.of(context).text.withOpacity(0.65))), .titleSmall!
.copyWith(fontWeight: FontWeight.w600, color: AppColors.of(context).text.withOpacity(0.65)),
),
const SizedBox( const SizedBox(
width: 4, width: 4,
), ),

View File

@@ -307,6 +307,7 @@ class _PremiumCustomAccentColorSettingState
controller: _testTabController, controller: _testTabController,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
censored: true, censored: true,
disableFading: true,
), ),
), ),
Padding( Padding(

View File

@@ -19,7 +19,7 @@ extension SettingsLocalization on String {
"colorpicker_panels": "Panelek", "colorpicker_panels": "Panelek",
"colorpicker_accent": "Színtónus", "colorpicker_accent": "Színtónus",
"need_sub": "A módosításhoz Kupak szintű támogatás szükséges.", "need_sub": "A módosításhoz Kupak szintű támogatás szükséges.",
"advanced": "Fejlett", "advanced": "Haladó",
}, },
"de_de": { "de_de": {
"theme_prev": "Vorschau", "theme_prev": "Vorschau",

View File

@@ -27,7 +27,6 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
SystemChrome.setPreferredOrientations([ SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]); ]);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
@@ -51,39 +50,32 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
(a, b) => math.max( (a, b) => math.max(
a, b.where((l) => l.subject.id != "" || l.isEmpty).length)); a, b.where((l) => l.subject.id != "" || l.isEmpty).length));
final int minIndex = int.tryParse(everyLesson.first.lessonIndex) ?? 0;
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(), appBar: AppBar(
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(color: AppColors.of(context).text),
shadowColor: Colors.transparent,
),
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),
itemCount: maxIndex + 1, itemCount: maxLessonCount + 1,
itemBuilder: (context, index) { itemBuilder: (context, index) {
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 lessonIndex = index - 1;
if (dayIndex == -1) { if (dayIndex == -1) {
if (lessonIndex >= 0) { if (index >= 1) {
columns.add(SizedBox( columns.add(SizedBox(
width: prefixw.toDouble(), width: prefixw.toDouble(),
height: 40.0, height: 40.0,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text( child: Text(
"${minIndex + lessonIndex}.", (index).toString()+".",
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.secondary), color: Theme.of(context).colorScheme.secondary),
@@ -101,104 +93,112 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
.toList(); .toList();
if (lessons.isEmpty) continue; if (lessons.isEmpty) continue;
if (lessonIndex >= lessons.length) continue;
if (dayIndex >= days.length || final dayOffset = int.tryParse(lessons.first.lessonIndex) ?? 0;
(lessonIndex + dayOffset) >= lessons.length) {
columns.add(SizedBox(width: colw)); if (index == 0 && dayIndex >= 0) {
columns.add(
SizedBox(
width: colw,
height: 40.0,
child: Text(
DateFormat("EEEE", I18n.of(context).locale.languageCode)
.format(lessons.first.date)
.capital(),
style: const TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
);
continue; continue;
} }
if (lessonIndex == -1 && dayIndex >= 0) { final lessonIndex = index - dayOffset;
columns.add(SizedBox(
width: colw, if (lessonIndex < 0 || lessonIndex >= lessons.length) {
height: 40.0, columns.add(SizedBox(width: colw));
child: Text(
DateFormat("EEEE", I18n.of(context).locale.languageCode)
.format(lessons.first.date)
.capital(),
style: const TextStyle(
fontSize: 24.0, fontWeight: FontWeight.bold),
),
));
continue; continue;
} }
if (lessons[lessonIndex].isEmpty) { if (lessons[lessonIndex].isEmpty) {
columns.add(SizedBox( columns.add(
width: colw, SizedBox(
child: Row( width: colw,
crossAxisAlignment: CrossAxisAlignment.start, child: Row(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Icon(FeatherIcons.slash,
size: 18.0,
color: AppColors.of(context).text.withOpacity(.3)),
const SizedBox(width: 8.0),
Text(
"Lyukas óra",
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.3)),
),
],
),
));
continue;
}
if (dayOffset > 0 && lessonIndex < dayOffset) {
columns.add(SizedBox(width: colw));
continue;
}
columns.add(SizedBox(
width: colw,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [ children: [
Icon( Icon(
SubjectIcon.resolveVariant( FeatherIcons.slash,
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(.3),
), ),
const SizedBox(width: 8.0), const SizedBox(width: 8.0),
Expanded( Text(
child: Text( "Lyukas óra",
lessons[lessonIndex - dayOffset].subject.renamedTo ?? style: TextStyle(
lessons[lessonIndex - dayOffset] color: AppColors.of(context).text.withOpacity(.3),
.subject ),
.name ),
.capital(), ],
maxLines: 1, ),
style: TextStyle( ),
fontStyle: lessons[lessonIndex - dayOffset] );
continue;
}
columns.add(
SizedBox(
width: colw,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
SubjectIcon.resolveVariant(
context: context,
subject: lessons[lessonIndex].subject,
),
size: 18.0,
color: AppColors.of(context).text.withOpacity(.7),
),
const SizedBox(width: 8.0),
Expanded(
child: Text(
lessons[lessonIndex].subject.renamedTo ??
lessons[lessonIndex].subject.name.capital(),
maxLines: 1,
style: TextStyle(
fontStyle: lessons[lessonIndex]
.subject .subject
.isRenamed .isRenamed
? FontStyle.italic ? FontStyle.italic
: null), : null,
overflow: TextOverflow.clip, ),
softWrap: false, overflow: TextOverflow.clip,
softWrap: false,
),
),
const SizedBox(width: 15),
],
),
Padding(
padding: const EdgeInsets.only(left: 26.0),
child: Text(
lessons[lessonIndex].room,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.5),
overflow: TextOverflow.ellipsis,
), ),
), ),
const SizedBox(width: 15),
],
),
Padding(
padding: const EdgeInsets.only(left: 26.0),
child: Text(
lessons[lessonIndex - dayOffset].room,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.5),
overflow: TextOverflow.ellipsis),
), ),
), ],
], ),
), ),
)); );
} }
return Row( return Row(
@@ -209,14 +209,4 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
), ),
); );
} }
AppBar buildAppBar() {
return AppBar(
backgroundColor: Colors.transparent,
automaticallyImplyLeading: false,
actions: const [
BackButton(),
],
);
}
} }