Commit 1e22b7d1bfc9bfeef388fe4b909281f759dd02d6
1 parent
26982eea
feat:儿歌/视频环节接口请求时机优化
Showing
11 changed files
with
172 additions
and
187 deletions
lib/common/request/dao/lesson_dao.dart
@@ -13,6 +13,7 @@ class LessonDao { | @@ -13,6 +13,7 @@ class LessonDao { | ||
13 | } | 13 | } |
14 | 14 | ||
15 | ///课程单元列表 | 15 | ///课程单元列表 |
16 | + ///@param moduleId 模块id | ||
16 | static Future<CourseUnitEntity?> courseUnit(int? moduleId) async { | 17 | static Future<CourseUnitEntity?> courseUnit(int? moduleId) async { |
17 | Map<String, dynamic> mapData = {}; | 18 | Map<String, dynamic> mapData = {}; |
18 | if (moduleId != null) { | 19 | if (moduleId != null) { |
@@ -32,7 +33,7 @@ class LessonDao { | @@ -32,7 +33,7 @@ class LessonDao { | ||
32 | return data; | 33 | return data; |
33 | } | 34 | } |
34 | 35 | ||
35 | - ///课程(单元)列表 | 36 | + ///课程(环节)列表 |
36 | static Future<List<CourseSectionEntity>?> courseSection({required int courseUnitId}) async { | 37 | static Future<List<CourseSectionEntity>?> courseSection({required int courseUnitId}) async { |
37 | Map<String, dynamic> mapData = {}; | 38 | Map<String, dynamic> mapData = {}; |
38 | mapData['courseUnitId'] = courseUnitId; | 39 | mapData['courseUnitId'] = courseUnitId; |
lib/pages/practice/bloc/topic_picture_bloc.dart
@@ -19,6 +19,7 @@ import '../../../common/permission/permissionRequester.dart'; | @@ -19,6 +19,7 @@ import '../../../common/permission/permissionRequester.dart'; | ||
19 | import '../../../route/route.dart'; | 19 | import '../../../route/route.dart'; |
20 | 20 | ||
21 | part 'topic_picture_event.dart'; | 21 | part 'topic_picture_event.dart'; |
22 | + | ||
22 | part 'topic_picture_state.dart'; | 23 | part 'topic_picture_state.dart'; |
23 | 24 | ||
24 | enum VoicePlayState { | 25 | enum VoicePlayState { |
@@ -47,6 +48,8 @@ class TopicPictureBloc | @@ -47,6 +48,8 @@ class TopicPictureBloc | ||
47 | 48 | ||
48 | CourseProcessEntity? _entity; | 49 | CourseProcessEntity? _entity; |
49 | 50 | ||
51 | + CourseProcessEntity? get entity => _entity; | ||
52 | + | ||
50 | ///正在评测 | 53 | ///正在评测 |
51 | bool _isVoicing = false; | 54 | bool _isVoicing = false; |
52 | 55 | ||
@@ -63,8 +66,6 @@ class TopicPictureBloc | @@ -63,8 +66,6 @@ class TopicPictureBloc | ||
63 | 66 | ||
64 | bool get forbiddenWhenCorrect => _forbiddenWhenCorrect; | 67 | bool get forbiddenWhenCorrect => _forbiddenWhenCorrect; |
65 | 68 | ||
66 | - CourseProcessEntity? get entity => _entity; | ||
67 | - | ||
68 | int get currentPage => _currentPage + 1; | 69 | int get currentPage => _currentPage + 1; |
69 | 70 | ||
70 | int get selectItem => _selectItem; | 71 | int get selectItem => _selectItem; |
@@ -257,8 +258,8 @@ class TopicPictureBloc | @@ -257,8 +258,8 @@ class TopicPictureBloc | ||
257 | XSVoiceStartEvent event, Emitter<TopicPictureState> emitter) async { | 258 | XSVoiceStartEvent event, Emitter<TopicPictureState> emitter) async { |
258 | await audioPlayer.stop(); | 259 | await audioPlayer.stop(); |
259 | // 调用封装好的权限检查和请求方法 | 260 | // 调用封装好的权限检查和请求方法 |
260 | - bool result = | ||
261 | - await requestPermission(context, Permission.microphone, "录音", "用于开启录音,识别您的开口作答并给出反馈"); | 261 | + bool result = await requestPermission( |
262 | + context, Permission.microphone, "录音", "用于开启录音,识别您的开口作答并给出反馈"); | ||
262 | if (result) { | 263 | if (result) { |
263 | methodChannel.invokeMethod('startVoice', { | 264 | methodChannel.invokeMethod('startVoice', { |
264 | 'word': event.testWord, | 265 | 'word': event.testWord, |
lib/pages/section/bloc/section_bloc.dart
1 | -import 'package:audioplayers/audioplayers.dart'; | ||
2 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; |
3 | import 'package:flutter/foundation.dart'; | 2 | import 'package:flutter/foundation.dart'; |
4 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
5 | import 'package:flutter_bloc/flutter_bloc.dart'; | 4 | import 'package:flutter_bloc/flutter_bloc.dart'; |
6 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 5 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
7 | -import 'package:wow_english/common/extension/string_extension.dart'; | ||
8 | import 'package:wow_english/common/request/dao/lesson_dao.dart'; | 6 | import 'package:wow_english/common/request/dao/lesson_dao.dart'; |
9 | import 'package:wow_english/common/request/exception.dart'; | 7 | import 'package:wow_english/common/request/exception.dart'; |
10 | import 'package:wow_english/common/request/dao/listen_dao.dart'; | 8 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
11 | -import 'package:wow_english/models/course_process_entity.dart'; | ||
12 | import 'package:wow_english/utils/audio_player_util.dart'; | 9 | import 'package:wow_english/utils/audio_player_util.dart'; |
13 | import 'package:wow_english/utils/loading.dart'; | 10 | import 'package:wow_english/utils/loading.dart'; |
14 | import 'package:wow_english/utils/toast_util.dart'; | 11 | import 'package:wow_english/utils/toast_util.dart'; |
@@ -53,10 +50,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -53,10 +50,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
53 | Map<int, List<CourseSectionEntity>?> get courseSectionDatasMap => | 50 | Map<int, List<CourseSectionEntity>?> get courseSectionDatasMap => |
54 | _courseSectionDatasMap; | 51 | _courseSectionDatasMap; |
55 | 52 | ||
56 | - CourseProcessEntity? _processEntity; | ||
57 | - | ||
58 | - CourseProcessEntity? get processEntity => _processEntity; | ||
59 | - | ||
60 | ///点击环节后先请求数据再进入,标志位避免频繁点击多次请求(以及多次进入) | 53 | ///点击环节后先请求数据再进入,标志位避免频繁点击多次请求(以及多次进入) |
61 | bool _isRequesting = false; | 54 | bool _isRequesting = false; |
62 | 55 | ||
@@ -66,7 +59,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -66,7 +59,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
66 | on<RequestDataEvent>(_requestSectionsData); | 59 | on<RequestDataEvent>(_requestSectionsData); |
67 | on<RequestEndClassEvent>(_requestEndClass); | 60 | on<RequestEndClassEvent>(_requestEndClass); |
68 | on<RequestEnterClassEvent>(_requestEnterClass); | 61 | on<RequestEnterClassEvent>(_requestEnterClass); |
69 | - on<RequestVideoLessonEvent>(_requestVideoLesson); | ||
70 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); | 62 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
71 | on<InitEvent>((event, emit) async { | 63 | on<InitEvent>((event, emit) async { |
72 | await AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); | 64 | await AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); |
@@ -92,23 +84,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -92,23 +84,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
92 | } | 84 | } |
93 | } | 85 | } |
94 | 86 | ||
95 | - void _requestVideoLesson( | ||
96 | - RequestVideoLessonEvent event, Emitter<SectionState> emitter) async { | ||
97 | - try { | ||
98 | - await loading(() async { | ||
99 | - _processEntity = await ListenDao.process(event.courseLessonId); | ||
100 | - emitter( | ||
101 | - RequestVideoLessonState(event.courseLessonId, event.courseType)); | ||
102 | - }); | ||
103 | - } catch (e) { | ||
104 | - if (e is ApiException) { | ||
105 | - showToast(e.message ?? '请求失败,请检查网络连接'); | ||
106 | - } | ||
107 | - } finally { | ||
108 | - _isRequesting = false; | ||
109 | - } | ||
110 | - } | ||
111 | - | ||
112 | void _requestEnterClass( | 87 | void _requestEnterClass( |
113 | RequestEnterClassEvent event, Emitter<SectionState> emitter) async { | 88 | RequestEnterClassEvent event, Emitter<SectionState> emitter) async { |
114 | try { | 89 | try { |
@@ -124,8 +99,9 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -124,8 +99,9 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
124 | } catch (e) { | 99 | } catch (e) { |
125 | if (e is ApiException) { | 100 | if (e is ApiException) { |
126 | showToast(e.message ?? '请求失败,请检查网络连接'); | 101 | showToast(e.message ?? '请求失败,请检查网络连接'); |
127 | - _isRequesting = false; | ||
128 | } | 102 | } |
103 | + } finally { | ||
104 | + _isRequesting = false; | ||
129 | } | 105 | } |
130 | } | 106 | } |
131 | 107 |
lib/pages/section/bloc/section_event.dart
@@ -11,14 +11,6 @@ class RequestDataEvent extends SectionEvent { | @@ -11,14 +11,6 @@ class RequestDataEvent extends SectionEvent { | ||
11 | 11 | ||
12 | class InitEvent extends SectionEvent {} | 12 | class InitEvent extends SectionEvent {} |
13 | 13 | ||
14 | -///获取视频课程内容 | ||
15 | -class RequestVideoLessonEvent extends SectionEvent { | ||
16 | - final String courseLessonId; | ||
17 | - final int courseType; | ||
18 | - | ||
19 | - RequestVideoLessonEvent(this.courseLessonId, this.courseType); | ||
20 | -} | ||
21 | - | ||
22 | ///进入课堂 | 14 | ///进入课堂 |
23 | class RequestEnterClassEvent extends SectionEvent { | 15 | class RequestEnterClassEvent extends SectionEvent { |
24 | final String courseLessonId; | 16 | final String courseLessonId; |
lib/pages/section/bloc/section_state.dart
@@ -7,13 +7,6 @@ class LessonInitial extends SectionState {} | @@ -7,13 +7,6 @@ class LessonInitial extends SectionState {} | ||
7 | 7 | ||
8 | class LessonDataLoadState extends SectionState {} | 8 | class LessonDataLoadState extends SectionState {} |
9 | 9 | ||
10 | -class RequestVideoLessonState extends SectionState { | ||
11 | - final String courseLessonId; | ||
12 | - final int type; | ||
13 | - | ||
14 | - RequestVideoLessonState(this.courseLessonId, this.type); | ||
15 | -} | ||
16 | - | ||
17 | class RequestEnterClassState extends SectionState { | 10 | class RequestEnterClassState extends SectionState { |
18 | final String courseLessonId; | 11 | final String courseLessonId; |
19 | final int courseType; | 12 | final int courseType; |
lib/pages/section/section_page.dart
@@ -60,58 +60,36 @@ class _SectionPageView extends StatelessWidget { | @@ -60,58 +60,36 @@ class _SectionPageView extends StatelessWidget { | ||
60 | final bloc = BlocProvider.of<SectionBloc>(context); | 60 | final bloc = BlocProvider.of<SectionBloc>(context); |
61 | return BlocListener<SectionBloc, SectionState>( | 61 | return BlocListener<SectionBloc, SectionState>( |
62 | listener: (context, state) async { | 62 | listener: (context, state) async { |
63 | - if (state is RequestVideoLessonState) { | ||
64 | - final videoUrl = bloc.processEntity?.videos?.videoUrl ?? ''; | ||
65 | - var title = ''; | ||
66 | - if (state.type == SectionType.song.value) { | ||
67 | - title = 'song'; | ||
68 | - } | ||
69 | - | ||
70 | - if (state.type == SectionType.video.value) { | ||
71 | - title = 'video'; | ||
72 | - } | ||
73 | - | ||
74 | - if (state.type == SectionType.bouns.value) { | ||
75 | - title = 'bonus'; | ||
76 | - } | ||
77 | - | ||
78 | - if (videoUrl.isEmpty || !videoUrl.contains('http')) { | ||
79 | - return; | ||
80 | - } | ||
81 | - pushNamed(AppRouteName.lookVideo, arguments: { | ||
82 | - 'videoUrl': videoUrl, | ||
83 | - 'title': title, | ||
84 | - 'courseLessonId': state.courseLessonId, | ||
85 | - 'isTopic': true | ||
86 | - }).then((value) { | ||
87 | - if (value != null) { | ||
88 | - Map<String, dynamic> dataMap = value as Map<String, dynamic>; | ||
89 | - bloc.add(RequestEndClassEvent( | ||
90 | - dataMap['courseLessonId']!, dataMap['isCompleted'], | ||
91 | - currentTime: dataMap['currentTime'], | ||
92 | - autoNextSection: dataMap['nextSection'])); | ||
93 | - } | ||
94 | - AudioPlayerUtil.getInstance() | ||
95 | - .playAudio(AudioPlayerUtilType.countWithMe); | ||
96 | - }); | ||
97 | - return; | ||
98 | - } | ||
99 | - | ||
100 | if (state is RequestEnterClassState) { | 63 | if (state is RequestEnterClassState) { |
101 | - if (state.courseType != SectionType.practice.value && | ||
102 | - state.courseType != SectionType.pictureBook.value) { | ||
103 | - ///视频类型 | ||
104 | - ///获取视频课程内容 | ||
105 | - if (state.courseType == 1) { | ||
106 | - AudioPlayerUtil.getInstance() | 64 | + if (state.courseType == SectionType.song.value && |
65 | + state.courseType == SectionType.video.value) { | ||
66 | + var title = | ||
67 | + state.courseType == SectionType.song.value ? 'song' : 'video'; | ||
68 | + | ||
69 | + ///儿歌/视频类型 | ||
70 | + if (state.courseType == SectionType.song.value) { | ||
71 | + await AudioPlayerUtil.getInstance() | ||
107 | .playAudio(AudioPlayerUtilType.musicTime); | 72 | .playAudio(AudioPlayerUtilType.musicTime); |
108 | } else { | 73 | } else { |
109 | - AudioPlayerUtil.getInstance() | 74 | + await AudioPlayerUtil.getInstance() |
110 | .playAudio(AudioPlayerUtilType.videoTime); | 75 | .playAudio(AudioPlayerUtilType.videoTime); |
111 | } | 76 | } |
112 | - bloc.add(RequestVideoLessonEvent( | ||
113 | - state.courseLessonId, state.courseType)); | ||
114 | - | 77 | + pushNamed(AppRouteName.lookVideo, arguments: { |
78 | + 'videoUrl': "", | ||
79 | + 'title': title, | ||
80 | + 'courseLessonId': state.courseLessonId, | ||
81 | + 'isTopic': true | ||
82 | + }).then((value) { | ||
83 | + if (value != null) { | ||
84 | + Map<String, dynamic> dataMap = value as Map<String, dynamic>; | ||
85 | + bloc.add(RequestEndClassEvent( | ||
86 | + dataMap['courseLessonId']!, dataMap['isCompleted'], | ||
87 | + currentTime: dataMap['currentTime'], | ||
88 | + autoNextSection: dataMap['nextSection'])); | ||
89 | + } | ||
90 | + AudioPlayerUtil.getInstance() | ||
91 | + .playAudio(AudioPlayerUtilType.countWithMe); | ||
92 | + }); | ||
115 | return; | 93 | return; |
116 | } | 94 | } |
117 | 95 |
lib/pages/video/lookvideo/bloc/look_video_bloc.dart
@@ -5,15 +5,19 @@ import 'package:wow_english/pages/section/subsection/base_section/bloc.dart'; | @@ -5,15 +5,19 @@ import 'package:wow_english/pages/section/subsection/base_section/bloc.dart'; | ||
5 | import 'package:wow_english/pages/section/subsection/base_section/event.dart'; | 5 | import 'package:wow_english/pages/section/subsection/base_section/event.dart'; |
6 | import 'package:wow_english/pages/section/subsection/base_section/state.dart'; | 6 | import 'package:wow_english/pages/section/subsection/base_section/state.dart'; |
7 | 7 | ||
8 | +import '../../../../common/request/dao/listen_dao.dart'; | ||
9 | +import '../../../../common/request/exception.dart'; | ||
10 | +import '../../../../models/course_process_entity.dart'; | ||
11 | +import '../../../../utils/loading.dart'; | ||
12 | +import '../../../../utils/toast_util.dart'; | ||
13 | + | ||
8 | part 'look_video_event.dart'; | 14 | part 'look_video_event.dart'; |
9 | part 'look_video_state.dart'; | 15 | part 'look_video_state.dart'; |
10 | 16 | ||
11 | class LookVideoBloc extends BaseSectionBloc<BaseSectionEvent, BaseSectionState> { | 17 | class LookVideoBloc extends BaseSectionBloc<BaseSectionEvent, BaseSectionState> { |
12 | 18 | ||
13 | - VideoPlayerController? _controller; | ||
14 | - | ||
15 | final String? _videoUrl; | 19 | final String? _videoUrl; |
16 | - String? get videoUrl => _videoUrl; | 20 | + String? get videoUrl => _videoUrl ?? _entity?.videos?.videoUrl ?? ''; |
17 | final String? _typeTitle; | 21 | final String? _typeTitle; |
18 | String? get typeTitle => _typeTitle; | 22 | String? get typeTitle => _typeTitle; |
19 | final String? _courseLessonId; | 23 | final String? _courseLessonId; |
@@ -21,12 +25,32 @@ class LookVideoBloc extends BaseSectionBloc<BaseSectionEvent, BaseSectionState> | @@ -21,12 +25,32 @@ class LookVideoBloc extends BaseSectionBloc<BaseSectionEvent, BaseSectionState> | ||
21 | final bool _isTopic; | 25 | final bool _isTopic; |
22 | bool get isTopic => _isTopic; | 26 | bool get isTopic => _isTopic; |
23 | 27 | ||
28 | + CourseProcessEntity? _entity; | ||
29 | + | ||
30 | + CourseProcessEntity? get entity => _entity; | ||
31 | + | ||
24 | LookVideoBloc(this._videoUrl, this._typeTitle, this._courseLessonId, this._isTopic) : super(LookVideoInitial()) { | 32 | LookVideoBloc(this._videoUrl, this._typeTitle, this._courseLessonId, this._isTopic) : super(LookVideoInitial()) { |
25 | on<LookVideoEvent>((event, emit) { | 33 | on<LookVideoEvent>((event, emit) { |
26 | // TODO: implement event handler | 34 | // TODO: implement event handler |
27 | }); | 35 | }); |
36 | + on<RequestDataEvent>(_requestData); | ||
28 | on<SectionAgainEvent>((event, emit) { | 37 | on<SectionAgainEvent>((event, emit) { |
29 | emit(SectionAgainState()); | 38 | emit(SectionAgainState()); |
30 | }); | 39 | }); |
31 | } | 40 | } |
41 | + | ||
42 | + ///请求数据 | ||
43 | + void _requestData( | ||
44 | + RequestDataEvent event, Emitter<BaseSectionState> emitter) async { | ||
45 | + try { | ||
46 | + await loading(() async { | ||
47 | + _entity = await ListenDao.process(courseLessonId); | ||
48 | + emitter(RequestDataState()); | ||
49 | + }); | ||
50 | + } catch (e) { | ||
51 | + if (e is ApiException) { | ||
52 | + showToast(e.message ?? '请求失败,请检查网络连接'); | ||
53 | + } | ||
54 | + } | ||
55 | + } | ||
32 | } | 56 | } |
lib/pages/video/lookvideo/bloc/look_video_event.dart
@@ -4,3 +4,5 @@ part of 'look_video_bloc.dart'; | @@ -4,3 +4,5 @@ part of 'look_video_bloc.dart'; | ||
4 | abstract class LookVideoEvent extends BaseSectionEvent {} | 4 | abstract class LookVideoEvent extends BaseSectionEvent {} |
5 | 5 | ||
6 | class RestartVideoEvent extends LookVideoEvent {} | 6 | class RestartVideoEvent extends LookVideoEvent {} |
7 | + | ||
8 | +class RequestDataEvent extends LookVideoEvent {} |
lib/pages/video/lookvideo/bloc/look_video_state.dart
@@ -6,3 +6,5 @@ abstract class LookVideoState extends BaseSectionState {} | @@ -6,3 +6,5 @@ abstract class LookVideoState extends BaseSectionState {} | ||
6 | class LookVideoInitial extends LookVideoState {} | 6 | class LookVideoInitial extends LookVideoState {} |
7 | 7 | ||
8 | class VideoStarState extends LookVideoState {} | 8 | class VideoStarState extends LookVideoState {} |
9 | + | ||
10 | +class RequestDataState extends LookVideoState {} |
lib/pages/video/lookvideo/look_video_page.dart
@@ -3,10 +3,15 @@ import 'package:flutter_bloc/flutter_bloc.dart'; | @@ -3,10 +3,15 @@ import 'package:flutter_bloc/flutter_bloc.dart'; | ||
3 | import 'package:wow_english/pages/section/subsection/base_section/state.dart'; | 3 | import 'package:wow_english/pages/section/subsection/base_section/state.dart'; |
4 | import 'package:wow_english/pages/video/lookvideo/bloc/look_video_bloc.dart'; | 4 | import 'package:wow_english/pages/video/lookvideo/bloc/look_video_bloc.dart'; |
5 | import 'package:wow_english/pages/video/lookvideo/widgets/video_widget.dart'; | 5 | import 'package:wow_english/pages/video/lookvideo/widgets/video_widget.dart'; |
6 | +import 'package:wow_english/utils/log_util.dart'; | ||
6 | 7 | ||
7 | class LookVideoPage extends StatelessWidget { | 8 | class LookVideoPage extends StatelessWidget { |
8 | const LookVideoPage( | 9 | const LookVideoPage( |
9 | - {super.key, this.videoUrl, this.typeTitle, this.courseLessonId, this.isTopic = false}); | 10 | + {super.key, |
11 | + this.videoUrl, | ||
12 | + this.typeTitle, | ||
13 | + this.courseLessonId, | ||
14 | + this.isTopic = false}); | ||
10 | 15 | ||
11 | final String? videoUrl; | 16 | final String? videoUrl; |
12 | final String? typeTitle; | 17 | final String? typeTitle; |
@@ -16,24 +21,34 @@ class LookVideoPage extends StatelessWidget { | @@ -16,24 +21,34 @@ class LookVideoPage extends StatelessWidget { | ||
16 | @override | 21 | @override |
17 | Widget build(BuildContext context) { | 22 | Widget build(BuildContext context) { |
18 | return BlocProvider( | 23 | return BlocProvider( |
19 | - create: (BuildContext context) => LookVideoBloc(videoUrl, typeTitle, courseLessonId, isTopic), | 24 | + create: (BuildContext context) => |
25 | + LookVideoBloc(videoUrl, typeTitle, courseLessonId, isTopic) | ||
26 | + ..add(RequestDataEvent()), | ||
20 | child: Builder(builder: (context) => _buildPage(context)), | 27 | child: Builder(builder: (context) => _buildPage(context)), |
21 | ); | 28 | ); |
22 | } | 29 | } |
23 | } | 30 | } |
24 | 31 | ||
25 | Widget _buildPage(BuildContext context) { | 32 | Widget _buildPage(BuildContext context) { |
26 | - return BlocBuilder<LookVideoBloc, BaseSectionState>(builder: (context, state) { | ||
27 | - final bloc = BlocProvider.of<LookVideoBloc>(context); | ||
28 | - return Container( | ||
29 | - color: Colors.white, | ||
30 | - child: VideoWidget( | ||
31 | - videoUrl: bloc.videoUrl ?? '', | ||
32 | - typeTitle: bloc.typeTitle ?? '', | ||
33 | - courseLessonId: bloc.courseLessonId ?? '', | ||
34 | - isTopic: bloc.isTopic, | ||
35 | - ) | ||
36 | - ); | ||
37 | - } | ||
38 | - ); | 33 | + return BlocBuilder<LookVideoBloc, BaseSectionState>( |
34 | + builder: (context, state) { | ||
35 | + final bloc = BlocProvider.of<LookVideoBloc>(context); | ||
36 | + Log.d("WQF lookvideo BlocBuilder bloc.videoUr=${bloc.videoUrl}"); | ||
37 | + return Center( | ||
38 | + child: bloc.videoUrl?.isNotEmpty == true | ||
39 | + ? Container( | ||
40 | + color: Colors.white, | ||
41 | + child: VideoWidget( | ||
42 | + videoUrl: bloc.videoUrl ?? '', | ||
43 | + typeTitle: bloc.typeTitle ?? '', | ||
44 | + courseLessonId: bloc.courseLessonId ?? '', | ||
45 | + isTopic: bloc.isTopic, | ||
46 | + )) | ||
47 | + //todo 空了需要抽一个通用的loading组件 | ||
48 | + : Container( | ||
49 | + color: Colors.white, | ||
50 | + child: const CircularProgressIndicator(), | ||
51 | + ), | ||
52 | + ); | ||
53 | + }); | ||
39 | } | 54 | } |
lib/pages/video/lookvideo/widgets/video_widget.dart
@@ -12,11 +12,12 @@ import '../../../section/subsection/base_section/state.dart'; | @@ -12,11 +12,12 @@ import '../../../section/subsection/base_section/state.dart'; | ||
12 | import 'video_opera_widget.dart'; | 12 | import 'video_opera_widget.dart'; |
13 | 13 | ||
14 | class VideoWidget extends StatefulWidget { | 14 | class VideoWidget extends StatefulWidget { |
15 | - const VideoWidget({super.key, | ||
16 | - this.videoUrl = '', | ||
17 | - this.typeTitle, | ||
18 | - this.courseLessonId = '', | ||
19 | - this.isTopic = false}); | 15 | + const VideoWidget( |
16 | + {super.key, | ||
17 | + this.videoUrl = '', | ||
18 | + this.typeTitle, | ||
19 | + this.courseLessonId = '', | ||
20 | + this.isTopic = false}); | ||
20 | 21 | ||
21 | final String videoUrl; | 22 | final String videoUrl; |
22 | final String? typeTitle; | 23 | final String? typeTitle; |
@@ -39,10 +40,10 @@ class _VideoWidgetState extends State<VideoWidget> { | @@ -39,10 +40,10 @@ class _VideoWidgetState extends State<VideoWidget> { | ||
39 | 40 | ||
40 | String formatDuration(Duration duration) { | 41 | String formatDuration(Duration duration) { |
41 | String hours = duration.inHours.toString().padLeft(2, '0'); | 42 | String hours = duration.inHours.toString().padLeft(2, '0'); |
42 | - String minutes = duration.inMinutes.remainder(60).toString().padLeft( | ||
43 | - 2, '0'); | ||
44 | - String seconds = duration.inSeconds.remainder(60).toString().padLeft( | ||
45 | - 2, '0'); | 43 | + String minutes = |
44 | + duration.inMinutes.remainder(60).toString().padLeft(2, '0'); | ||
45 | + String seconds = | ||
46 | + duration.inSeconds.remainder(60).toString().padLeft(2, '0'); | ||
46 | return "$hours:$minutes:$seconds"; | 47 | return "$hours:$minutes:$seconds"; |
47 | } | 48 | } |
48 | 49 | ||
@@ -71,17 +72,17 @@ class _VideoWidgetState extends State<VideoWidget> { | @@ -71,17 +72,17 @@ class _VideoWidgetState extends State<VideoWidget> { | ||
71 | _controller!.value.position.inSeconds == | 72 | _controller!.value.position.inSeconds == |
72 | _controller!.value.duration.inSeconds) { | 73 | _controller!.value.duration.inSeconds) { |
73 | final lookVideoBloc = context.read<LookVideoBloc>(); | 74 | final lookVideoBloc = context.read<LookVideoBloc>(); |
74 | - lookVideoBloc.sectionComplete(() { | ||
75 | - popPage(data: { | ||
76 | - 'courseLessonId': widget.courseLessonId, | ||
77 | - 'currentTime': getCurrentPositionSeconds(), | ||
78 | - 'isCompleted': true, | ||
79 | - 'nextSection': widget.isTopic | ||
80 | - }); | ||
81 | - } as VoidCallback, | ||
82 | - againSectionTap: (() { | ||
83 | - lookVideoBloc.add(SectionAgainEvent()); | ||
84 | - }), context: context); | 75 | + lookVideoBloc.sectionComplete( |
76 | + () { | ||
77 | + popPage(data: { | ||
78 | + 'courseLessonId': widget.courseLessonId, | ||
79 | + 'currentTime': getCurrentPositionSeconds(), | ||
80 | + 'isCompleted': true, | ||
81 | + 'nextSection': widget.isTopic | ||
82 | + }); | ||
83 | + } as VoidCallback, againSectionTap: (() { | ||
84 | + lookVideoBloc.add(SectionAgainEvent()); | ||
85 | + }), context: context); | ||
85 | } | 86 | } |
86 | } | 87 | } |
87 | }); | 88 | }); |
@@ -189,63 +190,63 @@ class _VideoWidgetState extends State<VideoWidget> { | @@ -189,63 +190,63 @@ class _VideoWidgetState extends State<VideoWidget> { | ||
189 | child: Center( | 190 | child: Center( |
190 | child: _controller!.value.isInitialized | 191 | child: _controller!.value.isInitialized |
191 | ? Stack( | 192 | ? Stack( |
192 | - alignment: Alignment.center, | ||
193 | - children: [ | ||
194 | - SizedBox( | ||
195 | - height: double.infinity, | ||
196 | - width: double.infinity, | ||
197 | - child: AspectRatio( | ||
198 | - aspectRatio: _controller!.value.aspectRatio, | ||
199 | - child: VideoPlayer(_controller!), | ||
200 | - ), | ||
201 | - ), | ||
202 | - Offstage( | ||
203 | - offstage: _hiddenTipView, | ||
204 | - child: VideoOperaWidget( | ||
205 | - title: widget.typeTitle ?? 'song', | ||
206 | - degree: _playDegree, | ||
207 | - totalTime: _totalTime, | ||
208 | - currentTime: _currentTime, | ||
209 | - isPlay: _controller!.value.isPlaying, | ||
210 | - actionEvent: (OperationType type) { | ||
211 | - actionType(type); | ||
212 | - }, | ||
213 | - sliderChangeEvent: (double degree) { | ||
214 | - int totalSecond = _controller! | ||
215 | - .value.duration.inMinutes | ||
216 | - .remainder(60) * | ||
217 | - 60 + | ||
218 | - _controller!.value.duration.inSeconds | ||
219 | - .remainder(60); | ||
220 | - int positionSecond = (totalSecond * degree).toInt(); | ||
221 | - _controller! | ||
222 | - .seekTo(Duration(seconds: positionSecond)); | ||
223 | - }, | ||
224 | - ), | ||
225 | - ), | ||
226 | - Offstage( | ||
227 | - offstage: _controller!.value.isPlaying, | ||
228 | - child: IconButton( | ||
229 | - onPressed: () { | ||
230 | - _controller!.play(); | ||
231 | - }, | ||
232 | - icon: Image.asset( | ||
233 | - 'video_stop'.assetPng, | ||
234 | - width: 70.w, | ||
235 | - height: 70.h, | ||
236 | - ), | ||
237 | - ), | ||
238 | - ) | ||
239 | - ], | ||
240 | - ) | 193 | + alignment: Alignment.center, |
194 | + children: [ | ||
195 | + SizedBox( | ||
196 | + height: double.infinity, | ||
197 | + width: double.infinity, | ||
198 | + child: AspectRatio( | ||
199 | + aspectRatio: _controller!.value.aspectRatio, | ||
200 | + child: VideoPlayer(_controller!), | ||
201 | + ), | ||
202 | + ), | ||
203 | + Offstage( | ||
204 | + offstage: _hiddenTipView, | ||
205 | + child: VideoOperaWidget( | ||
206 | + title: widget.typeTitle ?? 'song', | ||
207 | + degree: _playDegree, | ||
208 | + totalTime: _totalTime, | ||
209 | + currentTime: _currentTime, | ||
210 | + isPlay: _controller!.value.isPlaying, | ||
211 | + actionEvent: (OperationType type) { | ||
212 | + actionType(type); | ||
213 | + }, | ||
214 | + sliderChangeEvent: (double degree) { | ||
215 | + int totalSecond = _controller! | ||
216 | + .value.duration.inMinutes | ||
217 | + .remainder(60) * | ||
218 | + 60 + | ||
219 | + _controller!.value.duration.inSeconds | ||
220 | + .remainder(60); | ||
221 | + int positionSecond = (totalSecond * degree).toInt(); | ||
222 | + _controller! | ||
223 | + .seekTo(Duration(seconds: positionSecond)); | ||
224 | + }, | ||
225 | + ), | ||
226 | + ), | ||
227 | + Offstage( | ||
228 | + offstage: _controller!.value.isPlaying, | ||
229 | + child: IconButton( | ||
230 | + onPressed: () { | ||
231 | + _controller!.play(); | ||
232 | + }, | ||
233 | + icon: Image.asset( | ||
234 | + 'video_stop'.assetPng, | ||
235 | + width: 70.w, | ||
236 | + height: 70.h, | ||
237 | + ), | ||
238 | + ), | ||
239 | + ) | ||
240 | + ], | ||
241 | + ) | ||
241 | : Container( | 242 | : Container( |
242 | - color: Colors.white, | ||
243 | - child: const CircularProgressIndicator(), | ||
244 | - // Text( | ||
245 | - // '视频加载中....', | ||
246 | - // style: TextStyle(fontSize: 20.sp, color: Colors.black), | ||
247 | - // ), | ||
248 | - ), | 243 | + color: Colors.white, |
244 | + child: const CircularProgressIndicator(), | ||
245 | + // Text( | ||
246 | + // '视频加载中....', | ||
247 | + // style: TextStyle(fontSize: 20.sp, color: Colors.black), | ||
248 | + // ), | ||
249 | + ), | ||
249 | ), | 250 | ), |
250 | ), | 251 | ), |
251 | ); | 252 | ); |