Merge pull request #69 from refilc/dev

69-es szamu pr haha 😏
This commit is contained in:
Márton Kiss 2023-10-08 17:00:13 +02:00 committed by GitHub
commit acbffd6d72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 271 additions and 41 deletions

View File

@ -136,7 +136,7 @@
android:layout_below="@id/iv_1" android:layout_below="@id/iv_1"
android:layout_marginHorizontal="15dp" android:layout_marginHorizontal="15dp"
android:fontFamily="@font/montserrat_medium" android:fontFamily="@font/montserrat_medium"
android:text="A widget használatához, bejelentkezés szükséges." android:text="A widget használatához bejelentkezés szükséges."
android:textColor="@color/black" android:textColor="@color/black"
android:paddingTop="10dp" android:paddingTop="10dp"
android:textSize="17sp" android:textSize="17sp"

View File

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
# platform :ios, '11.0' platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -39,5 +39,8 @@ end
post_install do |installer| post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target) flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
end
end end
end end

View File

@ -51,7 +51,7 @@ class LiveCardProvider extends ChangeNotifier {
_liveActivitiesPlugin.areActivitiesEnabled().then((value) { _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
// Console log // Console log
if (kDebugMode) { if (kDebugMode) {
print("Live card enabled: $value"); print("iOS LiveActivity enabled: $value");
} }
if (value) { if (value) {
@ -62,13 +62,13 @@ class LiveCardProvider extends ChangeNotifier {
}); });
} }
}); });
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
_delay = settings.bellDelayEnabled
? Duration(seconds: settings.bellDelay)
: Duration.zero;
update();
} }
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
_delay = settings.bellDelayEnabled
? Duration(seconds: settings.bellDelay)
: Duration.zero;
update();
} }
@override @override
@ -196,7 +196,7 @@ class LiveCardProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('ERROR: Unable to create or update iOS LiveCard!'); print('ERROR: Unable to create or update iOS LiveActivity!');
} }
} }
} }

View File

