Commit 22f362320722bc706da82d9fd40629dde0345b76
1 parent
aa0d2360
feat:过渡页-练习环节
Showing
9 changed files
with
154 additions
and
60 deletions
lib/pages/practice/bloc/topic_picture_bloc.dart
| ... | ... | @@ -9,10 +9,14 @@ import 'package:wow_english/common/extension/string_extension.dart'; |
| 9 | 9 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
| 10 | 10 | import 'package:wow_english/common/request/exception.dart'; |
| 11 | 11 | import 'package:wow_english/models/course_process_entity.dart'; |
| 12 | +import 'package:wow_english/pages/section/subsection/base_section/bloc.dart'; | |
| 13 | +import 'package:wow_english/pages/section/subsection/base_section/event.dart'; | |
| 14 | +import 'package:wow_english/pages/section/subsection/base_section/state.dart'; | |
| 12 | 15 | import 'package:wow_english/utils/loading.dart'; |
| 13 | 16 | import 'package:wow_english/utils/toast_util.dart'; |
| 14 | 17 | |
| 15 | 18 | import '../../../common/permission/permissionRequestPage.dart'; |
| 19 | +import '../../../route/route.dart'; | |
| 16 | 20 | |
| 17 | 21 | part 'topic_picture_event.dart'; |
| 18 | 22 | part 'topic_picture_state.dart'; |
| ... | ... | @@ -28,7 +32,7 @@ enum VoicePlayState { |
| 28 | 32 | stop |
| 29 | 33 | } |
| 30 | 34 | |
| 31 | -class TopicPictureBloc extends Bloc<TopicPictureEvent, TopicPictureState> { | |
| 35 | +class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> { | |
| 32 | 36 | |
| 33 | 37 | final PageController pageController; |
| 34 | 38 | |
| ... | ... | @@ -94,11 +98,15 @@ class TopicPictureBloc extends Bloc<TopicPictureEvent, TopicPictureState> { |
| 94 | 98 | _forbiddenWhenCorrect = false; |
| 95 | 99 | debugPrint('播放完成后解除禁止'); |
| 96 | 100 | if (event == PlayerState.completed) { |
| 97 | - // 答对后且播放完自动翻页 | |
| 98 | - pageController.nextPage( | |
| 99 | - duration: const Duration(milliseconds: 500), | |
| 100 | - curve: Curves.ease, | |
| 101 | - ); | |
| 101 | + if (isLastPage()) { | |
| 102 | + showStepPage(); | |
| 103 | + } else { | |
| 104 | + // 答对后且播放完自动翻页 | |
| 105 | + pageController.nextPage( | |
| 106 | + duration: const Duration(milliseconds: 500), | |
| 107 | + curve: Curves.ease, | |
| 108 | + ); | |
| 109 | + } | |
| 102 | 110 | } |
| 103 | 111 | } |
| 104 | 112 | } |
| ... | ... | @@ -263,6 +271,9 @@ class TopicPictureBloc extends Bloc<TopicPictureEvent, TopicPictureState> { |
| 263 | 271 | showToast('测评成功,分数是$overall',duration: const Duration(seconds: 5)); |
| 264 | 272 | _isVoicing = false; |
| 265 | 273 | emitter(XSVoiceTestState()); |
| 274 | + if (isLastPage()) { | |
| 275 | + showStepPage(); | |
| 276 | + } | |
| 266 | 277 | } |
| 267 | 278 | |
| 268 | 279 | // 暂时没用上 |
| ... | ... | @@ -288,6 +299,7 @@ class TopicPictureBloc extends Bloc<TopicPictureEvent, TopicPictureState> { |
| 288 | 299 | } |
| 289 | 300 | } |
| 290 | 301 | |
| 302 | + ///播放选择结果音效 | |
| 291 | 303 | void _playResultSound(bool isCorrect) async { |
| 292 | 304 | // await audioPlayer.stop(); |
| 293 | 305 | if (audioPlayer.state == PlayerState.playing && _isResultSoundPlaying == false) { |
| ... | ... | @@ -302,4 +314,26 @@ class TopicPictureBloc extends Bloc<TopicPictureEvent, TopicPictureState> { |
| 302 | 314 | await audioPlayer.play(AssetSource('incorrect_voice'.assetMp3)); |
| 303 | 315 | } |
| 304 | 316 | } |
| 317 | + | |
| 318 | + ///是否是最后一页 | |
| 319 | + bool isLastPage() { | |
| 320 | + return currentPage == _entity?.topics?.length; | |
| 321 | + } | |
| 322 | + | |
| 323 | + ///展示过渡页 | |
| 324 | + void showStepPage() { | |
| 325 | + ///如果最后一页是语音问答题,评测完后自动翻页 | |
| 326 | + sectionComplete(() { | |
| 327 | + popPage( | |
| 328 | + data:{ | |
| 329 | + 'currentStep':currentPage.toString(), | |
| 330 | + 'courseLessonId':courseLessonId, | |
| 331 | + 'isLastPage': true, | |
| 332 | + 'nextSection': true | |
| 333 | + }); | |
| 334 | + }, againSectionTap: () { | |
| 335 | + debugPrint("WQF 重做"); | |
| 336 | + pageController.jumpToPage(0); | |
| 337 | + }); | |
| 338 | + } | |
| 305 | 339 | } | ... | ... |
lib/pages/practice/bloc/topic_picture_event.dart
lib/pages/practice/bloc/topic_picture_state.dart
lib/pages/practice/topic_picture_page.dart
| ... | ... | @@ -6,6 +6,7 @@ import 'package:wow_english/common/core/user_util.dart'; |
| 6 | 6 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 7 | 7 | import 'package:wow_english/common/widgets/ow_image_widget.dart'; |
| 8 | 8 | import 'package:wow_english/models/course_process_entity.dart'; |
| 9 | +import 'package:wow_english/pages/practice/topic_type.dart'; | |
| 9 | 10 | import 'package:wow_english/route/route.dart'; |
| 10 | 11 | import 'package:wow_english/utils/toast_util.dart'; |
| 11 | 12 | |
| ... | ... | @@ -71,7 +72,8 @@ class _TopicPicturePage extends StatelessWidget { |
| 71 | 72 | popPage( |
| 72 | 73 | data:{ |
| 73 | 74 | 'currentStep':bloc.currentPage.toString(), |
| 74 | - 'courseLessonId':bloc.courseLessonId | |
| 75 | + 'courseLessonId':bloc.courseLessonId, | |
| 76 | + 'isLastPage': bloc.isLastPage(), | |
| 75 | 77 | }); |
| 76 | 78 | // Navigator.pop(context); |
| 77 | 79 | }, |
| ... | ... | @@ -86,13 +88,13 @@ class _TopicPicturePage extends StatelessWidget { |
| 86 | 88 | }, |
| 87 | 89 | itemBuilder: (BuildContext context,int index){ |
| 88 | 90 | CourseProcessTopics? topics = bloc.entity?.topics![index]; |
| 89 | - if (topics?.type == 1) {//听音选图 | |
| 91 | + if (topics?.type == TopicType.audioImageSelect.value) {//听音选图 | |
| 90 | 92 | return _pageViewVoicePictureItemWidget(topics); |
| 91 | - } else if (topics?.type == 2) {//听音选字 | |
| 93 | + } else if (topics?.type == TopicType.audioCharSelect.value) {//听音选字 | |
| 92 | 94 | return _pageViewVoiceWordItemWidget(topics); |
| 93 | - } else if (topics?.type == 3) {//看题选字 | |
| 95 | + } else if (topics?.type == TopicType.questionCharSelect.value) {//看题选字 | |
| 94 | 96 | return _pageViewWordItemWidget(topics); |
| 95 | - } else if (topics?.type == 4) {//看题选图 | |
| 97 | + } else if (topics?.type == TopicType.questionImageSelect.value) {//看题选图 | |
| 96 | 98 | return _pageViewItemWidget(topics); |
| 97 | 99 | } else {//语音问答 |
| 98 | 100 | return _voiceAnswerItem(topics); | ... | ... |
lib/pages/practice/topic_type.dart
0 → 100644
| 1 | +///练习(题型)类型 | |
| 2 | +enum TopicType { | |
| 3 | + ///听音选图 | |
| 4 | + audioImageSelect, | |
| 5 | + | |
| 6 | + ///听音选字 | |
| 7 | + audioCharSelect, | |
| 8 | + | |
| 9 | + ///看题选字 | |
| 10 | + questionCharSelect, | |
| 11 | + | |
| 12 | + ///看题选图 | |
| 13 | + questionImageSelect, | |
| 14 | + | |
| 15 | + ///语音问答 | |
| 16 | + voiceQuestion | |
| 17 | +} | |
| 18 | + | |
| 19 | +extension TopicTypeExtension on TopicType { | |
| 20 | + int get value { | |
| 21 | + switch (this) { | |
| 22 | + case TopicType.audioImageSelect: | |
| 23 | + return 1; | |
| 24 | + case TopicType.audioCharSelect: | |
| 25 | + return 2; | |
| 26 | + case TopicType.questionCharSelect: | |
| 27 | + return 3; | |
| 28 | + case TopicType.questionImageSelect: | |
| 29 | + return 4; | |
| 30 | + case TopicType.voiceQuestion: | |
| 31 | + return 5; | |
| 32 | + default: | |
| 33 | + throw ArgumentError('Unknown topic type'); | |
| 34 | + } | |
| 35 | + } | |
| 36 | +} | ... | ... |
lib/pages/section/bloc/section_bloc.dart
| ... | ... | @@ -46,19 +46,22 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
| 46 | 46 | |
| 47 | 47 | CourseProcessEntity? get processEntity => _processEntity; |
| 48 | 48 | |
| 49 | - SectionBloc(this._courseUnitEntity, this._courseUnitDetail, this._pageController, this._listController) : super(LessonInitial()) { | |
| 49 | + SectionBloc(this._courseUnitEntity, this._courseUnitDetail, | |
| 50 | + this._pageController, this._listController) | |
| 51 | + : super(LessonInitial()) { | |
| 50 | 52 | on<RequestDataEvent>(_requestData); |
| 51 | - on<RequestExitClassEvent>(_requestExitClass); | |
| 52 | 53 | on<RequestEndClassEvent>(_requestEndClass); |
| 53 | 54 | on<RequestEnterClassEvent>(_requestEnterClass); |
| 54 | 55 | on<RequestVideoLessonEvent>(_requestVideoLesson); |
| 55 | 56 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
| 56 | 57 | } |
| 57 | 58 | |
| 58 | - void _requestData(RequestDataEvent event, Emitter<SectionState> emitter) async { | |
| 59 | + void _requestData( | |
| 60 | + RequestDataEvent event, Emitter<SectionState> emitter) async { | |
| 59 | 61 | try { |
| 60 | 62 | await loading(() async { |
| 61 | - _courseSectionDatas = await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!); | |
| 63 | + _courseSectionDatas = | |
| 64 | + await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!); | |
| 62 | 65 | emitter(LessonDataLoadState()); |
| 63 | 66 | }); |
| 64 | 67 | } catch (e) { |
| ... | ... | @@ -68,68 +71,84 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
| 68 | 71 | } |
| 69 | 72 | } |
| 70 | 73 | |
| 71 | - void _requestVideoLesson(RequestVideoLessonEvent event, Emitter<SectionState> emitter) async { | |
| 74 | + void _requestVideoLesson( | |
| 75 | + RequestVideoLessonEvent event, Emitter<SectionState> emitter) async { | |
| 72 | 76 | try { |
| 73 | 77 | await loading(() async { |
| 74 | 78 | _processEntity = await ListenDao.process(event.courseLessonId); |
| 75 | - emitter(RequestVideoLessonState(event.courseLessonId,event.courseType)); | |
| 79 | + emitter( | |
| 80 | + RequestVideoLessonState(event.courseLessonId, event.courseType)); | |
| 76 | 81 | }); |
| 77 | 82 | } catch (e) { |
| 78 | 83 | if (e is ApiException) { |
| 79 | - showToast(e.message??'请求失败,请检查网络连接'); | |
| 84 | + showToast(e.message ?? '请求失败,请检查网络连接'); | |
| 80 | 85 | } |
| 81 | 86 | } |
| 82 | 87 | } |
| 83 | 88 | |
| 84 | - | |
| 85 | - void _requestEnterClass(RequestEnterClassEvent event,Emitter<SectionState> emitter) async { | |
| 89 | + void _requestEnterClass( | |
| 90 | + RequestEnterClassEvent event, Emitter<SectionState> emitter) async { | |
| 86 | 91 | try { |
| 87 | 92 | await loading(() async { |
| 88 | - await ListenDao.enterClass(event.courseLessonId); | |
| 89 | - emitter(RequestEnterClassState(event.courseLessonId,event.courseType)); | |
| 93 | + await ListenDao.enterClass(event.courseLessonId); | |
| 94 | + emitter(RequestEnterClassState(event.courseLessonId, event.courseType)); | |
| 90 | 95 | }); |
| 91 | 96 | } catch (e) { |
| 92 | 97 | if (e is ApiException) { |
| 93 | - showToast(e.message??'请求失败,请检查网络连接'); | |
| 98 | + showToast(e.message ?? '请求失败,请检查网络连接'); | |
| 94 | 99 | } |
| 95 | 100 | } |
| 96 | 101 | } |
| 97 | 102 | |
| 98 | - void _requestExitClass(RequestExitClassEvent event,Emitter<SectionState> emitter) async { | |
| 99 | - await ListenDao.exitClass(event.courseLessonId,event.currentStep); | |
| 100 | - } | |
| 101 | - | |
| 102 | - void _requestEndClass(RequestEndClassEvent event,Emitter<SectionState> emitter) async { | |
| 103 | - final obj = await ListenDao.endClass(event.courseLessonId,event.currentStep); | |
| 103 | + void _requestEndClass( | |
| 104 | + RequestEndClassEvent event, Emitter<SectionState> emitter) async { | |
| 105 | + if (event.isLastPage) { | |
| 106 | + await await ListenDao.endClass(event.courseLessonId, event.currentStep, | |
| 107 | + currentTime: event.currentTime); | |
| 108 | + } else { | |
| 109 | + await await ListenDao.exitClass(event.courseLessonId, event.currentStep, | |
| 110 | + currentTime: event.currentTime); | |
| 111 | + } | |
| 112 | + debugPrint("WQF _requestEndClass autoNextSection=${event.autoNextSection}"); | |
| 104 | 113 | if (event.autoNextSection) { |
| 105 | - final nextCourseSection = getNextCourseSectionBySort(int.parse(event.courseLessonId)); | |
| 114 | + final nextCourseSection = | |
| 115 | + getNextCourseSectionBySort(int.parse(event.courseLessonId)); | |
| 116 | + debugPrint("WQF nextCourseSection = $nextCourseSection"); | |
| 106 | 117 | ///进入课堂 |
| 107 | - add(RequestEnterClassEvent(nextCourseSection!.id.toString() ?? '', nextCourseSection.courseType)); | |
| 118 | + add(RequestEnterClassEvent(nextCourseSection!.id.toString(), | |
| 119 | + nextCourseSection.courseType)); | |
| 108 | 120 | } |
| 109 | 121 | } |
| 110 | 122 | |
| 111 | - void _pageControllerChange(CurrentUnitIndexChangeEvent event, | |
| 112 | - Emitter<SectionState> emitter) async { | |
| 123 | + void _pageControllerChange( | |
| 124 | + CurrentUnitIndexChangeEvent event, Emitter<SectionState> emitter) async { | |
| 113 | 125 | _currentPage = event.unitIndex; |
| 114 | 126 | emitter(CurrentPageIndexState()); |
| 115 | 127 | } |
| 116 | 128 | |
| 117 | 129 | // 未锁定的页数 |
| 118 | 130 | int unlockPageCount() { |
| 119 | - return _courseUnitEntity.courseUnitVOList?.indexWhereOrNull((element) => element.lock == true) ?? 1; | |
| 131 | + return _courseUnitEntity.courseUnitVOList | |
| 132 | + ?.indexWhereOrNull((element) => element.lock == true) ?? | |
| 133 | + 1; | |
| 120 | 134 | } |
| 121 | 135 | |
| 122 | 136 | CourseSectionEntity? getNextCourseSectionBySort(int courseLessonId) { |
| 123 | - final curCourseSectionEntity = _courseSectionDatas?.firstWhere((element) => element.id == courseLessonId); | |
| 137 | + final curCourseSectionEntity = _courseSectionDatas | |
| 138 | + ?.firstWhere((element) => element.id == courseLessonId); | |
| 124 | 139 | final curSort = curCourseSectionEntity?.sortOrder ?? 0; |
| 125 | - CourseSectionEntity? nextCourseSectionEntity = _courseSectionDatas?.firstWhere((element) => element.sortOrder == curSort + 1); | |
| 140 | + CourseSectionEntity? nextCourseSectionEntity = _courseSectionDatas | |
| 141 | + ?.firstWhere((element) => element.sortOrder == curSort + 1); | |
| 126 | 142 | if (nextCourseSectionEntity != null) { |
| 127 | 143 | return nextCourseSectionEntity; |
| 128 | 144 | } else { |
| 129 | 145 | ///跨unit选lesson |
| 130 | - final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList?.firstWhere((element) => element.id == curCourseSectionEntity?.courseUnitId); | |
| 146 | + final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList | |
| 147 | + ?.firstWhere( | |
| 148 | + (element) => element.id == curCourseSectionEntity?.courseUnitId); | |
| 131 | 149 | if (curCourseUnitDetail != null) { |
| 132 | - final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList?.firstWhere((element) => element.sortOrder == 0); | |
| 150 | + final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList | |
| 151 | + ?.firstWhere((element) => element.sortOrder == 0); | |
| 133 | 152 | if (nextCourseUnitDetail != null) { |
| 134 | 153 | ///pageView翻页了,可能需要预加载 todo |
| 135 | 154 | return null; | ... | ... |
lib/pages/section/bloc/section_event.dart
| ... | ... | @@ -9,6 +9,7 @@ class RequestDataEvent extends SectionEvent {} |
| 9 | 9 | class RequestVideoLessonEvent extends SectionEvent { |
| 10 | 10 | final String courseLessonId; |
| 11 | 11 | final int courseType; |
| 12 | + | |
| 12 | 13 | RequestVideoLessonEvent(this.courseLessonId, this.courseType); |
| 13 | 14 | } |
| 14 | 15 | |
| ... | ... | @@ -16,29 +17,29 @@ class RequestVideoLessonEvent extends SectionEvent { |
| 16 | 17 | class RequestEnterClassEvent extends SectionEvent { |
| 17 | 18 | final String courseLessonId; |
| 18 | 19 | final int courseType; |
| 19 | - RequestEnterClassEvent(this.courseLessonId,this.courseType); | |
| 20 | -} | |
| 21 | 20 | |
| 22 | -///退出课堂 | |
| 23 | -class RequestExitClassEvent extends SectionEvent { | |
| 24 | - final String courseLessonId; | |
| 25 | - final String currentStep; | |
| 26 | - final String currentTime; | |
| 27 | - RequestExitClassEvent(this.courseLessonId,this.currentStep,this.currentTime); | |
| 21 | + RequestEnterClassEvent(this.courseLessonId, this.courseType); | |
| 28 | 22 | } |
| 29 | 23 | |
| 30 | 24 | ///结束课堂 |
| 31 | 25 | class RequestEndClassEvent extends SectionEvent { |
| 32 | 26 | final String courseLessonId; |
| 33 | 27 | final String currentStep; |
| 34 | - final String currentTime; | |
| 28 | + | |
| 29 | + ///是否是最后一页(决定调结束接口还是退出接口) | |
| 30 | + final bool isLastPage; | |
| 31 | + final int? currentTime; | |
| 32 | + | |
| 35 | 33 | ///自动进入下一环节 |
| 36 | 34 | final bool autoNextSection; |
| 37 | - RequestEndClassEvent(this.courseLessonId,this.currentStep,this.currentTime,{this.autoNextSection = false}); | |
| 35 | + | |
| 36 | + RequestEndClassEvent(this.courseLessonId, this.currentStep, this.isLastPage, | |
| 37 | + {this.currentTime, this.autoNextSection = false}); | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | ///页面切换 |
| 41 | 41 | class CurrentUnitIndexChangeEvent extends SectionEvent { |
| 42 | 42 | final int unitIndex; |
| 43 | + | |
| 43 | 44 | CurrentUnitIndexChangeEvent(this.unitIndex); |
| 44 | 45 | } | ... | ... |
lib/pages/section/section_page.dart
| ... | ... | @@ -76,8 +76,8 @@ class _SectionPageView extends StatelessWidget { |
| 76 | 76 | }).then((value) { |
| 77 | 77 | if (value != null) { |
| 78 | 78 | Map<String, dynamic> dataMap = value as Map<String, dynamic>; |
| 79 | - bloc.add(RequestEndClassEvent(dataMap['courseLessonId']!, '0', | |
| 80 | - dataMap['currentTime']!, autoNextSection: dataMap['nextSection'] as bool)); | |
| 79 | + bloc.add(RequestEndClassEvent(dataMap['courseLessonId']!, | |
| 80 | + dataMap['currentTime']!, true, autoNextSection: dataMap['nextSection'] as bool)); | |
| 81 | 81 | } |
| 82 | 82 | }); |
| 83 | 83 | return; |
| ... | ... | @@ -99,9 +99,10 @@ class _SectionPageView extends StatelessWidget { |
| 99 | 99 | arguments: {'courseLessonId': state.courseLessonId}) |
| 100 | 100 | .then((value) { |
| 101 | 101 | if (value != null) { |
| 102 | - Map<String, String> dataMap = value as Map<String, String>; | |
| 103 | - bloc.add(RequestExitClassEvent( | |
| 104 | - dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); | |
| 102 | + Map<String, dynamic> dataMap = value as Map<String, dynamic>; | |
| 103 | + bloc.add(RequestEndClassEvent( | |
| 104 | + dataMap['courseLessonId']!, dataMap['currentStep']!, | |
| 105 | + dataMap['isLastPage']! as bool, autoNextSection: dataMap['nextSection'] as bool)); | |
| 105 | 106 | } |
| 106 | 107 | }); |
| 107 | 108 | return; |
| ... | ... | @@ -113,9 +114,10 @@ class _SectionPageView extends StatelessWidget { |
| 113 | 114 | arguments: {'courseLessonId': state.courseLessonId}) |
| 114 | 115 | .then((value) { |
| 115 | 116 | if (value != null) { |
| 116 | - Map<String, String> dataMap = value as Map<String, String>; | |
| 117 | - bloc.add(RequestExitClassEvent( | |
| 118 | - dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); | |
| 117 | + Map<String, dynamic> dataMap = value as Map<String, dynamic>; | |
| 118 | + bloc.add(RequestEndClassEvent( | |
| 119 | + dataMap['courseLessonId']!, dataMap['currentStep']!, | |
| 120 | + dataMap['isLastPage']! as bool, autoNextSection: dataMap['nextSection'] as bool)); | |
| 119 | 121 | } |
| 120 | 122 | }); |
| 121 | 123 | return; | ... | ... |
lib/pages/section/subsection/base_section/bloc.dart
| ... | ... | @@ -14,7 +14,7 @@ abstract class BaseSectionBloc<E extends BaseSectionEvent, |
| 14 | 14 | |
| 15 | 15 | ///这里可以定义一些通用的逻辑 |
| 16 | 16 | void sectionComplete(final VoidCallback? nextSectionTap, |
| 17 | - {BuildContext? context}) { | |
| 17 | + {VoidCallback? againSectionTap, BuildContext? context}) { | |
| 18 | 18 | // 逻辑来标记步骤为已完成 |
| 19 | 19 | // 比如更新状态 |
| 20 | 20 | if (isCompleteDialogShow) { |
| ... | ... | @@ -38,8 +38,8 @@ abstract class BaseSectionBloc<E extends BaseSectionEvent, |
| 38 | 38 | flex: 1, |
| 39 | 39 | child: GestureDetector( |
| 40 | 40 | onTap: () { |
| 41 | - add(SectionAgainEvent() as E); | |
| 42 | 41 | popPage(); |
| 42 | + againSectionTap!(); | |
| 43 | 43 | }, |
| 44 | 44 | child: Image.asset('section_finish_again'.assetPng), |
| 45 | 45 | ), | ... | ... |