Commit 5e2bbbd3eb6c517214a7f3def9c88dba5b32ddf8
1 parent
7d72793d
添加音频
Showing
14 changed files
with
163 additions
and
80 deletions
assets/images/reade_answer.gif
100755 → 100644
assets/images/voice.png
assets/sounds/count_with_me_instrumental.mp3
0 → 100644
No preview for this file type
assets/sounds/in_my_tummy_instrumental.mp3
0 → 100644
No preview for this file type
assets/sounds/touch_instrumental.mp3
0 → 100644
No preview for this file type
ios/Runner.xcodeproj/project.pbxproj
| @@ -2327,7 +2327,7 @@ | @@ -2327,7 +2327,7 @@ | ||
| 2327 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; | 2327 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; |
| 2328 | CODE_SIGN_IDENTITY = "Apple Development"; | 2328 | CODE_SIGN_IDENTITY = "Apple Development"; |
| 2329 | CODE_SIGN_STYLE = Automatic; | 2329 | CODE_SIGN_STYLE = Automatic; |
| 2330 | - CURRENT_PROJECT_VERSION = 15; | 2330 | + CURRENT_PROJECT_VERSION = 16; |
| 2331 | DEVELOPMENT_TEAM = T8P9KW8GWH; | 2331 | DEVELOPMENT_TEAM = T8P9KW8GWH; |
| 2332 | ENABLE_BITCODE = NO; | 2332 | ENABLE_BITCODE = NO; |
| 2333 | INFOPLIST_FILE = Runner/Info.plist; | 2333 | INFOPLIST_FILE = Runner/Info.plist; |
| @@ -2671,7 +2671,7 @@ | @@ -2671,7 +2671,7 @@ | ||
| 2671 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; | 2671 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; |
| 2672 | CODE_SIGN_IDENTITY = "Apple Development"; | 2672 | CODE_SIGN_IDENTITY = "Apple Development"; |
| 2673 | CODE_SIGN_STYLE = Automatic; | 2673 | CODE_SIGN_STYLE = Automatic; |
| 2674 | - CURRENT_PROJECT_VERSION = 15; | 2674 | + CURRENT_PROJECT_VERSION = 16; |
| 2675 | DEVELOPMENT_TEAM = T8P9KW8GWH; | 2675 | DEVELOPMENT_TEAM = T8P9KW8GWH; |
| 2676 | ENABLE_BITCODE = NO; | 2676 | ENABLE_BITCODE = NO; |
| 2677 | HEADER_SEARCH_PATHS = ( | 2677 | HEADER_SEARCH_PATHS = ( |
| @@ -2876,7 +2876,7 @@ | @@ -2876,7 +2876,7 @@ | ||
| 2876 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; | 2876 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; |
| 2877 | CODE_SIGN_IDENTITY = "Apple Development"; | 2877 | CODE_SIGN_IDENTITY = "Apple Development"; |
| 2878 | CODE_SIGN_STYLE = Automatic; | 2878 | CODE_SIGN_STYLE = Automatic; |
| 2879 | - CURRENT_PROJECT_VERSION = 15; | 2879 | + CURRENT_PROJECT_VERSION = 16; |
| 2880 | DEVELOPMENT_TEAM = T8P9KW8GWH; | 2880 | DEVELOPMENT_TEAM = T8P9KW8GWH; |
| 2881 | ENABLE_BITCODE = NO; | 2881 | ENABLE_BITCODE = NO; |
| 2882 | INFOPLIST_FILE = Runner/Info.plist; | 2882 | INFOPLIST_FILE = Runner/Info.plist; |
lib/pages/home/bloc.dart
| @@ -16,9 +16,25 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | @@ -16,9 +16,25 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | ||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | bool exchangeResult = false; | 18 | bool exchangeResult = false; |
| 19 | + late AudioPlayer audioPlayer; | ||
| 20 | + late AudioPlayer studyPlayer; | ||
| 21 | + late AudioPlayer gamePlayer; | ||
| 22 | + @override | ||
| 23 | + Future<void> close() { | ||
| 24 | + audioPlayer.release(); | ||
| 25 | + audioPlayer.dispose(); | ||
| 26 | + studyPlayer.release(); | ||
| 27 | + studyPlayer.dispose(); | ||
| 28 | + gamePlayer.release(); | ||
| 29 | + gamePlayer.dispose(); | ||
| 30 | + return super.close(); | ||
| 31 | + } | ||
| 19 | 32 | ||
| 20 | void _init(InitEvent event, Emitter<HomeState> emit) async { | 33 | void _init(InitEvent event, Emitter<HomeState> emit) async { |
| 21 | - AudioPlayer().play(AssetSource('welcome_to_wow'.assetMp3)); | 34 | + audioPlayer = AudioPlayer(playerId: 'audio'); |
| 35 | + gamePlayer = AudioPlayer(playerId: 'game'); | ||
| 36 | + studyPlayer = AudioPlayer(playerId: 'study'); | ||
| 37 | + audioPlayer.play(AssetSource('welcome_to_wow'.assetMp3)); | ||
| 22 | await _checkUpdate(emit); | 38 | await _checkUpdate(emit); |
| 23 | } | 39 | } |
| 24 | 40 |
lib/pages/home/view.dart
| @@ -71,7 +71,7 @@ class _HomePageView extends StatelessWidget { | @@ -71,7 +71,7 @@ class _HomePageView extends StatelessWidget { | ||
| 71 | child: GestureDetector( | 71 | child: GestureDetector( |
| 72 | onTap: () { | 72 | onTap: () { |
| 73 | _checkPermission(() { | 73 | _checkPermission(() { |
| 74 | - AudioPlayer() | 74 | + bloc.studyPlayer |
| 75 | .play(AssetSource('class_time'.assetMp3)); | 75 | .play(AssetSource('class_time'.assetMp3)); |
| 76 | pushNamed(AppRouteName.courseUnit) | 76 | pushNamed(AppRouteName.courseUnit) |
| 77 | .then((value) => { | 77 | .then((value) => { |
| @@ -136,7 +136,7 @@ class _HomePageView extends StatelessWidget { | @@ -136,7 +136,7 @@ class _HomePageView extends StatelessWidget { | ||
| 136 | return GestureDetector( | 136 | return GestureDetector( |
| 137 | onTap: () { | 137 | onTap: () { |
| 138 | _checkPermission(() { | 138 | _checkPermission(() { |
| 139 | - AudioPlayer().play( | 139 | + bloc.gamePlayer.play( |
| 140 | AssetSource('game_time'.assetMp3)); | 140 | AssetSource('game_time'.assetMp3)); |
| 141 | pushNamed(AppRouteName.games); | 141 | pushNamed(AppRouteName.games); |
| 142 | }, bloc); | 142 | }, bloc); |
lib/pages/reading/reading_page.dart
| @@ -155,6 +155,7 @@ class _ReadingPage extends StatelessWidget { | @@ -155,6 +155,7 @@ class _ReadingPage extends StatelessWidget { | ||
| 155 | margin: EdgeInsets.symmetric(horizontal: 10.w), | 155 | margin: EdgeInsets.symmetric(horizontal: 10.w), |
| 156 | child: Row( | 156 | child: Row( |
| 157 | children: [ | 157 | children: [ |
| 158 | + 5.horizontalSpace, | ||
| 158 | GestureDetector( | 159 | GestureDetector( |
| 159 | onTap: () { | 160 | onTap: () { |
| 160 | if (bloc.isRecording) { | 161 | if (bloc.isRecording) { |
lib/pages/section/bloc/section_bloc.dart
| 1 | +import 'package:audioplayers/audioplayers.dart'; | ||
| 1 | import 'package:flutter/cupertino.dart'; | 2 | import 'package:flutter/cupertino.dart'; |
| 2 | import 'package:flutter/foundation.dart'; | 3 | import 'package:flutter/foundation.dart'; |
| 3 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
| 4 | import 'package:flutter_bloc/flutter_bloc.dart'; | 5 | import 'package:flutter_bloc/flutter_bloc.dart'; |
| 5 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 6 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
| 7 | +import 'package:wow_english/common/extension/string_extension.dart'; | ||
| 6 | import 'package:wow_english/common/request/dao/lesson_dao.dart'; | 8 | import 'package:wow_english/common/request/dao/lesson_dao.dart'; |
| 7 | import 'package:wow_english/common/request/exception.dart'; | 9 | import 'package:wow_english/common/request/exception.dart'; |
| 8 | import 'package:wow_english/common/request/dao/listen_dao.dart'; | 10 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
| @@ -43,6 +45,8 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -43,6 +45,8 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 43 | ///单元列表是否有刷新,有的话返回上一页时通知其刷新接口数据 | 45 | ///单元列表是否有刷新,有的话返回上一页时通知其刷新接口数据 |
| 44 | bool courseUnitEntityChanged = false; | 46 | bool courseUnitEntityChanged = false; |
| 45 | 47 | ||
| 48 | + late AudioPlayer audioPlayer; // 点击播放器 | ||
| 49 | + late AudioPlayer backgroundPlayer; // 背景播放器 | ||
| 46 | ///courseUnitId与课程环节列表的映射 | 50 | ///courseUnitId与课程环节列表的映射 |
| 47 | final Map<int, List<CourseSectionEntity>?> _courseSectionDatasMap = {}; | 51 | final Map<int, List<CourseSectionEntity>?> _courseSectionDatasMap = {}; |
| 48 | 52 | ||
| @@ -61,16 +65,48 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -61,16 +65,48 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 61 | on<RequestEnterClassEvent>(_requestEnterClass); | 65 | on<RequestEnterClassEvent>(_requestEnterClass); |
| 62 | on<RequestVideoLessonEvent>(_requestVideoLesson); | 66 | on<RequestVideoLessonEvent>(_requestVideoLesson); |
| 63 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); | 67 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
| 68 | + on<InitEvent>(_init); | ||
| 69 | + on<InitBlocEvent>((event, emit) { | ||
| 70 | + // audioPlayer = AudioPlayer(playerId: 'section'); | ||
| 71 | + // backgroundPlayer = AudioPlayer(playerId: 'back'); | ||
| 72 | + // backgroundPlayer.onPlayerStateChanged.listen((event) async { | ||
| 73 | + // if (event == PlayerState.completed) { | ||
| 74 | + // debugPrint('播放结束'); | ||
| 75 | + // backgroundPlayer | ||
| 76 | + // .play(AssetSource('count_with_me_instrumental'.assetMp3)); | ||
| 77 | + // } | ||
| 78 | + // }); | ||
| 79 | + // audioPlayer.onPlayerStateChanged.listen((event) async { | ||
| 80 | + // if (event == PlayerState.completed) { | ||
| 81 | + // debugPrint('播放结束'); | ||
| 82 | + // } | ||
| 83 | + // }); | ||
| 84 | + }); | ||
| 85 | + } | ||
| 86 | + @override | ||
| 87 | + Future<void> close() { | ||
| 88 | + audioPlayer.release(); | ||
| 89 | + audioPlayer.dispose(); | ||
| 90 | + backgroundPlayer.release(); | ||
| 91 | + backgroundPlayer.dispose(); | ||
| 92 | + return super.close(); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + void _init(InitEvent event, Emitter<SectionState> emit) async { | ||
| 96 | + audioPlayer = AudioPlayer(playerId: 'section'); | ||
| 97 | + // backgroundPlayer = AudioPlayer(playerId: 'back'); | ||
| 98 | + // backgroundPlayer.play(AssetSource('count_with_me_instrumental'.assetMp3)); | ||
| 64 | } | 99 | } |
| 65 | 100 | ||
| 66 | void _requestSectionsData( | 101 | void _requestSectionsData( |
| 67 | RequestDataEvent event, Emitter<SectionState> emitter) async { | 102 | RequestDataEvent event, Emitter<SectionState> emitter) async { |
| 68 | try { | 103 | try { |
| 69 | await loading(() async { | 104 | await loading(() async { |
| 70 | - List<CourseSectionEntity>? courseSectionEntities = await LessonDao.courseSection(courseUnitId: event.courseUnitId); | 105 | + List<CourseSectionEntity>? courseSectionEntities = |
| 106 | + await LessonDao.courseSection(courseUnitId: event.courseUnitId); | ||
| 71 | if (courseSectionEntities != null) { | 107 | if (courseSectionEntities != null) { |
| 72 | _courseSectionDatasMap[event.courseUnitId] = | 108 | _courseSectionDatasMap[event.courseUnitId] = |
| 73 | - await LessonDao.courseSection(courseUnitId: event.courseUnitId); | 109 | + await LessonDao.courseSection(courseUnitId: event.courseUnitId); |
| 74 | emitter(LessonDataLoadState()); | 110 | emitter(LessonDataLoadState()); |
| 75 | } | 111 | } |
| 76 | }); | 112 | }); |
| @@ -224,7 +260,8 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -224,7 +260,8 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 224 | ///查找当前unit的下一个section | 260 | ///查找当前unit的下一个section |
| 225 | CourseSectionEntity? nextCourseSectionEntity = | 261 | CourseSectionEntity? nextCourseSectionEntity = |
| 226 | findCourseSectionBySort(curSectionSort + 1); | 262 | findCourseSectionBySort(curSectionSort + 1); |
| 227 | - return checkCourseSectionLocked(courseLessonId, nextCourseSectionEntity, emitter); | 263 | + return checkCourseSectionLocked( |
| 264 | + courseLessonId, nextCourseSectionEntity, emitter); | ||
| 228 | } catch (e) { | 265 | } catch (e) { |
| 229 | if (e is ApiException) { | 266 | if (e is ApiException) { |
| 230 | showToast(e.message.toString()); | 267 | showToast(e.message.toString()); |
| @@ -234,7 +271,9 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -234,7 +271,9 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 234 | } | 271 | } |
| 235 | 272 | ||
| 236 | ///检查section是否锁定 | 273 | ///检查section是否锁定 |
| 237 | - Future<CourseSectionEntity?> checkCourseSectionLocked(int courseLessonId, CourseSectionEntity? courseSectionEntity, | 274 | + Future<CourseSectionEntity?> checkCourseSectionLocked( |
| 275 | + int courseLessonId, | ||
| 276 | + CourseSectionEntity? courseSectionEntity, | ||
| 238 | Emitter<SectionState> emitter) async { | 277 | Emitter<SectionState> emitter) async { |
| 239 | if (courseSectionEntity != null) { | 278 | if (courseSectionEntity != null) { |
| 240 | if (courseSectionEntity.lock == false) { | 279 | if (courseSectionEntity.lock == false) { |
| @@ -243,15 +282,15 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -243,15 +282,15 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 243 | } else { | 282 | } else { |
| 244 | ///如果section锁了,请求当前unit下的section数据,查询解锁状态 | 283 | ///如果section锁了,请求当前unit下的section数据,查询解锁状态 |
| 245 | int courseUnitId = courseSectionEntity.courseUnitId; | 284 | int courseUnitId = courseSectionEntity.courseUnitId; |
| 246 | - CourseSectionEntity? result = await loading(() async { | 285 | + CourseSectionEntity? result = await loading(() async { |
| 247 | List<CourseSectionEntity>? tempSectionEntities = | 286 | List<CourseSectionEntity>? tempSectionEntities = |
| 248 | - await LessonDao.courseSection(courseUnitId: courseUnitId); | 287 | + await LessonDao.courseSection(courseUnitId: courseUnitId); |
| 249 | if (tempSectionEntities != null) { | 288 | if (tempSectionEntities != null) { |
| 250 | _courseSectionDatasMap[courseUnitId] = tempSectionEntities; | 289 | _courseSectionDatasMap[courseUnitId] = tempSectionEntities; |
| 251 | emitter(LessonDataLoadState()); | 290 | emitter(LessonDataLoadState()); |
| 252 | } | 291 | } |
| 253 | courseSectionEntity = tempSectionEntities?.firstWhereOrNull( | 292 | courseSectionEntity = tempSectionEntities?.firstWhereOrNull( |
| 254 | - (element) => element.id == courseSectionEntity?.id); | 293 | + (element) => element.id == courseSectionEntity?.id); |
| 255 | if (courseSectionEntity?.lock == false) { | 294 | if (courseSectionEntity?.lock == false) { |
| 256 | ///刷新后的数据如果解锁了,直接返回 | 295 | ///刷新后的数据如果解锁了,直接返回 |
| 257 | return courseSectionEntity; | 296 | return courseSectionEntity; |
| @@ -270,18 +309,20 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -270,18 +309,20 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 270 | if (curCourseUnitDetail != null) { | 309 | if (curCourseUnitDetail != null) { |
| 271 | ///再根据当前unit的sortOrder找出下一个unit | 310 | ///再根据当前unit的sortOrder找出下一个unit |
| 272 | CourseUnitDetail? nextCourseUnitDetail = | 311 | CourseUnitDetail? nextCourseUnitDetail = |
| 273 | - _courseUnitEntity.courseUnitVOList?.firstWhereOrNull((element) => | ||
| 274 | - element.sortOrder == (curCourseUnitDetail.sortOrder! + 1)); | 312 | + _courseUnitEntity.courseUnitVOList?.firstWhereOrNull((element) => |
| 313 | + element.sortOrder == (curCourseUnitDetail.sortOrder! + 1)); | ||
| 275 | 314 | ||
| 276 | if (nextCourseUnitDetail != null) { | 315 | if (nextCourseUnitDetail != null) { |
| 277 | if (nextCourseUnitDetail.lock == true) { | 316 | if (nextCourseUnitDetail.lock == true) { |
| 278 | ///如果下一个unit是锁定状态,请求数据刷新查询解锁状态 | 317 | ///如果下一个unit是锁定状态,请求数据刷新查询解锁状态 |
| 279 | CourseSectionEntity? result = await loading(() async { | 318 | CourseSectionEntity? result = await loading(() async { |
| 280 | - CourseUnitEntity? newCourseUnitEntity = await LessonDao.courseUnit( | ||
| 281 | - _courseUnitEntity.nowCourseModuleId); | 319 | + CourseUnitEntity? newCourseUnitEntity = |
| 320 | + await LessonDao.courseUnit( | ||
| 321 | + _courseUnitEntity.nowCourseModuleId); | ||
| 282 | 322 | ||
| 283 | ///拿到重新获取到的unit后,再次判断是否解锁 | 323 | ///拿到重新获取到的unit后,再次判断是否解锁 |
| 284 | - nextCourseUnitDetail = newCourseUnitEntity?.courseUnitVOList?.firstWhereOrNull( | 324 | + nextCourseUnitDetail = newCourseUnitEntity?.courseUnitVOList |
| 325 | + ?.firstWhereOrNull( | ||
| 285 | (element) => element.id == nextCourseUnitDetail?.id); | 326 | (element) => element.id == nextCourseUnitDetail?.id); |
| 286 | if (nextCourseUnitDetail?.lock == false) { | 327 | if (nextCourseUnitDetail?.lock == false) { |
| 287 | ///解锁状态从锁定到解锁,覆盖原unit数据并刷新ui | 328 | ///解锁状态从锁定到解锁,覆盖原unit数据并刷新ui |
| @@ -289,7 +330,8 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -289,7 +330,8 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 289 | courseUnitEntityChanged = true; | 330 | courseUnitEntityChanged = true; |
| 290 | emitter(LessonDataLoadState()); | 331 | emitter(LessonDataLoadState()); |
| 291 | 332 | ||
| 292 | - return checkCourseSectionLockedOfNextUnit(courseLessonId, nextCourseUnitDetail!.id!, emitter); | 333 | + return checkCourseSectionLockedOfNextUnit( |
| 334 | + courseLessonId, nextCourseUnitDetail!.id!, emitter); | ||
| 293 | } else { | 335 | } else { |
| 294 | showToast('下个单元课程还没解锁哦'); | 336 | showToast('下个单元课程还没解锁哦'); |
| 295 | 337 | ||
| @@ -299,10 +341,12 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -299,10 +341,12 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 299 | }); | 341 | }); |
| 300 | return result; | 342 | return result; |
| 301 | } else { | 343 | } else { |
| 302 | - return checkCourseSectionLockedOfNextUnit(courseLessonId, nextCourseUnitDetail.id!, emitter); | 344 | + return checkCourseSectionLockedOfNextUnit( |
| 345 | + courseLessonId, nextCourseUnitDetail.id!, emitter); | ||
| 303 | } | 346 | } |
| 304 | } else { | 347 | } else { |
| 305 | showToast("恭喜你,本阶段学到顶啦"); | 348 | showToast("恭喜你,本阶段学到顶啦"); |
| 349 | + | ||
| 306 | ///最后一个unit了 | 350 | ///最后一个unit了 |
| 307 | return null; | 351 | return null; |
| 308 | } | 352 | } |
| @@ -314,13 +358,16 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -314,13 +358,16 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
| 314 | } | 358 | } |
| 315 | 359 | ||
| 316 | ///检查下一个unit的(第一个)section | 360 | ///检查下一个unit的(第一个)section |
| 317 | - Future<CourseSectionEntity?> checkCourseSectionLockedOfNextUnit(int courseLessonId, int nextCourseUnitDetailId, | 361 | + Future<CourseSectionEntity?> checkCourseSectionLockedOfNextUnit( |
| 362 | + int courseLessonId, | ||
| 363 | + int nextCourseUnitDetailId, | ||
| 318 | Emitter<SectionState> emitter) async { | 364 | Emitter<SectionState> emitter) async { |
| 319 | - CourseSectionEntity? firstSectionNextUnit = await getFirstSectionByUnitId( | ||
| 320 | - nextCourseUnitDetailId, emitter); | 365 | + CourseSectionEntity? firstSectionNextUnit = |
| 366 | + await getFirstSectionByUnitId(nextCourseUnitDetailId, emitter); | ||
| 321 | if (firstSectionNextUnit != null) { | 367 | if (firstSectionNextUnit != null) { |
| 322 | ///下个unit的第一个section如果不为空,再次检查是否锁定 | 368 | ///下个unit的第一个section如果不为空,再次检查是否锁定 |
| 323 | - CourseSectionEntity? courseSectionEntity = await checkCourseSectionLocked(courseLessonId, firstSectionNextUnit, emitter); | 369 | + CourseSectionEntity? courseSectionEntity = await checkCourseSectionLocked( |
| 370 | + courseLessonId, firstSectionNextUnit, emitter); | ||
| 324 | if (courseSectionEntity != null) { | 371 | if (courseSectionEntity != null) { |
| 325 | ///只有是下一unit的第一个section并且解锁了,才跳转 | 372 | ///只有是下一unit的第一个section并且解锁了,才跳转 |
| 326 | _pageController.nextPage( | 373 | _pageController.nextPage( |
lib/pages/section/bloc/section_event.dart
| @@ -9,6 +9,8 @@ class RequestDataEvent extends SectionEvent { | @@ -9,6 +9,8 @@ class RequestDataEvent extends SectionEvent { | ||
| 9 | RequestDataEvent(this.courseUnitId); | 9 | RequestDataEvent(this.courseUnitId); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | +class InitEvent extends SectionEvent {} | ||
| 13 | + | ||
| 12 | ///获取视频课程内容 | 14 | ///获取视频课程内容 |
| 13 | class RequestVideoLessonEvent extends SectionEvent { | 15 | class RequestVideoLessonEvent extends SectionEvent { |
| 14 | final String courseLessonId; | 16 | final String courseLessonId; |
| @@ -53,3 +55,5 @@ class CurrentUnitIndexChangeEvent extends SectionEvent { | @@ -53,3 +55,5 @@ class CurrentUnitIndexChangeEvent extends SectionEvent { | ||
| 53 | 55 | ||
| 54 | CurrentUnitIndexChangeEvent(this.unitIndex); | 56 | CurrentUnitIndexChangeEvent(this.unitIndex); |
| 55 | } | 57 | } |
| 58 | + | ||
| 59 | +class InitBlocEvent extends SectionEvent {} |
lib/pages/section/bloc/section_state.dart
| @@ -22,3 +22,5 @@ class RequestEnterClassState extends SectionState { | @@ -22,3 +22,5 @@ class RequestEnterClassState extends SectionState { | ||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | class CurrentPageIndexState extends SectionState {} | 24 | class CurrentPageIndexState extends SectionState {} |
| 25 | + | ||
| 26 | +class VoicePlayChangeState extends SectionState {} |
lib/pages/section/section_page.dart
| @@ -39,7 +39,8 @@ class SectionPage extends StatelessWidget { | @@ -39,7 +39,8 @@ class SectionPage extends StatelessWidget { | ||
| 39 | initialPage, | 39 | initialPage, |
| 40 | PageController(initialPage: initialPage), | 40 | PageController(initialPage: initialPage), |
| 41 | ScrollController(), | 41 | ScrollController(), |
| 42 | - ScrollController()), | 42 | + ScrollController()) |
| 43 | + ..add(InitEvent()), | ||
| 43 | //为了触发指示器进入后计算位置 | 44 | //为了触发指示器进入后计算位置 |
| 44 | // ..add(CurrentUnitIndexChangeEvent(initialPage)), | 45 | // ..add(CurrentUnitIndexChangeEvent(initialPage)), |
| 45 | child: _SectionPageView(context), | 46 | child: _SectionPageView(context), |
| @@ -88,57 +89,75 @@ class _SectionPageView extends StatelessWidget { | @@ -88,57 +89,75 @@ class _SectionPageView extends StatelessWidget { | ||
| 88 | currentTime: dataMap['currentTime'], | 89 | currentTime: dataMap['currentTime'], |
| 89 | autoNextSection: dataMap['nextSection'])); | 90 | autoNextSection: dataMap['nextSection'])); |
| 90 | } | 91 | } |
| 92 | + if (bloc.backgroundPlayer.state == PlayerState.paused) { | ||
| 93 | + bloc.backgroundPlayer.resume(); | ||
| 94 | + } | ||
| 91 | }); | 95 | }); |
| 92 | return; | 96 | return; |
| 93 | } | 97 | } |
| 94 | 98 | ||
| 95 | if (state is RequestEnterClassState) { | 99 | if (state is RequestEnterClassState) { |
| 100 | + bloc.backgroundPlayer.pause(); | ||
| 96 | if (state.courseType != SectionType.practice.value && | 101 | if (state.courseType != SectionType.practice.value && |
| 97 | state.courseType != SectionType.pictureBook.value) { | 102 | state.courseType != SectionType.pictureBook.value) { |
| 98 | ///视频类型 | 103 | ///视频类型 |
| 99 | ///获取视频课程内容 | 104 | ///获取视频课程内容 |
| 100 | if (state.courseType == 1) { | 105 | if (state.courseType == 1) { |
| 101 | - AudioPlayer().play(AssetSource('music_time'.assetMp3)); | 106 | + bloc.audioPlayer.play(AssetSource('music_time'.assetMp3)); |
| 102 | } else { | 107 | } else { |
| 103 | - AudioPlayer().play(AssetSource('video_time'.assetMp3)); | 108 | + bloc.audioPlayer.play(AssetSource('video_time'.assetMp3)); |
| 104 | } | 109 | } |
| 105 | - bloc.add(RequestVideoLessonEvent( | ||
| 106 | - state.courseLessonId, state.courseType)); | 110 | + Future.delayed(const Duration(seconds: 1), () { |
| 111 | + bloc.add(RequestVideoLessonEvent( | ||
| 112 | + state.courseLessonId, state.courseType)); | ||
| 113 | + }); | ||
| 114 | + | ||
| 107 | return; | 115 | return; |
| 108 | } | 116 | } |
| 109 | 117 | ||
| 110 | if (state.courseType == SectionType.pictureBook.value) { | 118 | if (state.courseType == SectionType.pictureBook.value) { |
| 111 | - AudioPlayer().play(AssetSource('reading_time'.assetMp3)); | ||
| 112 | - //绘本 | ||
| 113 | - pushNamed(AppRouteName.reading, | ||
| 114 | - arguments: {'courseLessonId': state.courseLessonId}) | ||
| 115 | - .then((value) { | ||
| 116 | - if (value != null) { | ||
| 117 | - Map<String, dynamic> dataMap = value as Map<String, dynamic>; | ||
| 118 | - bloc.add(RequestEndClassEvent( | ||
| 119 | - dataMap['courseLessonId']!, | ||
| 120 | - dataMap['isCompleted'], | ||
| 121 | - currentStep: dataMap['currentStep'], | ||
| 122 | - autoNextSection: dataMap['nextSection'], | ||
| 123 | - )); | ||
| 124 | - } | 119 | + bloc.audioPlayer.play(AssetSource('reading_time'.assetMp3)); |
| 120 | + Future.delayed(const Duration(seconds: 1), () { | ||
| 121 | + //绘本 | ||
| 122 | + pushNamed(AppRouteName.reading, | ||
| 123 | + arguments: {'courseLessonId': state.courseLessonId}) | ||
| 124 | + .then((value) { | ||
| 125 | + if (value != null) { | ||
| 126 | + Map<String, dynamic> dataMap = value as Map<String, dynamic>; | ||
| 127 | + bloc.add(RequestEndClassEvent( | ||
| 128 | + dataMap['courseLessonId']!, | ||
| 129 | + dataMap['isCompleted'], | ||
| 130 | + currentStep: dataMap['currentStep'], | ||
| 131 | + autoNextSection: dataMap['nextSection'], | ||
| 132 | + )); | ||
| 133 | + if (bloc.backgroundPlayer.state == PlayerState.paused) { | ||
| 134 | + bloc.backgroundPlayer.resume(); | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + }); | ||
| 125 | }); | 138 | }); |
| 139 | + | ||
| 126 | return; | 140 | return; |
| 127 | } | 141 | } |
| 128 | 142 | ||
| 129 | if (state.courseType == SectionType.practice.value) { | 143 | if (state.courseType == SectionType.practice.value) { |
| 130 | //练习 | 144 | //练习 |
| 131 | - AudioPlayer().play(AssetSource('quiz_time'.assetMp3)); | ||
| 132 | - pushNamed(AppRouteName.topicPic, | ||
| 133 | - arguments: {'courseLessonId': state.courseLessonId}) | ||
| 134 | - .then((value) { | ||
| 135 | - if (value != null) { | ||
| 136 | - Map<String, dynamic> dataMap = value as Map<String, dynamic>; | ||
| 137 | - bloc.add(RequestEndClassEvent( | ||
| 138 | - dataMap['courseLessonId']!, dataMap['isCompleted'], | ||
| 139 | - currentStep: dataMap['currentStep'], | ||
| 140 | - autoNextSection: dataMap['nextSection'])); | ||
| 141 | - } | 145 | + bloc.audioPlayer.play(AssetSource('quiz_time'.assetMp3)); |
| 146 | + Future.delayed(const Duration(seconds: 1), () { | ||
| 147 | + pushNamed(AppRouteName.topicPic, | ||
| 148 | + arguments: {'courseLessonId': state.courseLessonId}) | ||
| 149 | + .then((value) { | ||
| 150 | + if (value != null) { | ||
| 151 | + Map<String, dynamic> dataMap = value as Map<String, dynamic>; | ||
| 152 | + bloc.add(RequestEndClassEvent( | ||
| 153 | + dataMap['courseLessonId']!, dataMap['isCompleted'], | ||
| 154 | + currentStep: dataMap['currentStep'], | ||
| 155 | + autoNextSection: dataMap['nextSection'])); | ||
| 156 | + } | ||
| 157 | + if (bloc.backgroundPlayer.state == PlayerState.paused) { | ||
| 158 | + bloc.backgroundPlayer.resume(); | ||
| 159 | + } | ||
| 160 | + }); | ||
| 142 | }); | 161 | }); |
| 143 | return; | 162 | return; |
| 144 | } | 163 | } |
lib/pages/unit/widget/course_unit_item.dart
| @@ -17,14 +17,13 @@ class CourseUnitItem extends StatelessWidget { | @@ -17,14 +17,13 @@ class CourseUnitItem extends StatelessWidget { | ||
| 17 | @override | 17 | @override |
| 18 | Widget build(BuildContext context) { | 18 | Widget build(BuildContext context) { |
| 19 | return Padding( | 19 | return Padding( |
| 20 | - padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 24.h), | ||
| 21 | - child: Stack( | ||
| 22 | - children: [ | ||
| 23 | - _normalItem(), | ||
| 24 | - _lockWidget(), | ||
| 25 | - ], | ||
| 26 | - ) | ||
| 27 | - ); | 20 | + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 24.h), |
| 21 | + child: Stack( | ||
| 22 | + children: [ | ||
| 23 | + _normalItem(), | ||
| 24 | + _lockWidget(), | ||
| 25 | + ], | ||
| 26 | + )); | ||
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | Widget _normalItem() { | 29 | Widget _normalItem() { |
| @@ -40,17 +39,17 @@ class CourseUnitItem extends StatelessWidget { | @@ -40,17 +39,17 @@ class CourseUnitItem extends StatelessWidget { | ||
| 40 | children: [ | 39 | children: [ |
| 41 | Expanded( | 40 | Expanded( |
| 42 | child: Container( | 41 | child: Container( |
| 43 | - decoration: BoxDecoration( | ||
| 44 | - border: Border.all( | ||
| 45 | - width: 2, | ||
| 46 | - color: const Color(0xFF140C10), | ||
| 47 | - ), | ||
| 48 | - borderRadius: BorderRadius.circular(6)), | ||
| 49 | - child: OwImageWidget( | ||
| 50 | - name: unitLesson.coverUrl ?? '', | ||
| 51 | - fit: BoxFit.fitHeight, | 42 | + decoration: BoxDecoration( |
| 43 | + border: Border.all( | ||
| 44 | + width: 2, | ||
| 45 | + color: const Color(0xFF140C10), | ||
| 52 | ), | 46 | ), |
| 53 | - )), | 47 | + borderRadius: BorderRadius.circular(6)), |
| 48 | + child: OwImageWidget( | ||
| 49 | + name: unitLesson.coverUrl ?? '', | ||
| 50 | + fit: BoxFit.fitHeight, | ||
| 51 | + ), | ||
| 52 | + )), | ||
| 54 | 20.verticalSpace, | 53 | 20.verticalSpace, |
| 55 | SizedBox( | 54 | SizedBox( |
| 56 | height: 40.h, | 55 | height: 40.h, |
| @@ -58,8 +57,7 @@ class CourseUnitItem extends StatelessWidget { | @@ -58,8 +57,7 @@ class CourseUnitItem extends StatelessWidget { | ||
| 58 | unitLesson.name ?? '', | 57 | unitLesson.name ?? '', |
| 59 | maxLines: 2, | 58 | maxLines: 2, |
| 60 | overflow: TextOverflow.ellipsis, | 59 | overflow: TextOverflow.ellipsis, |
| 61 | - style: | ||
| 62 | - TextStyle(fontSize: 11.sp, color: const Color(0xFF140C10)), | 60 | + style: TextStyle(fontSize: 11.sp, color: const Color(0xFF140C10)), |
| 63 | ), | 61 | ), |
| 64 | ) | 62 | ) |
| 65 | ], | 63 | ], |
| @@ -75,12 +73,8 @@ class CourseUnitItem extends StatelessWidget { | @@ -75,12 +73,8 @@ class CourseUnitItem extends StatelessWidget { | ||
| 75 | width: 165.w, | 73 | width: 165.w, |
| 76 | decoration: BoxDecoration( | 74 | decoration: BoxDecoration( |
| 77 | image: DecorationImage( | 75 | image: DecorationImage( |
| 78 | - image: AssetImage( | ||
| 79 | - 'gendubeij_mengban'.assetPng | ||
| 80 | - ), | ||
| 81 | - fit: BoxFit.fill | ||
| 82 | - ) | ||
| 83 | - ), | 76 | + image: AssetImage('gendubeij_mengban'.assetPng), |
| 77 | + fit: BoxFit.fill)), | ||
| 84 | alignment: Alignment.center, | 78 | alignment: Alignment.center, |
| 85 | child: Image.asset( | 79 | child: Image.asset( |
| 86 | 'iv_lock'.assetPng, | 80 | 'iv_lock'.assetPng, |