@ -79,11 +79,12 @@ class StatusProvider extends ChangeNotifier {
} }
} }
if (_stack.contains(Status.network)) return; if (res.body == 'invalid_grant' ||
if (res.body == "invalid_grant" ||
res.body.replaceAll(' ', '') == '' || res.body.replaceAll(' ', '') == '' ||
res.statusCode == 400) { res.statusCode == 400) {
if (!_stack.contains(Status.apiError)) { if (!_stack.contains(Status.apiError) &&
!_stack.contains(Status.network)) {
if (res.statusCode == 401) return;
_stack.insert(0, Status.apiError); _stack.insert(0, Status.apiError);
notifyListeners(); notifyListeners();
} }

View File

@ -131,6 +131,7 @@ class App extends StatelessWidget {
create: (context) => HomeworkProvider( create: (context) => HomeworkProvider(
context: context, context: context,
database: database, database: database,
user: user,
), ),
), ),
ChangeNotifierProvider<MessageProvider>( ChangeNotifierProvider<MessageProvider>(

View File

@ -195,7 +195,7 @@ class NotificationsHelper {
if (userProvider.getUsers().length == 1) { if (userProvider.getUsers().length == 1) {
await flutterLocalNotificationsPlugin.show( await flutterLocalNotificationsPlugin.show(
absence.id.hashCode, absence.id.hashCode,
"title_absence".i18n, "title_absence".i18n, // https://discord.com/channels/1111649116020285532/1153273625206591528
"body_absence".i18n.fill( "body_absence".i18n.fill(
[ [
DateFormat("yyyy-MM-dd").format(absence.date), DateFormat("yyyy-MM-dd").format(absence.date),
@ -210,7 +210,7 @@ class NotificationsHelper {
} else { } else {
await flutterLocalNotificationsPlugin.show( await flutterLocalNotificationsPlugin.show(
absence.id.hashCode, absence.id.hashCode,
"title_absence".i18n, "title_absence".i18n, // https://discord.com/channels/1111649116020285532/1153273625206591528
"body_absence_multiuser".i18n.fill( "body_absence_multiuser".i18n.fill(
[ [
userProvider.displayName!, userProvider.displayName!,

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.3.0+226 version: 4.3.1+230
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"

View File

@ -144,8 +144,8 @@ class _GradesPageState extends State<GradesPage> {
Expanded( Expanded(
child: StatisticsTile( child: StatisticsTile(
outline: true, outline: true,
title: AutoSizeText( title: AutoSizeText( // https://discord.com/channels/1111649116020285532/1153397476578050130
"classavg".i18n, "classavg".i18n,
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, maxLines: 2,
wrapWords: false, wrapWords: false,

View File

@ -0,0 +1,122 @@
import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input_overlay.dart';
import 'package:filcnaplo_desktop_ui/screens/login/school_input/school_input_tile.dart';
import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_search.dart';
import 'package:flutter/material.dart';
import 'package:filcnaplo_kreta_api/models/school.dart';
class SchoolInput extends StatefulWidget {
const SchoolInput({Key? key, required this.controller, required this.scroll})
: super(key: key);
final SchoolInputController controller;
final ScrollController scroll;
@override
_SchoolInputState createState() => _SchoolInputState();
}
class _SchoolInputState extends State<SchoolInput> {
final _focusNode = FocusNode();
final _layerLink = LayerLink();
late SchoolInputOverlay overlay;
@override
void initState() {
super.initState();
widget.controller.update = (fn) {
if (mounted) setState(fn);
};
overlay = SchoolInputOverlay(layerLink: _layerLink);
// Show school list when focused
_focusNode.addListener(() {
if (_focusNode.hasFocus) {
WidgetsBinding.instance
.addPostFrameCallback((_) => overlay.createOverlayEntry(context));
Future.delayed(const Duration(milliseconds: 100)).then((value) {
if (mounted && widget.scroll.hasClients) {
widget.scroll.animateTo(widget.scroll.offset + 500,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
}
});
} else {
overlay.entry?.remove();
}
});
// LoginInput TextField listener
widget.controller.textController.addListener(() {
String text = widget.controller.textController.text;
if (text.isEmpty) {
overlay.children = null;
return;
}
List<School> results =
searchSchools(widget.controller.schools ?? [], text);
setState(() {
overlay.children = results
.map((School e) => SchoolInputTile(
school: e,
onTap: () => _selectSchool(e),
))
.toList();
});
Overlay.of(context).setState(() {});
});
}
void _selectSchool(School school) {
FocusScope.of(context).requestFocus(FocusNode());
setState(() {
widget.controller.selectedSchool = school;
widget.controller.textController.text = school.name;
});
}
@override
Widget build(BuildContext context) {
return CompositedTransformTarget(
link: _layerLink,
child: widget.controller.schools == null
? Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.15),
borderRadius: BorderRadius.circular(12.0),
),
child: const Center(
child: SizedBox(
height: 28.0,
width: 28.0,
child: CircularProgressIndicator(
color: Colors.white,
),
),
),
)
: LoginInput(
style: LoginInputStyle.school,
focusNode: _focusNode,
onClear: () {
widget.controller.selectedSchool = null;
FocusScope.of(context).requestFocus(_focusNode);
},
controller: widget.controller.textController,
),
);
}
}
class SchoolInputController {
final textController = TextEditingController();
School? selectedSchool;
List<School>? schools;
late void Function(void Function()) update;
}

View File

@ -0,0 +1,65 @@
import 'package:filcnaplo_kreta_api/models/school.dart';
import 'package:flutter/material.dart';
class SchoolInputTile extends StatelessWidget {
const SchoolInputTile({Key? key, required this.school, this.onTap})
: super(key: key);
final School school;
final Function()? onTap;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: GestureDetector(
onPanDown: (e) {
onTap!();
},
child: InkWell(
onTapDown: (e) {},
borderRadius: BorderRadius.circular(6.0),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// School name
Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Text(
school.name,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
Row(
children: [
// School id
Expanded(
child: Text(
school.instituteCode,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
// School city
Expanded(
child: Text(
school.city,
textAlign: TextAlign.right,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
),
),
),
);
}
}

View File

@ -24,10 +24,12 @@ class HomeworkProvider with ChangeNotifier {
List<Homework> initialHomework = const [], List<Homework> initialHomework = const [],
required BuildContext context, required BuildContext context,
required DatabaseProvider database, required DatabaseProvider database,
required UserProvider user,
}) { }) {
_homework = List.castFrom(initialHomework); _homework = List.castFrom(initialHomework);
_context = context; _context = context;
_database = database; _database = database;
_user = user;
if (_homework.isEmpty) restore(); if (_homework.isEmpty) restore();
} }

View File

@ -127,7 +127,7 @@ class AbsenceView extends StatelessWidget {
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
onPressed: () { onPressed: () { // https://discord.com/channels/1111649116020285532/1149964760130002945
Navigator.of(context).pop(); Navigator.of(context).pop();
if (outsideContext != null) { if (outsideContext != null) {

View File

@ -57,7 +57,7 @@ class ChangedLessonTile extends StatelessWidget {
), ),
), ),
title: Text( title: Text(
lesson.substituteTeacher?.name != "" lesson.substituteTeacher?.name != "" || lesson.substituteTeacher?.name != null
? "substituted".i18n ? "substituted".i18n
: "cancelled".i18n, : "cancelled".i18n,
maxLines: 2, maxLines: 2,

View File

@ -40,7 +40,7 @@ class AbsenceSubjectView extends StatelessWidget {
TimetablePage.jump(context, lesson: lesson); TimetablePage.jump(context, lesson: lesson);
} else { } else {
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar( ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
content: Text("Cannot find lesson".i18n, content: Text("lesson_not_found".i18n,
style: const TextStyle(color: Colors.white)), style: const TextStyle(color: Colors.white)),
backgroundColor: AppColors.of(context).red, backgroundColor: AppColors.of(context).red,
context: context, context: context,

View File

@ -17,6 +17,7 @@ extension ScreensLocalization on String {
"Subjects": "Subjects", "Subjects": "Subjects",
"attention": "Attention!", "attention": "Attention!",
"attention_body": "Percentage calculations are only an approximation so they may not be accurate.", "attention_body": "Percentage calculations are only an approximation so they may not be accurate.",
"lesson_not_found": "Cannot find lesson",
}, },
"hu_hu": { "hu_hu": {
"Absences": "Hiányzások", "Absences": "Hiányzások",
@ -32,6 +33,7 @@ extension ScreensLocalization on String {
"Subjects": "Tantárgyak", "Subjects": "Tantárgyak",
"attention": "Figyelem!", "attention": "Figyelem!",
"attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.", "attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.",
"lesson_not_found": "Nem található óra",
}, },
"de_de": { "de_de": {
"Absences": "Fehlen", "Absences": "Fehlen",
@ -47,6 +49,7 @@ extension ScreensLocalization on String {
"Subjects": "Fächer", "Subjects": "Fächer",
"attention": "Achtung!", "attention": "Achtung!",
"attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.", "attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.",
"lesson_not_found": "Lektion kann nicht gefunden werden",
}, },
}; };

View File

@ -102,6 +102,8 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
firstName = "János"; firstName = "János";
} }
bool customWelcome = false;
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) && if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
now.isAfter(DateTime(now.year, DateTime.june, 14))) { now.isAfter(DateTime(now.year, DateTime.june, 14))) {
greeting = "goodrest"; greeting = "goodrest";
@ -112,16 +114,16 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
Future.delayed(const Duration(seconds: 1)) Future.delayed(const Duration(seconds: 1))
.then((value) => mounted ? _confettiController?.play() : null); .then((value) => mounted ? _confettiController?.play() : null);
} }
// } else if (now.month == user.student?.birth.month && } else if (now.month == user.student?.birth.month &&
// now.day == user.student?.birth.day) { now.day == user.student?.birth.day) {
// greeting = "happybirthday"; greeting = "happybirthday";
// if (NavigationScreen.of(context)?.init("confetti") ?? false) { if (NavigationScreen.of(context)?.init("confetti") ?? false) {
// _confettiController = _confettiController =
// ConfettiController(duration: const Duration(seconds: 3)); ConfettiController(duration: const Duration(seconds: 3));
// Future.delayed(const Duration(seconds: 1)) Future.delayed(const Duration(seconds: 1))
// .then((value) => mounted ? _confettiController?.play() : null); .then((value) => mounted ? _confettiController?.play() : null);
// } }
} else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) && } else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) &&
now.isBefore(DateTime(now.year, DateTime.may, 30))) { now.isBefore(DateTime(now.year, DateTime.may, 30))) {
greeting = "refilcopen"; greeting = "refilcopen";
@ -144,6 +146,8 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
settings.welcomeMessage, settings.welcomeMessage,
[firstName], [firstName],
); );
customWelcome = true;
} else if (now.hour >= 18) { } else if (now.hour >= 18) {
greeting = "goodevening"; greeting = "goodevening";
} else if (now.hour >= 10) { } else if (now.hour >= 10) {
@ -153,6 +157,8 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
} else { } else {
greeting = "goodevening"; greeting = "goodevening";
} }
greeting = customWelcome ? greeting : greeting.i18n.fill([firstName]);
} }
@override @override
@ -191,7 +197,7 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
title: Padding( title: Padding(
padding: const EdgeInsets.only(left: 24.0), padding: const EdgeInsets.only(left: 24.0),
child: Text( child: Text(
greeting.i18n.fill([firstName]), greeting,
overflow: TextOverflow.fade, overflow: TextOverflow.fade,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,

View File

@ -17,6 +17,8 @@ List<School> searchSchools(List<School> all, String pattern) {
}); });
if (contains == pattern.split(" ").length) results.add(item); if (contains == pattern.split(" ").length) results.add(item);
if (item.instituteCode.toLowerCase().specialChars().contains(pattern)) results.add(item);
} }
results.sort((a, b) => a.name.compareTo(b.name)); results.sort((a, b) => a.name.compareTo(b.name));

View File

@ -87,7 +87,9 @@ class _SettingsScreenState extends State<SettingsScreen>
String _firstName; String _firstName;
List<String> _nameParts = account.displayName.split(" "); List<String> _nameParts =
(account.nickname != '' ? account.nickname : account.displayName)
.split(" ");
if (!settings.presentationMode) { if (!settings.presentationMode) {
_firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0]; _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
} else { } else {
@ -96,7 +98,10 @@ class _SettingsScreenState extends State<SettingsScreen>
accountTiles.add( accountTiles.add(
AccountTile( AccountTile(
name: Text(!settings.presentationMode ? account.name : "János", name: Text(
!settings.presentationMode
? (account.nickname != '' ? account.nickname : account.name)
: "János",
style: const TextStyle(fontWeight: FontWeight.w500)), style: const TextStyle(fontWeight: FontWeight.w500)),
username: Text( username: Text(
!settings.presentationMode ? account.username : "01234567890"), !settings.presentationMode ? account.username : "01234567890"),
@ -275,7 +280,7 @@ class _SettingsScreenState extends State<SettingsScreen>
child: Panel( child: Panel(
child: Column( child: Column(
children: [ children: [
// Account list // account list
...accountTiles, ...accountTiles,
if (accountTiles.isNotEmpty) if (accountTiles.isNotEmpty)
@ -291,7 +296,7 @@ class _SettingsScreenState extends State<SettingsScreen>
), ),
), ),
// Account settings // account settings
PanelButton( PanelButton(
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context)

View File

@ -22,7 +22,7 @@ class GoalProvider extends ChangeNotifier {
Future<void> fetchDone({required GradeProvider gradeProvider}) async { Future<void> fetchDone({required GradeProvider gradeProvider}) async {
var goalAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!); var goalAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!);
var beforeAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!); var beforeAvgs = await _db.userQuery.subjectGoalBefores(userId: _user.id!);
List<Subject> subjects = gradeProvider.grades List<Subject> subjects = gradeProvider.grades
.map((e) => e.subject) .map((e) => e.subject)

View File

@ -329,7 +329,7 @@ class _PremiumCustomAccentColorSettingState
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(24),
gradient: LinearGradient( gradient: LinearGradient( // https://discord.com/channels/1111649116020285532/1153619667848548452
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
stops: const [ stops: const [
@ -337,7 +337,8 @@ class _PremiumCustomAccentColorSettingState
0.75 0.75
], ],
colors: [ colors: [
Theme.of(context).colorScheme.background, settings.customBackgroundColor
?? Theme.of(context).colorScheme.background,
isBackgroundDifferent isBackgroundDifferent
? HSVColor.fromColor(Theme.of(context) ? HSVColor.fromColor(Theme.of(context)
.colorScheme .colorScheme

View File

@ -126,8 +126,14 @@ class _WelcomeMessageEditorState extends State<WelcomeMessageEditor> {
// } // }
var finalText = _welcomeMsg.text var finalText = _welcomeMsg.text
.trim() .trim()
.replaceAll('%s', '') .replaceFirst('%name%', '\$s')
.replaceFirst('%name%', '%s'); .replaceFirst('%user%', '\$s')
.replaceFirst('%username%', '\$s')
.replaceFirst('%me%', '\$s')
.replaceFirst('%profile%', '\$s')
.replaceAll('%', '')
.replaceFirst('\$s', '%s');
// .replaceAll('\$s', 's');
widget.settingsProvider widget.settingsProvider
.update(welcomeMessage: finalText, store: true); .update(welcomeMessage: finalText, store: true);

View File

@ -1,4 +1,5 @@
import 'package:filcnaplo/helpers/subject.dart'; import 'package:filcnaplo/helpers/subject.dart';
import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/theme/colors/colors.dart'; import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart'; import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
import 'package:filcnaplo_mobile_ui/common/empty.dart'; import 'package:filcnaplo_mobile_ui/common/empty.dart';
@ -9,6 +10,7 @@ import 'package:filcnaplo/utils/format.dart';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:i18n_extension/i18n_widget.dart'; import 'package:i18n_extension/i18n_widget.dart';
import 'package:provider/provider.dart';
class PremiumFSTimetable extends StatefulWidget { class PremiumFSTimetable extends StatefulWidget {
const PremiumFSTimetable({Key? key, required this.controller}) const PremiumFSTimetable({Key? key, required this.controller})
@ -21,6 +23,8 @@ class PremiumFSTimetable extends StatefulWidget {
} }
class _PremiumFSTimetableState extends State<PremiumFSTimetable> { class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
late SettingsProvider settings;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -37,6 +41,8 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
settings = Provider.of<SettingsProvider>(context);
if (widget.controller.days == null || widget.controller.days!.isEmpty) { if (widget.controller.days == null || widget.controller.days!.isEmpty) {
return const Center(child: Empty()); return const Center(child: Empty());
} }
@ -174,7 +180,7 @@ class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
style: TextStyle( style: TextStyle(
fontStyle: lessons[lessonIndex] fontStyle: lessons[lessonIndex]
.subject .subject
.isRenamed .isRenamed && settings.renamedSubjectsItalics
? FontStyle.italic ? FontStyle.italic
: null, : null,
), ),

7
upgrade-pub.sh Normal file
View File

@ -0,0 +1,7 @@
cd filcnaplo && flutter pub upgrade && cd ..
cd filcnaplo_kreta_api && flutter pub upgrade && cd ..
cd filcnaplo_mobile_ui && flutter pub upgrade && cd ..
cd filcnaplo_desktop_ui && flutter pub upgrade && cd ..
cd filcnaplo_premium && flutter pub upgrade && cd ..
echo Upgraded pub.