omfg really sok progress

This commit is contained in:
Kima 2024-05-04 22:11:29 +02:00
parent 6b8708e1e3
commit 3b1e345f14
14 changed files with 689 additions and 161 deletions

View File

@ -485,9 +485,9 @@ class SettingsProvider extends ChangeNotifier {
navShadow: true,
newColors: true,
uwuMode: false,
qTimetableLessonNum: false,
qTimetableSubTiles: false,
qSubjectsSubTiles: false,
qTimetableLessonNum: true,
qTimetableSubTiles: true,
qSubjectsSubTiles: true,
);
}
@ -694,7 +694,7 @@ class SettingsProvider extends ChangeNotifier {
if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay;
if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) {
_bellDelayEnabled = bellDelayEnabled;
if(Platform.isIOS){
if (Platform.isIOS) {
LiveCardProvider.hasActivitySettingsChanged = true;
}
}

View File

@ -31,3 +31,66 @@ Map<AccentColor, Color> accentColorMap = {
AccentColor.adaptive: const Color(0xFF3D7BF4),
AccentColor.custom: const Color(0xFF3D7BF4),
};
// new v5 things
Map<AccentColor, Color> lightPrimary = {
AccentColor.filc: const Color(0xFF050B15),
};
Map<AccentColor, Color> lightSecondary = {
AccentColor.filc: const Color(0xFF3F444F),
};
Map<AccentColor, Color> lightTeritary = {
AccentColor.filc: const Color(0xFF1C469A),
};
Map<AccentColor, Color> lightIcon = {
AccentColor.filc: const Color(0xFF0A2456),
};
Map<AccentColor, Color> lightAccent = {
AccentColor.filc: const Color(0xFF487DE6),
};
Map<AccentColor, Color> lightBgDarkened = {
AccentColor.filc: const Color(0xFFB9C8E5),
};
Map<AccentColor, Color> lightBtnSecStrk = {
AccentColor.filc: const Color(0xFFCEDBF5),
};
Map<AccentColor, Color> lightBg = {
AccentColor.filc: const Color(0xFFDAE4F7),
};
Map<AccentColor, Color> lightCard = {
AccentColor.filc: const Color(0xFFEDF3FF),
};
Map<AccentColor, Color> lightBtnSec = {
AccentColor.filc: const Color(0xFFFBFCFF),
};
Map<AccentColor, Color> darkPrimary = {
AccentColor.filc: const Color(0xFFEBF1FD),
};
Map<AccentColor, Color> darkSecondary = {
AccentColor.filc: const Color(0xFFCFD8E9),
};
Map<AccentColor, Color> darkTeritary = {
AccentColor.filc: const Color(0xFFAEC8FC),
};
Map<AccentColor, Color> darkIcon = {
AccentColor.filc: const Color(0xFFBAD1FF),
};
Map<AccentColor, Color> darkAccent = {
AccentColor.filc: const Color(0xFF487DE6),
};
Map<AccentColor, Color> darkBgDarkened = {
AccentColor.filc: const Color(0xFF010205),
};
Map<AccentColor, Color> darkBtnSecStrk = {
AccentColor.filc: const Color(0xFF1C2230),
};
Map<AccentColor, Color> darkBg = {
AccentColor.filc: const Color(0xFF070A0E),
};
Map<AccentColor, Color> darkCard = {
AccentColor.filc: const Color(0xFF0F131B),
};
Map<AccentColor, Color> darkBtnSec = {
AccentColor.filc: const Color(0xFF131822),
};

View File

@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
class NewColors extends ThemeExtension<NewColors> {
const NewColors({
required this.accent,
required this.primary,
required this.secondary,
required this.teritary,
required this.icon,
required this.darkenBg,
required this.btnSecStrk,
required this.background,
required this.card,
required this.btnSec,
});
final Color? accent;
final Color? primary;
final Color? secondary;
final Color? teritary;
final Color? icon;
final Color? darkenBg;
final Color? btnSecStrk;
final Color? background;
final Color? card;
final Color? btnSec;
@override
NewColors copyWith({
Color? accent,
Color? primary,
Color? secondary,
Color? teritary,
Color? icon,
Color? darkenBg,
Color? btnSecStrk,
Color? background,
Color? card,
Color? btnSec,
}) {
return NewColors(
accent: accent ?? this.accent,
primary: primary ?? this.primary,
secondary: secondary ?? this.secondary,
teritary: teritary ?? this.teritary,
icon: icon ?? this.icon,
darkenBg: darkenBg ?? this.darkenBg,
btnSecStrk: btnSecStrk ?? this.btnSecStrk,
background: background ?? this.background,
card: card ?? this.card,
btnSec: btnSec ?? this.btnSec,
);
}
@override
NewColors lerp(NewColors? other, double t) {
if (other is! NewColors) {
return this;
}
return NewColors(
accent: Color.lerp(accent, other.accent, t),
primary: Color.lerp(primary, other.primary, t),
secondary: Color.lerp(secondary, other.secondary, t),
teritary: Color.lerp(teritary, other.teritary, t),
icon: Color.lerp(icon, other.icon, t),
darkenBg: Color.lerp(darkenBg, other.darkenBg, t),
btnSecStrk: Color.lerp(btnSecStrk, other.btnSecStrk, t),
background: Color.lerp(background, other.background, t),
card: Color.lerp(card, other.card, t),
btnSec: Color.lerp(btnSec, other.btnSec, t),
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/accent.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/theme/colors/new_colors.dart';
import 'package:refilc/theme/colors/utils.dart';
import 'package:refilc/theme/observer.dart';
import 'package:flutter/material.dart';
@ -87,6 +88,20 @@ class AppTheme {
amount: 0.4); // white mode: same tertiary as secondary
return ThemeData(
// extensions: [
// NewColors(
// accent: lightAccent[accentColor]!,
// primary: lightPrimary[accentColor]!,
// secondary: lightSecondary[accentColor]!,
// teritary: lightTeritary[accentColor]!,
// icon: lightIcon[accentColor]!,
// darkenBg: lightBgDarkened[accentColor]!,
// btnSecStrk: lightBtnSecStrk[accentColor]!,
// background: lightBg[accentColor]!,
// card: lightCard[accentColor]!,
// btnSec: lightBtnSec[accentColor]!,
// ),
// ],
brightness: Brightness.light,
useMaterial3: true,
fontFamily: _defaultFontFamily,
@ -198,6 +213,20 @@ class AppTheme {
amount: 0.1); // dark mode: tertiary is way darker than secondary
return ThemeData(
// extensions: [
// NewColors(
// accent: darkAccent[accentColor]!,
// primary: darkPrimary[accentColor]!,
// secondary: darkSecondary[accentColor]!,
// teritary: darkTeritary[accentColor]!,
// icon: darkIcon[accentColor]!,
// darkenBg: darkBgDarkened[accentColor]!,
// btnSecStrk: darkBtnSecStrk[accentColor]!,
// background: darkBg[accentColor]!,
// card: darkCard[accentColor]!,
// btnSec: darkBtnSec[accentColor]!,
// ),
// ],
brightness: Brightness.dark,
useMaterial3: true,
fontFamily: _defaultFontFamily,

View File

@ -1,4 +1,5 @@
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/new_colors.dart';
import 'package:refilc_kreta_api/providers/exam_provider.dart';
import 'package:refilc_kreta_api/providers/homework_provider.dart';
import 'package:refilc/theme/colors/colors.dart';

View File

@ -1,8 +1,12 @@
import 'dart:developer';
import 'package:googleapis/privateca/v1.dart';
import 'package:refilc_kreta_api/models/absence.dart';
import 'package:refilc_kreta_api/models/category.dart';
import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_kreta_api/models/week.dart';
import 'package:refilc_kreta_api/providers/grade_provider.dart';
import 'package:refilc_kreta_api/providers/timetable_provider.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
@ -41,4 +45,23 @@ class ReverseSearch {
// difference.inDays is not reliable
static bool _sameDate(DateTime a, DateTime b) =>
(a.year == b.year && a.month == b.month && a.day == b.day);
static Future<GradeSubject?> getSubjectByLesson(
Lesson lesson, BuildContext context) async {
final gradeProvider = Provider.of<GradeProvider>(context, listen: false);
try {
await gradeProvider.fetch();
} catch (e) {
log("[ERROR] getSubjectByLesson: $e");
}
try {
return gradeProvider.grades.map((e) => e.subject).firstWhere(
(s) => s.id == lesson.subject.id,
);
} catch (e) {
return null;
}
}
}

View File

@ -8,19 +8,21 @@ class RoundedBottomSheet extends StatelessWidget {
this.borderRadius = 16.0,
this.shrink = true,
this.showHandle = true,
this.backgroundColor,
});
final Widget? child;
final double borderRadius;
final bool shrink;
final bool showHandle;
final Color? backgroundColor;
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
color: backgroundColor ?? Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(borderRadius),
topRight: Radius.circular(borderRadius),
@ -52,6 +54,7 @@ Future<T?> showRoundedModalBottomSheet<T>(
required Widget child,
bool rootNavigator = true,
bool showHandle = true,
Color? backgroundColor,
}) async {
return await showModalBottomSheet<T>(
useSafeArea: false,
@ -62,6 +65,7 @@ Future<T?> showRoundedModalBottomSheet<T>(
useRootNavigator: rootNavigator,
isScrollControlled: true,
builder: (context) => RoundedBottomSheet(
backgroundColor: backgroundColor,
showHandle: showHandle,
child: child,
),

View File

@ -9,12 +9,14 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class GradeSubjectTile extends StatelessWidget {
const GradeSubjectTile(this.subject,
{super.key,
this.average = 0.0,
this.groupAverage = 0.0,
this.onTap,
this.averageBefore = 0.0});
const GradeSubjectTile(
this.subject, {
super.key,
this.average = 0.0,
this.groupAverage = 0.0,
this.onTap,
this.averageBefore = 0.0,
});
final GradeSubject subject;
final void Function()? onTap;

View File

@ -1,13 +1,16 @@
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:flutter_svg/svg.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/helpers/subject.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/theme/colors/utils.dart';
import 'package:refilc/utils/reverse_search.dart';
import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
import 'package:refilc_mobile_ui/common/round_border_icon.dart';
import 'package:refilc_mobile_ui/common/viewable.dart';
@ -15,18 +18,25 @@ import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
import 'package:flutter/material.dart';
import 'package:refilc_mobile_ui/pages/grades/grades_page.dart';
import 'package:refilc_plus/models/premium_scopes.dart';
import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
import 'lesson_view.i18n.dart';
class LessonViewable extends StatefulWidget {
const LessonViewable(this.lesson,
{super.key, this.swapDesc = false, required this.customDesc});
const LessonViewable(
this.lesson, {
super.key,
this.swapDesc = false,
required this.customDesc,
this.showSubTiles = true,
});
final Lesson lesson;
final bool swapDesc;
final String customDesc;
final bool showSubTiles;
@override
State<LessonViewable> createState() => LessonViewableState();
@ -51,14 +61,28 @@ class LessonViewableState extends State<LessonViewable> {
Lesson lsn = widget.lesson;
lsn.description = widget.customDesc;
final tile = LessonTile(lsn, swapDesc: widget.swapDesc);
final tile = LessonTile(
lsn,
swapDesc: widget.swapDesc,
showSubTiles: widget.showSubTiles,
);
if (lsn.subject.id == '' || tile.lesson.isEmpty) return tile;
return LessonTile(
lsn,
swapDesc: widget.swapDesc,
onTap: () => TimetableLessonPopup.show(context: context, lesson: lsn),
return GestureDetector(
onTap: () => TimetableLessonPopup.show(
context: context,
lesson: lsn,
),
child: LessonTile(
lsn,
swapDesc: widget.swapDesc,
showSubTiles: widget.showSubTiles,
// onTap: () => TimetableLessonPopup.show(
// context: context,
// lesson: lsn,
// ),
),
);
// return Viewable(
@ -232,9 +256,14 @@ class LessonViewableState extends State<LessonViewable> {
}
class TimetableLessonPopup extends StatelessWidget {
const TimetableLessonPopup({super.key, required this.lesson});
const TimetableLessonPopup({
super.key,
required this.lesson,
required this.outsideContext,
});
final Lesson lesson;
final BuildContext outsideContext;
static void show({
required BuildContext context,
@ -244,6 +273,7 @@ class TimetableLessonPopup extends StatelessWidget {
context,
child: TimetableLessonPopup(
lesson: lesson,
outsideContext: context,
),
showHandle: false,
);
@ -272,13 +302,42 @@ class TimetableLessonPopup extends StatelessWidget {
),
child: Stack(
children: [
SvgPicture.asset(
"assets/svg/mesh_bg.svg",
// ignore: deprecated_member_use
color: ColorsUtils().fade(
context, Theme.of(context).scaffoldBackgroundColor,
darkenAmount: 0.1, lightenAmount: 0.1),
width: MediaQuery.of(context).size.width,
Stack(
children: [
SvgPicture.asset(
"assets/svg/mesh_bg.svg",
// ignore: deprecated_member_use
color: ColorsUtils()
.fade(context, Theme.of(context).colorScheme.secondary,
darkenAmount: 0.1, lightenAmount: 0.1)
.withOpacity(0.33),
width: MediaQuery.of(context).size.width,
),
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
),
gradient: LinearGradient(
colors: [
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context)
.scaffoldBackgroundColor
.withOpacity(0.1),
Theme.of(context)
.scaffoldBackgroundColor
.withOpacity(0.1),
Theme.of(context).scaffoldBackgroundColor,
],
stops: const [0.1, 0.5, 0.7, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
width: MediaQuery.of(context).size.width,
height: 175.0,
),
],
),
SizedBox(
width: MediaQuery.of(context).size.width,
@ -291,9 +350,11 @@ class TimetableLessonPopup extends StatelessWidget {
width: 40,
height: 4,
decoration: BoxDecoration(
color: ColorsUtils().fade(
context, Theme.of(context).scaffoldBackgroundColor,
darkenAmount: 0.2, lightenAmount: 0.2),
color: ColorsUtils()
.fade(
context, Theme.of(context).colorScheme.secondary,
darkenAmount: 0.1, lightenAmount: 0.1)
.withOpacity(0.33),
borderRadius: BorderRadius.circular(
2.0,
),
@ -302,10 +363,31 @@ class TimetableLessonPopup extends StatelessWidget {
const SizedBox(
height: 38.0,
),
RoundBorderIcon(
icon: Icon(
SubjectIcon.resolveVariant(
context: context, subject: lesson.subject),
Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: RoundBorderIcon(
color: ColorsUtils()
.darken(
Theme.of(context).colorScheme.secondary,
amount: 0.1,
)
.withOpacity(0.9),
width: 1.5,
padding: 10.0,
icon: Icon(
SubjectIcon.resolveVariant(
context: context, subject: lesson.subject),
size: 32.0,
color: ColorsUtils()
.darken(
Theme.of(context).colorScheme.secondary,
amount: 0.1,
)
.withOpacity(0.8),
),
),
),
const SizedBox(
@ -315,9 +397,11 @@ class TimetableLessonPopup extends StatelessWidget {
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(6.0),
borderRadius: BorderRadius.vertical(
top: const Radius.circular(12.0),
bottom: (lesson.description.replaceAll(' ', '') != '')
? const Radius.circular(6.0)
: const Radius.circular(12.0),
),
),
padding: const EdgeInsets.all(14.0),
@ -325,7 +409,7 @@ class TimetableLessonPopup extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'6:09 - 4:20',
'${DateFormat('H:mm').format(lesson.start)} - ${DateFormat('H:mm').format(lesson.end)}',
style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.85),
fontSize: 14.0,
@ -357,64 +441,79 @@ class TimetableLessonPopup extends StatelessWidget {
],
),
),
const SizedBox(
height: 6.0,
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(6.0),
bottom: Radius.circular(12.0),
),
if (lesson.description.replaceAll(' ', '') != '')
const SizedBox(
height: 6.0,
),
padding: const EdgeInsets.all(14.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
lesson.description,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.9),
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
),
const SizedBox(
height: 24.0,
),
GestureDetector(
onTap: () {
Navigator.of(context, rootNavigator: true)
.pushReplacementNamed('/');
},
child: Container(
if (lesson.description.replaceAll(' ', '') != '')
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(12.0),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(6.0),
bottom: Radius.circular(12.0),
),
),
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(14.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'view_subject'.i18n,
lesson.description,
style: TextStyle(
color:
AppColors.of(context).text.withOpacity(0.9),
fontSize: 18.0,
fontWeight: FontWeight.w500,
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
// const SizedBox(
// height: 24.0,
// ),
// GestureDetector(
// onTap: () async {
// ReverseSearch.getSubjectByLesson(lesson, context)
// .then((subject) {
// if (subject != null) {
// GradesPage.jump(outsideContext, subject: subject);
// } else {
// ScaffoldMessenger.of(context)
// .showSnackBar(CustomSnackBar(
// content: Text("Cannot find subject".i18n,
// style: const TextStyle(color: Colors.white)),
// backgroundColor: AppColors.of(context).red,
// context: context,
// ));
// }
// });
// },
// child: Container(
// width: double.infinity,
// decoration: BoxDecoration(
// color: Theme.of(context).colorScheme.background,
// borderRadius: BorderRadius.circular(12.0),
// ),
// padding: const EdgeInsets.all(16.0),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Text(
// 'view_subject'.i18n,
// style: TextStyle(
// color:
// AppColors.of(context).text.withOpacity(0.9),
// fontSize: 18.0,
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// ),
// ),
// ),
],
),
),

View File

@ -19,6 +19,7 @@ import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_kreta_api/models/group_average.dart';
import 'package:refilc_kreta_api/providers/homework_provider.dart';
import 'package:refilc_mobile_ui/common/average_display.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/empty.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart';
@ -32,6 +33,9 @@ import 'package:refilc_mobile_ui/pages/grades/fail_warning.dart';
import 'package:refilc_mobile_ui/pages/grades/grades_count.dart';
import 'package:refilc_mobile_ui/pages/grades/graph.dart';
import 'package:refilc_mobile_ui/pages/grades/grade_subject_view.dart';
import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
import 'package:refilc_mobile_ui/screens/navigation/navigation_route_handler.dart';
import 'package:refilc_mobile_ui/screens/navigation/navigation_screen.dart';
import 'package:refilc_plus/models/premium_scopes.dart';
import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:flutter/material.dart';
@ -48,6 +52,19 @@ import 'grades_page.i18n.dart';
class GradesPage extends StatefulWidget {
const GradesPage({super.key});
static void jump(BuildContext context, {GradeSubject? subject}) {
// Go to timetable page with arguments
NavigationScreen.of(context)
?.customRoute(navigationPageRoute((context) => const GradesPage()));
NavigationScreen.of(context)?.setPage("grades");
// Show initial Lesson
if (subject != null) {
GradeSubjectView(subject, groupAverage: 0.0).push(context, root: true);
}
}
@override
GradesPageState createState() => GradesPageState();
}
@ -147,7 +164,8 @@ class GradesPageState extends State<GradesPage> {
Exam? nearestExam = allExams.firstWhereOrNull((e) =>
e.subject.id == subject.id && e.writeDate.isAfter(DateTime.now()));
bool hasUnder = hasHomework || nearestExam != null;
bool hasUnder = (hasHomework || nearestExam != null) &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles;
return Padding(
padding: i > 1 ? const EdgeInsets.only(top: 9.0) : EdgeInsets.zero,
@ -201,7 +219,8 @@ class GradesPageState extends State<GradesPage> {
const SizedBox(
height: 6.0,
),
if (hasHomework)
if (hasHomework &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
Container(
decoration: BoxDecoration(
boxShadow: [
@ -249,7 +268,8 @@ class GradesPageState extends State<GradesPage> {
),
),
),
if (nearestExam != null)
if (nearestExam != null &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
Container(
decoration: BoxDecoration(
boxShadow: [
@ -519,19 +539,10 @@ class GradesPageState extends State<GradesPage> {
child: IconButton(
splashRadius: 24.0,
onPressed: () {
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.totalGradeCalculator)) {
PlusLockedFeaturePopup.show(
context: context,
feature: PremiumFeature.gradeCalculation);
return;
}
// SoonAlert.show(context: context);
gradeCalcTotal(context);
showQuickSettings(context);
},
icon: Icon(
FeatherIcons.plus,
FeatherIcons.moreHorizontal,
color: AppColors.of(context).text,
),
),
@ -627,4 +638,88 @@ class GradesPageState extends State<GradesPage> {
}
});
}
void showQuickSettings(BuildContext context) {
// _sheetController = _scaffoldKey.currentState?.showBottomSheet(
// (context) => RoundedBottomSheet(
// borderRadius: 14.0,
// child: BottomSheetMenu(items: [
// SwitchListTile(
// title: Text('show_lesson_num'.i18n),
// value:
// Provider.of<SettingsProvider>(context).qTimetableLessonNum,
// onChanged: (v) {
// Provider.of<SettingsProvider>(context, listen: false)
// .update(qTimetableLessonNum: v);
// })
// ])),
// backgroundColor: const Color(0x00000000),
// elevation: 12.0,
// );
// _sheetController!.closed.then((value) {
// // Show fab and grades
// if (mounted) {}
// });
showRoundedModalBottomSheet(
context,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: BottomSheetMenu(items: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
title: Row(
children: [
const Icon(FeatherIcons.plusCircle),
const SizedBox(
width: 10.0,
),
Text('grade_calc'.i18n),
],
),
onTap: () {
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.totalGradeCalculator)) {
PlusLockedFeaturePopup.show(
context: context, feature: PremiumFeature.gradeCalculation);
return;
}
// SoonAlert.show(context: context);
gradeCalcTotal(context);
},
),
),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: SwitchListTile(
title: Row(
children: [
const Icon(Icons.edit_document),
const SizedBox(
width: 10.0,
),
Text('show_exams_homework'.i18n),
],
),
value: Provider.of<SettingsProvider>(context, listen: false)
.qSubjectsSubTiles,
onChanged: (v) {
Provider.of<SettingsProvider>(context, listen: false)
.update(qSubjectsSubTiles: v);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
]),
);
}
}

View File

@ -27,6 +27,8 @@ extension Localization on String {
"exams": "Exams",
"timetable": "Timetable",
"grades": "Grades",
"show_exams_homework": "Exams and Homework",
"grade_calc": "Grade Calculator",
},
"hu_hu": {
"Grades": "Tantárgyak",
@ -51,6 +53,8 @@ extension Localization on String {
"exams": "Számonkérések",
"timetable": "Órarend",
"grades": "Jegyek",
"show_exams_homework": "Dolgozatok és házik",
"grade_calc": "Jegy kalkulátor",
},
"de_de": {
"Grades": "Fächer",
@ -75,6 +79,8 @@ extension Localization on String {
"exams": "Prüfungen",
"timetable": "Stundenplan",
"grades": "Noten",
"show_exams_homework": "Referate und Hausaufgaben",
"grade_calc": "Noten-Rechner",
},
};

View File

@ -1,5 +1,6 @@
import 'dart:math';
import 'package:animations/animations.dart';
import 'package:flutter/widgets.dart';
import 'package:i18n_extension/i18n_extension.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/update_provider.dart';
@ -14,6 +15,7 @@ import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/dot.dart';
import 'package:refilc_mobile_ui/common/empty.dart';
import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
@ -69,6 +71,10 @@ class TimetablePage extends StatefulWidget {
class TimetablePageState extends State<TimetablePage>
with TickerProviderStateMixin, WidgetsBindingObserver {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
PersistentBottomSheetController? _sheetController;
late UserProvider user;
late TimetableProvider timetableProvider;
late UpdateProvider updateProvider;
@ -215,6 +221,7 @@ class TimetablePageState extends State<TimetablePage>
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
return Scaffold(
key: _scaffoldKey,
body: Padding(
padding: const EdgeInsets.only(top: 9.0),
child: RefreshIndicator(
@ -235,50 +242,50 @@ class TimetablePageState extends State<TimetablePage>
snap: false,
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
actions: [
Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
child: IconButton(
splashRadius: 24.0,
// tested timetable sync
// onPressed: () async {
// ThirdPartyProvider tpp =
// Provider.of<ThirdPartyProvider>(context,
// listen: false);
// Padding(
// padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
// child: IconButton(
// splashRadius: 24.0,
// // tested timetable sync
// // onPressed: () async {
// // ThirdPartyProvider tpp =
// // Provider.of<ThirdPartyProvider>(context,
// // listen: false);
// await tpp.pushTimetable(context, _controller);
// },
onPressed: () {
// If timetable empty, show empty
if (_tabController.length == 0) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("empty_timetable".i18n),
duration: const Duration(seconds: 2),
));
return;
}
// // await tpp.pushTimetable(context, _controller);
// // },
// onPressed: () {
// // If timetable empty, show empty
// if (_tabController.length == 0) {
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(
// content: Text("empty_timetable".i18n),
// duration: const Duration(seconds: 2),
// ));
// return;
// }
Navigator.of(context, rootNavigator: true)
.push(PageRouteBuilder(
pageBuilder:
(context, animation, secondaryAnimation) =>
FSTimetable(
controller: _controller,
),
))
.then((_) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]);
setSystemChrome(context);
});
},
icon: Icon(FeatherIcons.trello,
color: AppColors.of(context).text),
),
),
// Navigator.of(context, rootNavigator: true)
// .push(PageRouteBuilder(
// pageBuilder:
// (context, animation, secondaryAnimation) =>
// FSTimetable(
// controller: _controller,
// ),
// ))
// .then((_) {
// SystemChrome.setPreferredOrientations(
// [DeviceOrientation.portraitUp]);
// setSystemChrome(context);
// });
// },
// icon: Icon(FeatherIcons.trello,
// color: AppColors.of(context).text),
// ),
// ),
Padding(
padding: const EdgeInsets.only(
right: 8.0,
right: 5.0,
bottom: 8.0,
top: 8.0,
),
@ -293,9 +300,9 @@ class TimetablePageState extends State<TimetablePage>
// await tpp.pushTimetable(context, _controller);
// },
onPressed: () {
showQuickOptions(context);
showQuickSettings(context);
},
icon: Icon(FeatherIcons.menu,
icon: Icon(FeatherIcons.moreHorizontal,
color: AppColors.of(context).text),
),
),
@ -711,6 +718,9 @@ class TimetablePageState extends State<TimetablePage>
customLessonDesc[
lesson.id] ??
lesson.description,
showSubTiles:
settingsProvider
.qTimetableSubTiles,
),
),
),
@ -844,35 +854,149 @@ class TimetablePageState extends State<TimetablePage>
);
}
void showQuickOptions(BuildContext context) {
showBottomSheetMenu(
void showQuickSettings(BuildContext context) {
// _sheetController = _scaffoldKey.currentState?.showBottomSheet(
// (context) => RoundedBottomSheet(
// borderRadius: 14.0,
// child: BottomSheetMenu(items: [
// SwitchListTile(
// title: Text('show_lesson_num'.i18n),
// value:
// Provider.of<SettingsProvider>(context).qTimetableLessonNum,
// onChanged: (v) {
// Provider.of<SettingsProvider>(context, listen: false)
// .update(qTimetableLessonNum: v);
// })
// ])),
// backgroundColor: const Color(0x00000000),
// elevation: 12.0,
// );
// _sheetController!.closed.then((value) {
// // Show fab and grades
// if (mounted) {}
// });
showRoundedModalBottomSheet(
context,
items: [
SwitchListTile(
title: Text(
'show_lesson_num'.i18n,
),
value: settingsProvider.qTimetableLessonNum,
onChanged: (v) {
settingsProvider.update(qTimetableLessonNum: v);
setState(() {});
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: BottomSheetMenu(items: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
contentPadding: const EdgeInsets.only(left: 16.0, right: 10.0),
title: Row(
children: [
const Icon(FeatherIcons.trello),
const SizedBox(
width: 10.0,
),
Text('full_screen_timetable'.i18n),
],
),
onTap: () {
if (_tabController.length == 0) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("empty_timetable".i18n),
duration: const Duration(seconds: 2),
));
return;
}
Navigator.of(context).maybePop();
},
),
SwitchListTile(
title: Text(
'show_exams_and_homework'.i18n,
),
value: settingsProvider.qTimetableSubTiles,
onChanged: (v) {
settingsProvider.update(qTimetableSubTiles: v);
setState(() {});
Navigator.of(context, rootNavigator: true).pop();
Navigator.of(context).maybePop();
},
Navigator.of(context, rootNavigator: true)
.push(PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
FSTimetable(
controller: _controller,
),
))
.then((_) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]);
setSystemChrome(context);
});
},
),
),
],
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: SwitchListTile(
contentPadding: const EdgeInsets.only(left: 16.0, right: 10.0),
title: Row(
children: [
const Icon(Icons.local_cafe_rounded),
const SizedBox(
width: 10.0,
),
Text('show_breaks'.i18n),
],
),
value: Provider.of<SettingsProvider>(context, listen: false)
.showBreaks,
onChanged: (v) {
Provider.of<SettingsProvider>(context, listen: false)
.update(showBreaks: v);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
// SwitchListTile(
// title: Row(
// children: [
// const Icon(FeatherIcons.clock),
// const SizedBox(
// width: 10.0,
// ),
// Text('show_lesson_num'.i18n),
// ],
// ),
// value: Provider.of<SettingsProvider>(context, listen: false)
// .qTimetableLessonNum,
// onChanged: (v) {
// Provider.of<SettingsProvider>(context, listen: false)
// .update(qTimetableLessonNum: v);
// Navigator.of(context, rootNavigator: true).pop();
// },
// ),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: SwitchListTile(
contentPadding: const EdgeInsets.only(left: 16.0, right: 10.0),
title: Row(
children: [
const Icon(Icons.edit_document),
const SizedBox(
width: 10.0,
),
Text('show_exams_homework'.i18n),
],
),
value: Provider.of<SettingsProvider>(context, listen: false)
.qTimetableSubTiles,
onChanged: (v) {
Provider.of<SettingsProvider>(context, listen: false)
.update(qTimetableSubTiles: v);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
]),
);
}
}

View File

@ -10,6 +10,9 @@ extension Localization on String {
"error": "Failed to fetch timetable!",
"empty_timetable": "Timetable is empty!",
"break": "Break",
"full_screen_timetable": "Full Screen Timetable",
"show_breaks": "Show Breaks",
"show_exams_homework": "Exams and Homework",
},
"hu_hu": {
"timetable": "Órarend",
@ -18,6 +21,9 @@ extension Localization on String {
"error": "Nem sikerült lekérni az órarendet!",
"empty_timetable": "Az órarend üres!",
"break": "Szünet",
"full_screen_timetable": "Teljes képernyős órarend",
"show_breaks": "Szünetek megjelenítése",
"show_exams_homework": "Dolgozatok és házik",
},
"de_de": {
"timetable": "Zeitplan",
@ -26,6 +32,9 @@ extension Localization on String {
"error": "Der Fahrplan konnte nicht abgerufen werden!",
"empty_timetable": "Der Zeitplan ist blank!",
"break": "Pause",
"full_screen_timetable": "Vollbildfahrplan",
"show_breaks": "Pausen anzeigen",
"show_exams_homework": "Referate und Hausaufgaben",
},
};

View File

@ -751,7 +751,7 @@ class _BellDelaySettingState extends State<BellDelaySetting>
Provider.of<SettingsProvider>(context, listen: false)
.update(bellDelay: currentDelay.inSeconds);
_tabController.index = currentDelay.inSeconds > 0 ? 1 : 0;
if(Platform.isIOS){
if (Platform.isIOS) {
LiveCardProvider.hasActivitySettingsChanged = true;
}
setState(() {});
@ -764,7 +764,7 @@ class _BellDelaySettingState extends State<BellDelaySetting>
//Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt());
Provider.of<SettingsProvider>(context, listen: false)
.update(bellDelay: currentDelay.inSeconds);
if(Platform.isIOS){
if (Platform.isIOS) {
LiveCardProvider.hasActivitySettingsChanged = true;
}
Navigator.of(context).maybePop();