From 3579c4e821b1806d9a72ecc24f2938a287cfae64 Mon Sep 17 00:00:00 2001 From: kima Date: Sat, 17 Jun 2023 20:04:11 +0200 Subject: [PATCH] fixed grades page ui in summary --- .../flutter/generated_plugin_registrant.cc | 4 + .../linux/flutter/generated_plugins.cmake | 1 + .../Flutter/GeneratedPluginRegistrant.swift | 2 + filcnaplo_mobile_ui/lib/common/empty.dart | 15 +- .../lib/pages/home/live_card/live_card.dart | 30 +- .../screens/summary/pages/grades_page.dart | 348 +++++++++++------- .../lib/screens/summary/summary_screen.dart | 54 ++- 7 files changed, 283 insertions(+), 171 deletions(-) diff --git a/filcnaplo/linux/flutter/generated_plugin_registrant.cc b/filcnaplo/linux/flutter/generated_plugin_registrant.cc index 4894d34..0fcfb27 100644 --- a/filcnaplo/linux/flutter/generated_plugin_registrant.cc +++ b/filcnaplo/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include @@ -14,6 +15,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) flutter_acrylic_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterAcrylicPlugin"); flutter_acrylic_plugin_register_with_registrar(flutter_acrylic_registrar); diff --git a/filcnaplo/linux/flutter/generated_plugins.cmake b/filcnaplo/linux/flutter/generated_plugins.cmake index c8808fe..c5541e6 100644 --- a/filcnaplo/linux/flutter/generated_plugins.cmake +++ b/filcnaplo/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + file_selector_linux flutter_acrylic url_launcher_linux ) diff --git a/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift b/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift index c6b190d..53df988 100644 --- a/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,7 @@ import Foundation import connectivity_plus import dynamic_color +import file_selector_macos import flutter_local_notifications import macos_window_utils import package_info_plus @@ -18,6 +19,7 @@ import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) diff --git a/filcnaplo_mobile_ui/lib/common/empty.dart b/filcnaplo_mobile_ui/lib/common/empty.dart index 6b32339..ea0a06c 100755 --- a/filcnaplo_mobile_ui/lib/common/empty.dart +++ b/filcnaplo_mobile_ui/lib/common/empty.dart @@ -23,7 +23,6 @@ class Empty extends StatelessWidget { @override Widget build(BuildContext context) { - // make the face randomness a bit more constant (to avoid strokes) int index = Random(DateTime.now().minute).nextInt(faces.length); return Center( @@ -32,9 +31,19 @@ class Empty extends StatelessWidget { child: Text.rich( TextSpan( text: faces[index], - style: TextStyle(fontSize: 32.0, fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(.75)), + style: TextStyle( + fontSize: 32.0, + fontWeight: FontWeight.w500, + color: AppColors.of(context).text.withOpacity(.75)), children: subtitle != null - ? [TextSpan(text: "\n" + subtitle!, style: TextStyle(fontSize: 18.0, height: 2.0, color: AppColors.of(context).text.withOpacity(.5)))] + ? [ + TextSpan( + text: "\n" + subtitle!, + style: TextStyle( + fontSize: 18.0, + height: 2.0, + color: AppColors.of(context).text.withOpacity(.5))) + ] : [], ), textAlign: TextAlign.center, diff --git a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart b/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart index d996d56..bb8afff 100755 --- a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart +++ b/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart @@ -13,6 +13,7 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart'; import 'package:i18n_extension/i18n_widget.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; +import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart'; import 'live_card.i18n.dart'; class LiveCard extends StatefulWidget { @@ -66,13 +67,30 @@ class _LiveCardState extends State { color: Theme.of(context).textTheme.bodyMedium?.color, ), ), - onTap: () => Navigator.of(context).push( - MaterialPageRoute( - builder: (BuildContext context) => const SummaryScreen( - currentPage: 'grades', + onTap: () { + showSlidingBottomSheet( + context, + useRootNavigator: true, + builder: (context) => SlidingSheetDialog( + color: Theme.of(context).scaffoldBackgroundColor, + duration: const Duration(milliseconds: 400), + scrollSpec: const ScrollSpec.bouncingScroll(), + snapSpec: const SnapSpec( + snap: true, + snappings: [1.0], + positioning: SnapPositioning.relativeToSheetHeight, + ), + cornerRadius: 16, + cornerRadiusOnFullscreen: 0, + builder: (context, state) => Material( + color: Theme.of(context).scaffoldBackgroundColor, + child: const SummaryScreen( + currentPage: 'grades', + ), + ), ), - ), - ), + ); + }, ); break; case LiveCardState.morning: diff --git a/filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart b/filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart index cd21ae1..110bf11 100644 --- a/filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart +++ b/filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart @@ -3,18 +3,29 @@ import 'dart:math'; import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/helpers/average_helper.dart'; import 'package:filcnaplo/models/settings.dart'; -import 'package:filcnaplo/theme/colors/colors.dart'; import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart'; import 'package:filcnaplo/utils/format.dart'; import 'package:filcnaplo_kreta_api/models/grade.dart'; import 'package:filcnaplo_kreta_api/models/subject.dart'; import 'package:filcnaplo_kreta_api/providers/grade_provider.dart'; -import 'package:filcnaplo_mobile_ui/common/empty.dart'; -import 'package:filcnaplo_mobile_ui/pages/grades/grades_page.i18n.dart'; +import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:auto_size_text/auto_size_text.dart'; +List faces = [ + "(·.·)", + "(≥o≤)", + "(·_·)", + "(˚Δ˚)b", + "(^-^*)", + "(='X'=)", + "(>_<)", + "(;-;)", + "\\(^Д^)/", + "\\(o_o)/", +]; + class GradesBody extends StatefulWidget { const GradesBody({Key? key}) : super(key: key); @@ -49,6 +60,7 @@ class _GradesBodyState extends State { void initState() { super.initState(); + gradeProvider = Provider.of(context, listen: false); settings = Provider.of(context, listen: false); } @@ -62,41 +74,65 @@ class _GradesBodyState extends State { Map subjectAvgs = {}; - tiles.addAll(subjects.map((subject) { + for (Subject subject in subjects) { List subjectGrades = getSubjectGrades(subject); double avg = AverageHelper.averageEvals(subjectGrades); if (avg != 0) subjectAvgs[subject] = avg; - if (avg.round() == filter) { - return Row( - children: [ - GradeValueWidget( - GradeValue(avg.round(), '', '', 100), - fill: true, - size: 22.0, + Widget widget = Row( + children: [ + GradeValueWidget( + GradeValue(avg.round(), '', '', 100), + fill: true, + size: 28.0, + ), + const SizedBox(width: 8), + Text( + subject.renamedTo ?? subject.name.capital(), + maxLines: 2, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20.0, + color: Colors.white.withOpacity(0.98), + fontStyle: settings.renamedSubjectsItalics && subject.isRenamed + ? FontStyle.italic + : null, ), - Text( - subject.renamedTo ?? subject.name.capital(), - maxLines: 2, - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 18.0, - color: AppColors.of(context).text, - fontStyle: settings.renamedSubjectsItalics && subject.isRenamed - ? FontStyle.italic - : null, - ), - ) - ], - ); - } else { - return Container(); + ) + ], + ); + + if (avg.round() == filter) { + tiles.add(widget); } - })); + } if (tiles.isEmpty) { - tiles.insert(0, Empty(subtitle: "empty".i18n)); + int index = Random(DateTime.now().minute).nextInt(faces.length); + Widget faceWidget = Center( + child: Text.rich( + TextSpan( + text: faces[index], + style: const TextStyle( + fontSize: 32.0, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + children: [ + TextSpan( + text: "\nno_grades".i18n, + style: TextStyle( + fontSize: 18.0, + height: 2.0, + color: Colors.white.withOpacity(0.5)), + ), + ], + ), + textAlign: TextAlign.center, + ), + ); + tiles.insert(0, faceWidget); } subjectAvg = subjectAvgs.isNotEmpty @@ -106,17 +142,15 @@ class _GradesBodyState extends State { if (filter == 5) { subjectTiles5 = List.castFrom(tiles); - if (subjectTiles5.length > 5) { - subjectTiles5.length = 5; + if (subjectTiles5.length > 4) { + subjectTiles5.length = 4; } - } - if (filter == 3) { + } else if (filter == 3) { subjectTiles3 = List.castFrom(tiles); if (subjectTiles3.length > 3) { subjectTiles3.length = 3; } - } - if (filter == 1) { + } else if (filter == 1) { subjectTiles1 = List.castFrom(tiles); if (subjectTiles1.length > 2) { subjectTiles1.length = 2; @@ -124,6 +158,12 @@ class _GradesBodyState extends State { } } + void getGrades() { + generateTiles(filter: 5); + generateTiles(filter: 3); + generateTiles(filter: 1); + } + @override Widget build(BuildContext context) { user = Provider.of(context); @@ -136,152 +176,176 @@ class _GradesBodyState extends State { firstName = "János"; } - generateTiles(filter: 5); - generateTiles(filter: 3); - generateTiles(filter: 1); + getGrades(); return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Jó éved volt, $firstName!', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 24.0, - color: Theme.of(context).textTheme.bodyMedium?.color, + textAlign: TextAlign.left, + style: const TextStyle( + fontWeight: FontWeight.w900, + fontSize: 26.0, + color: Colors.white, ), ), - Text( + const Text( 'Nézzük a jegyeidet... 📖', style: TextStyle( fontWeight: FontWeight.bold, - fontSize: 20.0, - color: Theme.of(context).textTheme.bodyMedium?.color, + fontSize: 22.0, + color: Colors.white, ), ), - const SizedBox(height: 20.0), - ListView.builder( - padding: EdgeInsets.zero, - physics: const BouncingScrollPhysics(), - itemCount: max(subjectTiles5.length, 1), - itemBuilder: (context, index) { - if (subjectTiles5.isNotEmpty) { - EdgeInsetsGeometry panelPadding = - const EdgeInsets.symmetric(horizontal: 24.0); + const SizedBox(height: 12.0), + SizedBox( + height: ((100 * subjectTiles5.length) / + (subjectTiles5[0].runtimeType == Row ? 1.95 : 1.2)) + .toDouble(), + child: ListView.builder( + padding: const EdgeInsets.only(left: 5), + physics: const BouncingScrollPhysics(), + itemCount: max(subjectTiles5.length, 1), + itemBuilder: (context, index) { + if (subjectTiles5.isNotEmpty) { + EdgeInsetsGeometry panelPadding = + const EdgeInsets.symmetric(horizontal: 24.0); - if (subjectTiles5[index].runtimeType == Row) { - return subjectTiles5[index]; + if (subjectTiles5[index].runtimeType == Row) { + return Padding( + padding: const EdgeInsets.only(top: 8), + child: subjectTiles5[index]); + } else { + return Padding( + padding: panelPadding, child: subjectTiles5[index]); + } } else { - return Padding( - padding: panelPadding, child: subjectTiles5[index]); + return Container(); } - } else { - return Container(); - } - }, + }, + ), ), - const SizedBox(height: 20.0), - Text( + const SizedBox(height: 12.0), + const Text( 'Próba teszi a mestert! 🔃', style: TextStyle( fontWeight: FontWeight.bold, - fontSize: 20.0, - color: Theme.of(context).textTheme.bodyMedium?.color, + fontSize: 22.0, + color: Colors.white, ), ), - const SizedBox(height: 20.0), - ListView.builder( - padding: EdgeInsets.zero, - physics: const BouncingScrollPhysics(), - itemCount: max(subjectTiles3.length, 1), - itemBuilder: (context, index) { - if (subjectTiles3.isNotEmpty) { - EdgeInsetsGeometry panelPadding = - const EdgeInsets.symmetric(horizontal: 24.0); + const SizedBox(height: 12.0), + SizedBox( + height: ((100 * subjectTiles3.length) / + (subjectTiles3[0].runtimeType == Row ? 1.95 : 1.2)) + .toDouble(), + child: ListView.builder( + padding: const EdgeInsets.only(left: 5), + physics: const BouncingScrollPhysics(), + itemCount: max(subjectTiles3.length, 1), + itemBuilder: (context, index) { + if (subjectTiles3.isNotEmpty) { + EdgeInsetsGeometry panelPadding = + const EdgeInsets.symmetric(horizontal: 24.0); - if (subjectTiles3[index].runtimeType == Row) { - return subjectTiles3[index]; + if (subjectTiles3[index].runtimeType == Row) { + return Padding( + padding: const EdgeInsets.only(top: 8), + child: subjectTiles3[index]); + } else { + return Padding( + padding: panelPadding, child: subjectTiles3[index]); + } } else { - return Padding( - padding: panelPadding, child: subjectTiles3[index]); + return Container(); } - } else { - return Container(); - } - }, + }, + ), ), - const SizedBox(height: 20.0), - Text( + const SizedBox(height: 12.0), + const Text( 'Ajajj... 🥴', style: TextStyle( fontWeight: FontWeight.bold, - fontSize: 20.0, - color: Theme.of(context).textTheme.bodyMedium?.color, + fontSize: 22.0, + color: Colors.white, ), ), - const SizedBox(height: 20.0), - ListView.builder( - padding: EdgeInsets.zero, - physics: const BouncingScrollPhysics(), - itemCount: max(subjectTiles1.length, 1), - itemBuilder: (context, index) { - if (subjectTiles1.isNotEmpty) { - EdgeInsetsGeometry panelPadding = - const EdgeInsets.symmetric(horizontal: 24.0); + const SizedBox(height: 12.0), + SizedBox( + height: ((100 * subjectTiles1.length) / + (subjectTiles1[0].runtimeType == Row ? 1.95 : 1.2)) + .toDouble(), + child: ListView.builder( + padding: const EdgeInsets.only(left: 5), + physics: const BouncingScrollPhysics(), + itemCount: max(subjectTiles1.length, 1), + itemBuilder: (context, index) { + if (subjectTiles1.isNotEmpty) { + EdgeInsetsGeometry panelPadding = + const EdgeInsets.symmetric(horizontal: 24.0); - if (subjectTiles1[index].runtimeType == Row) { - return subjectTiles1[index]; + if (subjectTiles1[index].runtimeType == Row) { + return Padding( + padding: const EdgeInsets.only(top: 8), + child: subjectTiles1[index]); + } else { + return Padding( + padding: panelPadding, child: subjectTiles1[index]); + } } else { - return Padding( - padding: panelPadding, child: subjectTiles1[index]); + return Container(); } - } else { - return Container(); - } - }, + }, + ), ), const SizedBox(height: 40.0), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - 'Év végi átlagod', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20.0, - color: Theme.of(context).textTheme.bodyMedium?.color, - ), - ), - Container( - margin: const EdgeInsets.only(top: 4.0), - padding: - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0), - decoration: BoxDecoration( - color: gradeColor(context: context, value: subjectAvg) - .withOpacity(.2), - border: Border.all( - color: (gradeColor(context: context, value: subjectAvg)) - .withOpacity(0.0), - width: 2.0, - ), - borderRadius: BorderRadius.circular(45.0), - ), - child: AutoSizeText.rich( - TextSpan( - text: subjectAvg.toString(), - ), - maxLines: 1, - minFontSize: 5, + Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + 'Év végi átlagod', textAlign: TextAlign.center, style: TextStyle( - color: gradeColor(context: context, value: subjectAvg), - fontWeight: FontWeight.w800, - fontSize: 32.0, + fontWeight: FontWeight.bold, + fontSize: 22.0, + color: Colors.white, ), ), - ), - ], - ) + Container( + margin: const EdgeInsets.only(top: 10.0), + padding: + const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0), + decoration: BoxDecoration( + color: gradeColor(context: context, value: subjectAvg) + .withOpacity(.2), + border: Border.all( + color: (gradeColor(context: context, value: subjectAvg)) + .withOpacity(0.0), + width: 2.0, + ), + borderRadius: BorderRadius.circular(45.0), + ), + child: AutoSizeText.rich( + TextSpan( + text: subjectAvg.toStringAsFixed(2), + ), + maxLines: 1, + minFontSize: 5, + textAlign: TextAlign.center, + style: TextStyle( + color: gradeColor(context: context, value: subjectAvg), + fontWeight: FontWeight.w800, + fontSize: 32.0, + ), + ), + ), + ], + ), + ), ], ); } diff --git a/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart b/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart index b795100..98fa41b 100644 --- a/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart +++ b/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart @@ -15,7 +15,9 @@ class SummaryScreen extends StatefulWidget { _SummaryScreenState createState() => _SummaryScreenState(); } -class _SummaryScreenState extends State { +class _SummaryScreenState extends State + with SingleTickerProviderStateMixin { + late AnimationController _hideContainersController; ConfettiController? _confettiController; final LinearGradient _backgroundGradient = const LinearGradient( @@ -28,6 +30,14 @@ class _SummaryScreenState extends State { stops: [-1.0, 1.0], ); + @override + void initState() { + super.initState(); + + _hideContainersController = AnimationController( + vsync: this, duration: const Duration(milliseconds: 200)); + } + @override void dispose() { _confettiController?.dispose(); @@ -37,28 +47,32 @@ class _SummaryScreenState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: Container( - decoration: BoxDecoration(gradient: _backgroundGradient), + return AnimatedBuilder( + animation: _hideContainersController, + builder: (context, child) => Opacity( + opacity: 1 - _hideContainersController.value, 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: 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: MediaQuery.of(context).padding.top, + bottom: 52.0, + ), + child: widget.currentPage == 'grades' + ? const GradesBody() + : widget.currentPage == 'lessons' + ? const LessonsBody() + : widget.currentPage == 'allsum' + ? const GradesBody() + : const PersonalityBody(), ), - child: widget.currentPage == 'grades' - ? const GradesBody() - : widget.currentPage == 'lessons' - ? const LessonsBody() - : widget.currentPage == 'allsum' - ? const GradesBody() - : const PersonalityBody(), ), ), ),