11import 'dart:convert' ;
22import 'dart:ui' ;
33
4+ import 'package:arabic_learning/vars/config_structure.dart' show ClassItem, SourceItem, WordItem;
45import 'package:flutter/material.dart' ;
56import 'package:provider/provider.dart' ;
67
@@ -35,20 +36,30 @@ import 'package:arabic_learning/funcs/utili.dart';
3536/// List<List<String>> value = await popSelectClasses(context);
3637/// List<Map<String, dynamic>> words = getSelectedWords(context , forceSelectClasses: value);
3738/// ```
38- Future <List <List < String > >> popSelectClasses (BuildContext context, {bool withCache = false }) async {
39+ Future <List <ClassItem >> popSelectClasses (BuildContext context, {bool withCache = false }) async {
3940 context.read <Global >().uiLogger.info ("弹出课程选择(ClassSelectPage),withCache: $withCache " );
40- late final List <List < String >> beforeSelectedClasses;
41+ final List <ClassItem > beforeSelectedClasses = [] ;
4142 if (withCache) {
4243 final String tpcPrefs = context.read <Global >().prefs.getString ("tempConfig" ) ?? jsonEncode (StaticsVar .tempConfig);
43- beforeSelectedClasses = (jsonDecode (tpcPrefs)["SelectedClasses" ] as List )
44+ final List < List < String >> cacheList = (jsonDecode (tpcPrefs)["SelectedClasses" ] as List )
4445 .cast <List >()
4546 .map ((e) => e.cast <String >().toList ())
4647 .toList ();
48+ for (List <String > cachedClass in cacheList) {
49+ for (SourceItem sourceItem in context.read <Global >().wordData.classes){
50+ if (sourceItem.sourceJsonFileName != cachedClass[0 ]){
51+ continue ;
52+ }
53+ if (sourceItem.subClasses.any ((ClassItem classItem) => classItem.className == cachedClass[1 ])){
54+ beforeSelectedClasses.add (
55+ sourceItem.subClasses.firstWhere ((ClassItem classItem) => classItem.className == cachedClass[1 ])
56+ );
57+ }
58+ }
59+ }
4760 context.read <Global >().uiLogger.fine ("已缓存课程选择: $beforeSelectedClasses " );
48- } else {
49- beforeSelectedClasses = [];
5061 }
51- List <List < String >> ? selectedClasses = await showModalBottomSheet <List <List < String > >>(
62+ List <ClassItem > ? selectedClasses = await showModalBottomSheet <List <ClassItem >>(
5263 context: context,
5364 // 假装圆角... :)
5465 shape: RoundedRectangleBorder (side: BorderSide (width: 1.0 , color: Theme .of (context).colorScheme.onSurface.withAlpha (150 )), borderRadius: StaticsVar .br),
@@ -67,7 +78,7 @@ Future<List<List<String>>> popSelectClasses(BuildContext context, {bool withCach
6778 context.read <Global >().uiLogger.info ("课程选择缓存完成" );
6879 }
6980 if (context.mounted) context.read <Global >().uiLogger.fine ("选择的课程: $selectedClasses " );
70- return selectedClasses ?? [];
81+ return selectedClasses?? [];
7182}
7283
7384
@@ -82,11 +93,11 @@ Future<List<List<String>>> popSelectClasses(BuildContext context, {bool withCach
8293/// [isClassSelected] :需要一个函数判断该课程是否被选中
8394///
8495/// 一般情况下该函数只会在 [ClassSelectPage] 中被使用,若非必要你不应该使用此函数
85- List <Widget > classesSelectionList (BuildContext context, Function (List < String > ) onChanged, bool Function (List < String > ) isClassSelected) {
96+ List <Widget > classesSelectionList (BuildContext context, Function (ClassItem ) onChanged, bool Function (ClassItem ) isClassSelected) {
8697 context.read <Global >().uiLogger.fine ("构建课程选择列表" );
87- Map < String , dynamic > wordData = context.read <Global >().wordData;
98+ List < SourceItem > sourcesList = context.read <Global >().wordData.classes ;
8899 List <Widget > widgetList = [];
89- for (String sourceName in wordData[ "Classes" ].keys ) {
100+ for (SourceItem source in sourcesList ) {
90101 widgetList.add (
91102 Container (
92103 margin: EdgeInsets .all (16.0 ),
@@ -96,7 +107,7 @@ List<Widget> classesSelectionList(BuildContext context, Function (List<String>)
96107 borderRadius: StaticsVar .br,
97108 ),
98109 child: Text (
99- sourceName ,
110+ source.sourceJsonFileName ,
100111 style: TextStyle (
101112 fontSize: 16.0 ,
102113 fontWeight: FontWeight .bold,
@@ -105,7 +116,7 @@ List<Widget> classesSelectionList(BuildContext context, Function (List<String>)
105116 ),
106117 );
107118 bool isEven = true ;
108- for (String className in wordData[ "Classes" ][sourceName].keys ){
119+ for (ClassItem classItem in source.subClasses ){
109120 widgetList.add (
110121 Container (
111122 margin: EdgeInsets .all (2 ),
@@ -116,11 +127,11 @@ List<Widget> classesSelectionList(BuildContext context, Function (List<String>)
116127 child: StatefulBuilder (
117128 builder: (context, setLocalState) {
118129 return CheckboxListTile (
119- title: Text (className),
120- value: isClassSelected ([sourceName, className] ),
130+ title: Text (classItem. className),
131+ value: isClassSelected (classItem ),
121132 onChanged: (value) {
122133 setLocalState (() {
123- onChanged ([sourceName, className] );
134+ onChanged (classItem );
124135 });
125136 },
126137 );
@@ -190,7 +201,7 @@ void alart(BuildContext context, String e, {Function? onConfirmed, Duration dela
190201}
191202
192203/// 弹出详解页面
193- void viewAnswer (BuildContext context, Map < String , dynamic > wordData) async {
204+ void viewAnswer (BuildContext context, WordItem wordData) async {
194205 context.read <Global >().uiLogger.info ("弹出详解页面" );
195206 MediaQueryData mediaQuery = MediaQuery .of (context);
196207 showBottomSheet (
@@ -445,7 +456,7 @@ class _ChooseButtonBoxState extends State<ChooseButtonBox> {
445456///
446457/// [useMask] :是否显示高斯遮罩
447458class WordCard extends StatelessWidget {
448- final Map < String , dynamic > word;
459+ final WordItem word;
449460 final double ? width;
450461 final double ? height;
451462 final bool useMask;
@@ -468,9 +479,9 @@ class WordCard extends StatelessWidget {
468479 padding: const EdgeInsets .all (16.0 ),
469480 ),
470481 icon: const Icon (Icons .volume_up, size: 24.0 ),
471- label: FittedBox (child: Text (word[ " arabic" ] , style: TextStyle (fontSize: 64.0 , fontFamily: context.read <Global >().arFont))),
482+ label: FittedBox (child: Text (word. arabic, style: TextStyle (fontSize: 64.0 , fontFamily: context.read <Global >().arFont))),
472483 onPressed: (){
473- playTextToSpeech (word[ " arabic" ] , context);
484+ playTextToSpeech (word. arabic, context);
474485 },
475486 ),
476487 Stack (
@@ -483,7 +494,7 @@ class WordCard extends StatelessWidget {
483494 borderRadius: BorderRadius .vertical (bottom: Radius .circular (25.0 )),
484495 ),
485496 child: Center (
486- child: Text (' 中文:${word [ " chinese" ] }\n 示例:${word [ " explanation" ] }\n 归属课程:${word [ "subClass" ] }' ,
497+ child: Text (' 中文:${word . chinese }\n 示例:${word . explanation }\n 归属课程:${word . className }' ,
487498 style: Theme .of (context).textTheme.bodyLarge,
488499 textAlign: TextAlign .left,
489500 ),
@@ -541,22 +552,22 @@ class WordCard extends StatelessWidget {
541552///
542553/// 注意:如果你要进行课程选择,请先考虑 [popSelectClasses] 函数,这是一个已经基本成熟的实现
543554class ClassSelectPage extends StatelessWidget {
544- final List <List < String > > beforeSelectedClasses;
555+ final List <ClassItem > beforeSelectedClasses;
545556 const ClassSelectPage ({super .key, this .beforeSelectedClasses = const []});
546557 @override
547558 Widget build (BuildContext context) {
548- final mediaQuery = MediaQuery .of (context);
549- List <List < String > > selectedClass = beforeSelectedClasses.toList ();
550- void addClass (List < String > classInfo) {
559+ final MediaQueryData mediaQuery = MediaQuery .of (context);
560+ List <ClassItem > selectedClass = beforeSelectedClasses.toList ();
561+ void addClass (ClassItem classInfo) {
551562 selectedClass.add (classInfo);
552563 }
553- void removeClass (List < String > classInfo) {
554- selectedClass.removeWhere ((e) => e[ 0 ] == classInfo[ 0 ] && e[ 1 ] == classInfo[ 1 ] );
564+ void removeClass (ClassItem classInfo) {
565+ selectedClass.remove ( classInfo);
555566 }
556- bool isClassSelected (List < String > classInfo) {
557- return selectedClass.any ((e) => e[ 0 ] == classInfo[ 0 ] && e[ 1 ] == classInfo[ 1 ] );
567+ bool isClassSelected (ClassItem classInfo) {
568+ return selectedClass.any ((e) => e== classInfo);
558569 }
559- void onClassChanged (List < String > classInfo) {
570+ void onClassChanged (ClassItem classInfo) {
560571 if (isClassSelected (classInfo)) {
561572 removeClass (classInfo);
562573 } else {
@@ -800,14 +811,14 @@ class _ChoiceQuestions extends State<ChoiceQuestions> {
800811///
801812/// [bottomWidget] :题目下方的组件,可用于翻页之类的其他功能,自行设置
802813class WordCardQuestion extends StatelessWidget {
803- final Map < String , dynamic > word;
814+ final WordItem word;
804815 final String ? hint;
805816 final Widget ? bottomWidget;
806817 const WordCardQuestion ({super .key, required this .word, this .hint, this .bottomWidget});
807818
808819 @override
809820 Widget build (BuildContext context) {
810- context.read <Global >().uiLogger.info ("构建单词卡片页面,主单词: ${word [ " arabic" ] }" );
821+ context.read <Global >().uiLogger.info ("构建单词卡片页面,主单词: ${word . arabic }" );
811822 MediaQueryData mediaQuery = MediaQuery .of (context);
812823 return Material (
813824 child: Column (
0 commit comments