diff --git a/filcnaplo_mobile_ui/lib/common/splitted_panel/splitted_panel.dart b/filcnaplo_mobile_ui/lib/common/splitted_panel/splitted_panel.dart index ac1dc3c..162a3ba 100644 --- a/filcnaplo_mobile_ui/lib/common/splitted_panel/splitted_panel.dart +++ b/filcnaplo_mobile_ui/lib/common/splitted_panel/splitted_panel.dart @@ -65,7 +65,11 @@ class SplittedPanel extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ // title - if (title != null) SplittedPanelTitle(title: title!), + if (title != null) + SplittedPanelTitle( + title: title!, + leftPadding: (padding?.horizontal ?? 48.0) / 2, + ), // body if (children != null) @@ -94,14 +98,16 @@ class SplittedPanel extends StatelessWidget { } class SplittedPanelTitle extends StatelessWidget { - const SplittedPanelTitle({super.key, required this.title}); + const SplittedPanelTitle( + {super.key, required this.title, this.leftPadding = 24.0}); final Widget title; + final double leftPadding; @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.only(left: 14.0 + 24.0, bottom: 8.0), + padding: EdgeInsets.only(left: 14.0 + leftPadding, bottom: 8.0), child: DefaultTextStyle( style: Theme.of(context).textTheme.titleMedium!.copyWith( fontWeight: FontWeight.w600, diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart index 23d4319..994f1ef 100755 --- a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart +++ b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart @@ -82,6 +82,7 @@ extension SettingsLocalization on String { "personalization": "Personalization", "edit": "Edit", "switch_account": "Switch Account", + "subjects": "Subjects", }, "hu_hu": { "personal_details": "Személyes információk", @@ -162,6 +163,7 @@ extension SettingsLocalization on String { "personalization": "Személyre szabás", "edit": "Szerkesztés", "switch_account": "Fiókváltás", + "subjects": "Tantárgyak", }, "de_de": { "personal_details": "Persönliche Angaben", @@ -242,6 +244,7 @@ extension SettingsLocalization on String { "personalization": "Personalisierung", "edit": "Bearbeiten", "switch_account": "Benutzer wechseln", + "subjects": "Themen", }, }; diff --git a/filcnaplo_mobile_ui/lib/screens/settings/submenu/personalize_screen.dart b/filcnaplo_mobile_ui/lib/screens/settings/submenu/personalize_screen.dart index 36ad1a8..21f35c5 100644 --- a/filcnaplo_mobile_ui/lib/screens/settings/submenu/personalize_screen.dart +++ b/filcnaplo_mobile_ui/lib/screens/settings/submenu/personalize_screen.dart @@ -1,11 +1,19 @@ -// import 'package:filcnaplo/models/settings.dart'; +// ignore_for_file: use_build_context_synchronously + +import 'package:filcnaplo/helpers/subject.dart'; +import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/theme/colors/colors.dart'; +import 'package:filcnaplo/utils/format.dart'; +import 'package:filcnaplo_kreta_api/models/subject.dart'; +import 'package:filcnaplo_kreta_api/providers/grade_provider.dart'; import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart'; +import 'package:filcnaplo_mobile_ui/common/splitted_panel/splitted_panel.dart'; +import 'package:filcnaplo_mobile_ui/screens/settings/settings_helper.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart'; -// import 'package:provider/provider.dart'; -import 'submenu_screen.i18n.dart'; +import 'package:provider/provider.dart'; +import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart'; class MenuPersonalizeSettings extends StatelessWidget { const MenuPersonalizeSettings({ @@ -39,27 +47,261 @@ class MenuPersonalizeSettings extends StatelessWidget { } } -class PersonalizeSettingsScreen extends StatelessWidget { +class PersonalizeSettingsScreen extends StatefulWidget { const PersonalizeSettingsScreen({super.key}); @override - Widget build(BuildContext context) { - // SettingsProvider settings = Provider.of(context); + PersonalizeSettingsScreenState createState() => + PersonalizeSettingsScreenState(); +} - return Scaffold( - appBar: AppBar( - surfaceTintColor: Theme.of(context).scaffoldBackgroundColor, - leading: BackButton(color: AppColors.of(context).text), +class PersonalizeSettingsScreenState extends State + with SingleTickerProviderStateMixin { + late SettingsProvider settingsProvider; + + late AnimationController _hideContainersController; + + late List subjects; + late List tiles; + + @override + void initState() { + super.initState(); + + subjects = Provider.of(context, listen: false) + .grades + .map((e) => e.subject) + .toSet() + .toList() + ..sort((a, b) => a.name.compareTo(b.name)); + + _hideContainersController = AnimationController( + vsync: this, duration: const Duration(milliseconds: 200)); + } + + void buildSubjectTiles() { + List subjectTiles = []; + + var i = 0; + + for (var s in subjects) { + Widget widget = PanelButton( + onPressed: () { + // TODO: open subject's config page + }, title: Text( - "personalization".i18n, - style: TextStyle(color: AppColors.of(context).text), + (s.isRenamed ? s.renamedTo : s.name.capital()) ?? '', + style: TextStyle( + color: AppColors.of(context).text.withOpacity(.95), + ), ), - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0), - child: Column( - children: [], + leading: Icon( + SubjectIcon.resolveVariant(context: context, subject: s), + size: 22.0, + color: AppColors.of(context).text.withOpacity(.95), + ), + trailing: Icon( + FeatherIcons.chevronRight, + size: 22.0, + color: AppColors.of(context).text.withOpacity(0.95), + ), + borderRadius: BorderRadius.vertical( + top: Radius.circular(i == 0 ? 12.0 : 4.0), + bottom: Radius.circular(i + 1 == subjects.length ? 12.0 : 4.0), + ), + ); + + i += 1; + subjectTiles.add(widget); + } + + tiles = subjectTiles; + } + + @override + Widget build(BuildContext context) { + settingsProvider = Provider.of(context); + + String themeModeText = { + ThemeMode.light: "light".i18n, + ThemeMode.dark: "dark".i18n, + ThemeMode.system: "system".i18n + }[settingsProvider.theme] ?? + "?"; + + buildSubjectTiles(); + + return AnimatedBuilder( + animation: _hideContainersController, + builder: (context, child) => Opacity( + opacity: 1 - _hideContainersController.value, + child: Scaffold( + appBar: AppBar( + surfaceTintColor: Theme.of(context).scaffoldBackgroundColor, + leading: BackButton(color: AppColors.of(context).text), + title: Text( + "personalization".i18n, + style: TextStyle(color: AppColors.of(context).text), + ), + ), + body: SingleChildScrollView( + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0), + child: Column( + children: [ + SplittedPanel( + padding: const EdgeInsets.only(top: 8.0), + cardPadding: const EdgeInsets.all(4.0), + isSeparated: true, + children: [ + PanelButton( + onPressed: () { + SettingsHelper.theme(context); + setState(() {}); + }, + title: Text("theme".i18n), + leading: Icon( + FeatherIcons.sun, + size: 22.0, + color: AppColors.of(context).text.withOpacity(0.95), + ), + trailing: Text( + themeModeText, + style: const TextStyle(fontSize: 14.0), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12.0), + bottom: Radius.circular(12.0), + ), + ), + ], + ), + SplittedPanel( + padding: const EdgeInsets.only(top: 9.0), + cardPadding: const EdgeInsets.all(4.0), + isSeparated: true, + children: [ + PanelButton( + padding: const EdgeInsets.only(left: 14.0, right: 14.0), + onPressed: () async { + await _hideContainersController.forward(); + SettingsHelper.accentColor(context); + setState(() {}); + _hideContainersController.reset(); + }, + title: Text( + "color".i18n, + style: TextStyle( + color: AppColors.of(context).text.withOpacity(.95), + ), + ), + leading: Icon( + FeatherIcons.droplet, + size: 22.0, + color: AppColors.of(context).text.withOpacity(.95), + ), + trailing: Container( + width: 12.0, + height: 12.0, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondary, + shape: BoxShape.circle, + ), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12.0), + bottom: Radius.circular(12.0), + ), + ), + ], + ), + SplittedPanel( + padding: const EdgeInsets.only(top: 9.0), + cardPadding: const EdgeInsets.all(4.0), + isSeparated: true, + children: [ + PanelButton( + onPressed: () { + SettingsHelper.iconPack(context); + }, + title: Text( + "icon_pack".i18n, + style: TextStyle( + color: AppColors.of(context).text.withOpacity(.95), + ), + ), + leading: Icon( + FeatherIcons.grid, + size: 22.0, + color: AppColors.of(context).text.withOpacity(.95), + ), + trailing: Text( + settingsProvider.iconPack.name.capital(), + style: const TextStyle(fontSize: 14.0), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12.0), + bottom: Radius.circular(12.0), + ), + ), + ], + ), + SplittedPanel( + padding: const EdgeInsets.only(top: 9.0), + cardPadding: const EdgeInsets.all(4.0), + isSeparated: true, + children: [ + PanelButton( + onPressed: () { + SettingsHelper.gradeColors(context); + setState(() {}); + }, + title: Text( + "grade_colors".i18n, + style: TextStyle( + color: AppColors.of(context).text.withOpacity(.95), + ), + ), + leading: Icon( + FeatherIcons.star, + size: 22.0, + color: AppColors.of(context).text.withOpacity(.95), + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: List.generate( + 5, + (i) => Container( + margin: const EdgeInsets.only(left: 2.0), + width: 12.0, + height: 12.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: settingsProvider.gradeColors[i], + ), + ), + ), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12.0), + bottom: Radius.circular(12.0), + ), + ), + ], + ), + const SizedBox( + height: 18.0, + ), + SplittedPanel( + title: Text('subjects'.i18n), + padding: EdgeInsets.zero, + cardPadding: const EdgeInsets.all(4.0), + children: tiles, + ), + ], + ), + ), ), ), ),