Showing
11 changed files
with
489 additions
and
143 deletions
... | @@ -3,21 +3,33 @@ import 'package:Parlando/routers/i_router.dart'; | ... | @@ -3,21 +3,33 @@ import 'package:Parlando/routers/i_router.dart'; |
3 | 3 | ||
4 | import 'page/account_edit_page.dart'; | 4 | import 'page/account_edit_page.dart'; |
5 | import 'page/account_page.dart'; | 5 | import 'page/account_page.dart'; |
6 | +import 'page/work_player.dart'; | ||
6 | 7 | ||
7 | - | 8 | +class AccountRouter implements IRouterProvider { |
8 | -class AccountRouter implements IRouterProvider{ | ||
9 | - | ||
10 | static String accountPage = '/account'; | 9 | static String accountPage = '/account'; |
11 | static String accountEditPage = '/account/edit'; | 10 | static String accountEditPage = '/account/edit'; |
11 | + static String workPlayer = '/account/work/player'; | ||
12 | 12 | ||
13 | @override | 13 | @override |
14 | void initRouter(FluroRouter router) { | 14 | void initRouter(FluroRouter router) { |
15 | router.define(accountPage, handler: Handler(handlerFunc: (_, __) { | 15 | router.define(accountPage, handler: Handler(handlerFunc: (_, __) { |
16 | - return const AccountPage(isSelfPage: true,); | 16 | + return const AccountPage( |
17 | + isSelfPage: true, | ||
18 | + ); | ||
17 | })); | 19 | })); |
18 | router.define(accountEditPage, handler: Handler(handlerFunc: (_, __) { | 20 | router.define(accountEditPage, handler: Handler(handlerFunc: (_, __) { |
19 | return AccountEditPage(); | 21 | return AccountEditPage(); |
20 | })); | 22 | })); |
23 | + router.define( | ||
24 | + workPlayer, | ||
25 | + handler: Handler( | ||
26 | + handlerFunc: (_, Map<String, List<String>> params) { | ||
27 | + String? id = params['id']?.first; | ||
28 | + return WorkPlayer( | ||
29 | + id: int.parse(id!), | ||
30 | + ); | ||
31 | + }, | ||
32 | + ), | ||
33 | + ); | ||
21 | } | 34 | } |
22 | - | ||
23 | } | 35 | } | ... | ... |
lib/account/models/video_entity.dart
0 → 100644
1 | +import 'dart:convert'; | ||
2 | +import 'package:Parlando/generated/json/base/json_field.dart'; | ||
3 | +import 'package:Parlando/generated/json/video_entity.g.dart'; | ||
4 | + | ||
5 | +@JsonSerializable() | ||
6 | +class VideoEntity { | ||
7 | + String? status; | ||
8 | + int? code; | ||
9 | + String? message; | ||
10 | + VideoData? data; | ||
11 | + VideoError? error; | ||
12 | + | ||
13 | + VideoEntity(); | ||
14 | + | ||
15 | + factory VideoEntity.fromJson(Map<String, dynamic> json) => | ||
16 | + $VideoEntityFromJson(json); | ||
17 | + | ||
18 | + Map<String, dynamic> toJson() => $VideoEntityToJson(this); | ||
19 | + | ||
20 | + @override | ||
21 | + String toString() { | ||
22 | + return jsonEncode(this); | ||
23 | + } | ||
24 | +} | ||
25 | + | ||
26 | +@JsonSerializable() | ||
27 | +class VideoData { | ||
28 | + int? id; | ||
29 | + @JSONField(name: "user_id") | ||
30 | + int? userId; | ||
31 | + String? title; | ||
32 | + String? content; | ||
33 | + String? url; | ||
34 | + int? type; | ||
35 | + String? duration; | ||
36 | + String? size; | ||
37 | + @JSONField(name: "poem_id") | ||
38 | + int? poemId; | ||
39 | + @JSONField(name: "temp_id") | ||
40 | + int? tempId; | ||
41 | + String? thumbnail; | ||
42 | + dynamic bgm; | ||
43 | + String? praise; | ||
44 | + String? view; | ||
45 | + String? collect; | ||
46 | + String? share; | ||
47 | + String? comment; | ||
48 | + String? state; | ||
49 | + @JSONField(name: "is_publish") | ||
50 | + String? isPublish; | ||
51 | + @JSONField(name: "is_check") | ||
52 | + String? isCheck; | ||
53 | + @JSONField(name: "created_at") | ||
54 | + String? createdAt; | ||
55 | + @JSONField(name: "updated_at") | ||
56 | + String? updatedAt; | ||
57 | + | ||
58 | + VideoData(); | ||
59 | + | ||
60 | + factory VideoData.fromJson(Map<String, dynamic> json) => | ||
61 | + $VideoDataFromJson(json); | ||
62 | + | ||
63 | + Map<String, dynamic> toJson() => $VideoDataToJson(this); | ||
64 | + | ||
65 | + @override | ||
66 | + String toString() { | ||
67 | + return jsonEncode(this); | ||
68 | + } | ||
69 | +} | ||
70 | + | ||
71 | +@JsonSerializable() | ||
72 | +class VideoError { | ||
73 | + VideoError(); | ||
74 | + | ||
75 | + factory VideoError.fromJson(Map<String, dynamic> json) => | ||
76 | + $VideoErrorFromJson(json); | ||
77 | + | ||
78 | + Map<String, dynamic> toJson() => $VideoErrorToJson(this); | ||
79 | + | ||
80 | + @override | ||
81 | + String toString() { | ||
82 | + return jsonEncode(this); | ||
83 | + } | ||
84 | +} |
... | @@ -64,7 +64,10 @@ class AccountPageState extends State<AccountPage> { | ... | @@ -64,7 +64,10 @@ class AccountPageState extends State<AccountPage> { |
64 | params: [], | 64 | params: [], |
65 | onSuccess: (data) { | 65 | onSuccess: (data) { |
66 | for (MyVideosData each in data!.data!) { | 66 | for (MyVideosData each in data!.data!) { |
67 | - videos.add(_SmallVideo()); | 67 | + videos.add(_SmallVideo( |
68 | + url: each.thumbnail!, | ||
69 | + id: each.id!, | ||
70 | + )); | ||
68 | } | 71 | } |
69 | isLoadMyVideos = false; | 72 | isLoadMyVideos = false; |
70 | setState(() {}); | 73 | setState(() {}); |
... | @@ -255,11 +258,14 @@ class AccountPageState extends State<AccountPage> { | ... | @@ -255,11 +258,14 @@ class AccountPageState extends State<AccountPage> { |
255 | child: isLoadMyVideos | 258 | child: isLoadMyVideos |
256 | ? const GFLoader() | 259 | ? const GFLoader() |
257 | : GridView( | 260 | : GridView( |
261 | + padding: EdgeInsets.all(15.px), | ||
258 | gridDelegate: | 262 | gridDelegate: |
259 | const SliverGridDelegateWithFixedCrossAxisCount( | 263 | const SliverGridDelegateWithFixedCrossAxisCount( |
260 | - crossAxisCount: 3, //横轴三个子widget | 264 | + crossAxisCount: 3, //横轴三个子widget |
261 | - childAspectRatio: 1.0 //宽高比为1时,子widget | 265 | + childAspectRatio: 1.0, //宽高比为1时,子widget |
262 | - ), | 266 | + mainAxisSpacing: 5, |
267 | + crossAxisSpacing: 5, | ||
268 | + ), | ||
263 | children: videos, | 269 | children: videos, |
264 | ), | 270 | ), |
265 | ), | 271 | ), |
... | @@ -390,62 +396,14 @@ class _UserTag extends StatelessWidget { | ... | @@ -390,62 +396,14 @@ class _UserTag extends StatelessWidget { |
390 | } | 396 | } |
391 | } | 397 | } |
392 | 398 | ||
393 | -class _UserVideoTable extends StatelessWidget { | ||
394 | - const _UserVideoTable({ | ||
395 | - Key? key, | ||
396 | - }) : super(key: key); | ||
397 | - | ||
398 | - @override | ||
399 | - Widget build(BuildContext context) { | ||
400 | - return Column( | ||
401 | - children: <Widget>[ | ||
402 | - Container( | ||
403 | - color: ColorPlate.white, | ||
404 | - padding: EdgeInsets.symmetric( | ||
405 | - vertical: 12.px, | ||
406 | - ), | ||
407 | - child: Row( | ||
408 | - mainAxisAlignment: MainAxisAlignment.center, | ||
409 | - crossAxisAlignment: CrossAxisAlignment.center, | ||
410 | - children: <Widget>[ | ||
411 | - _PointSelectTextButton( | ||
412 | - true, | ||
413 | - ParlandoLocalizations.of(context) | ||
414 | - .onePoemBottomNavigationBarItemTitle, | ||
415 | - ), | ||
416 | - _PointSelectTextButton( | ||
417 | - false, | ||
418 | - ParlandoLocalizations.of(context) | ||
419 | - .timelineBottomNavigationBarItemTitle), | ||
420 | - _PointSelectTextButton( | ||
421 | - false, | ||
422 | - ParlandoLocalizations.of(context) | ||
423 | - .categoryBottomNavigationBarItemTitle), | ||
424 | - ], | ||
425 | - ), | ||
426 | - ), | ||
427 | - Row( | ||
428 | - children: const [ | ||
429 | - _SmallVideo(), | ||
430 | - _SmallVideo(), | ||
431 | - _SmallVideo(), | ||
432 | - ], | ||
433 | - ), | ||
434 | - Row( | ||
435 | - children: const [ | ||
436 | - _SmallVideo(), | ||
437 | - _SmallVideo(), | ||
438 | - _SmallVideo(), | ||
439 | - ], | ||
440 | - ), | ||
441 | - ], | ||
442 | - ); | ||
443 | - } | ||
444 | -} | ||
445 | - | ||
446 | class _SmallVideo extends StatelessWidget { | 399 | class _SmallVideo extends StatelessWidget { |
400 | + final String url; | ||
401 | + final int id; | ||
402 | + | ||
447 | const _SmallVideo({ | 403 | const _SmallVideo({ |
448 | Key? key, | 404 | Key? key, |
405 | + required this.url, | ||
406 | + required this.id, | ||
449 | }) : super(key: key); | 407 | }) : super(key: key); |
450 | 408 | ||
451 | @override | 409 | @override |
... | @@ -455,27 +413,16 @@ class _SmallVideo extends StatelessWidget { | ... | @@ -455,27 +413,16 @@ class _SmallVideo extends StatelessWidget { |
455 | onTap: () { | 413 | onTap: () { |
456 | NavigatorUtils.push( | 414 | NavigatorUtils.push( |
457 | context, | 415 | context, |
458 | - '${PoemRouter.poemDetailPage}?id=100', | 416 | + '${AccountRouter.workPlayer}?id=$id', |
459 | ); | 417 | ); |
460 | }, | 418 | }, |
461 | child: AspectRatio( | 419 | child: AspectRatio( |
462 | aspectRatio: 3.px / 4.0, | 420 | aspectRatio: 3.px / 4.0, |
463 | - child: Container( | 421 | + child: CachedNetworkImage( |
464 | - decoration: const BoxDecoration( | 422 | + fit: BoxFit.cover, |
465 | - image: DecorationImage( | 423 | + placeholder: (context, url) => const CircularProgressIndicator(), |
466 | - image: AssetImage("assets/images/poem/poem_background.png"), | 424 | + errorWidget: (context, url, error) => const Icon(Icons.error), |
467 | - fit: BoxFit.fill, | 425 | + imageUrl: url, |
468 | - ), | ||
469 | - ), | ||
470 | - alignment: Alignment.center, | ||
471 | - child: Text( | ||
472 | - '一言', | ||
473 | - style: TextStyle( | ||
474 | - color: Colors.black54, | ||
475 | - fontSize: 18.px, | ||
476 | - fontWeight: FontWeight.w900, | ||
477 | - ), | ||
478 | - ), | ||
479 | ), | 426 | ), |
480 | ), | 427 | ), |
481 | ), | 428 | ), |
... | @@ -483,55 +430,16 @@ class _SmallVideo extends StatelessWidget { | ... | @@ -483,55 +430,16 @@ class _SmallVideo extends StatelessWidget { |
483 | } | 430 | } |
484 | } | 431 | } |
485 | 432 | ||
486 | -class _PointSelectTextButton extends StatelessWidget { | ||
487 | - final bool isSelect; | ||
488 | - final String title; | ||
489 | - final Function? onTap; | ||
490 | - | ||
491 | - const _PointSelectTextButton(this.isSelect, | ||
492 | - this.title, { | ||
493 | - Key? key, | ||
494 | - this.onTap, | ||
495 | - }) : super(key: key); | ||
496 | - | ||
497 | - @override | ||
498 | - Widget build(BuildContext context) { | ||
499 | - return Expanded( | ||
500 | - child: Row( | ||
501 | - mainAxisAlignment: MainAxisAlignment.center, | ||
502 | - children: <Widget>[ | ||
503 | - isSelect | ||
504 | - ? Container( | ||
505 | - width: 6.px, | ||
506 | - height: 6.px, | ||
507 | - decoration: BoxDecoration( | ||
508 | - color: ColorPlate.orange, | ||
509 | - borderRadius: BorderRadius.circular(3), | ||
510 | - ), | ||
511 | - ) | ||
512 | - : Container(), | ||
513 | - Container( | ||
514 | - padding: const EdgeInsets.only(left: 2), | ||
515 | - child: Text( | ||
516 | - title, | ||
517 | - style: isSelect ? StandardTextStyle.big : StandardTextStyle.small, | ||
518 | - ), | ||
519 | - ) | ||
520 | - ], | ||
521 | - ), | ||
522 | - ); | ||
523 | - } | ||
524 | -} | ||
525 | - | ||
526 | class TextGroup extends StatelessWidget { | 433 | class TextGroup extends StatelessWidget { |
527 | final String title, tag; | 434 | final String title, tag; |
528 | final Color? color; | 435 | final Color? color; |
529 | 436 | ||
530 | - const TextGroup(this.title, | 437 | + const TextGroup( |
531 | - this.tag, { | 438 | + this.title, |
532 | - Key? key, | 439 | + this.tag, { |
533 | - this.color, | 440 | + Key? key, |
534 | - }) : super(key: key); | 441 | + this.color, |
442 | + }) : super(key: key); | ||
535 | 443 | ||
536 | @override | 444 | @override |
537 | Widget build(BuildContext context) { | 445 | Widget build(BuildContext context) { | ... | ... |
lib/account/page/work_player.dart
0 → 100644
1 | +import 'package:Parlando/account/models/video_entity.dart'; | ||
2 | +import 'package:Parlando/net/dio_utils.dart'; | ||
3 | +import 'package:Parlando/net/http_api.dart'; | ||
4 | +import 'package:Parlando/util/toast_utils.dart'; | ||
5 | +import 'package:fijkplayer/fijkplayer.dart'; | ||
6 | +import 'package:flutter/material.dart'; | ||
7 | +import 'package:Parlando/widgets/my_app_bar.dart'; | ||
8 | + | ||
9 | +class WorkPlayer extends StatefulWidget { | ||
10 | + final int id; | ||
11 | + | ||
12 | + const WorkPlayer({ | ||
13 | + Key? key, | ||
14 | + required this.id, | ||
15 | + }) : super(key: key); | ||
16 | + | ||
17 | + @override | ||
18 | + WorkPlayerState createState() => WorkPlayerState(); | ||
19 | +} | ||
20 | + | ||
21 | +class WorkPlayerState extends State<WorkPlayer> { | ||
22 | + final FijkPlayer player = FijkPlayer(); | ||
23 | + | ||
24 | + bool isLoading = false; | ||
25 | + | ||
26 | + @override | ||
27 | + void initState() { | ||
28 | + super.initState(); | ||
29 | + | ||
30 | + isLoading = true; | ||
31 | + DioUtils.instance.asyncRequestNetwork<VideoEntity>( | ||
32 | + Method.get, | ||
33 | + '${HttpApi.myVideos}/${widget.id}', | ||
34 | + params: [], | ||
35 | + onSuccess: (data) { | ||
36 | + isLoading = false; | ||
37 | + player.setDataSource( | ||
38 | + data!.data!.url!, | ||
39 | + autoPlay: true, | ||
40 | + ); | ||
41 | + player.setLoop(0); | ||
42 | + }, | ||
43 | + onError: (code, msg) { | ||
44 | + isLoading = false; | ||
45 | + Toast.show("获取数据失败,请稍后再试..."); | ||
46 | + }, | ||
47 | + ); | ||
48 | + } | ||
49 | + | ||
50 | + @override | ||
51 | + Widget build(BuildContext context) { | ||
52 | + return Scaffold( | ||
53 | + appBar: MyAppBar( | ||
54 | + homeMenuHeader: Container( | ||
55 | + alignment: Alignment.center, | ||
56 | + child: const Text( | ||
57 | + "我的临境", | ||
58 | + style: TextStyle( | ||
59 | + color: Colors.white, | ||
60 | + ), | ||
61 | + ), | ||
62 | + ), | ||
63 | + ), | ||
64 | + body: Stack( | ||
65 | + children: [ | ||
66 | + FijkView( | ||
67 | + height: MediaQuery.of(context).size.height, | ||
68 | + player: player, | ||
69 | + fit: FijkFit.fill, | ||
70 | + ), | ||
71 | + ], | ||
72 | + )); | ||
73 | + } | ||
74 | + | ||
75 | + @override | ||
76 | + void dispose() { | ||
77 | + player.release(); | ||
78 | + super.dispose(); | ||
79 | + } | ||
80 | +} |
... | @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; | ... | @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; |
7 | import 'package:Parlando/account/models/my_videos_entity.dart'; | 7 | import 'package:Parlando/account/models/my_videos_entity.dart'; |
8 | import 'package:Parlando/account/models/upload_avatar_entity.dart'; | 8 | import 'package:Parlando/account/models/upload_avatar_entity.dart'; |
9 | import 'package:Parlando/account/models/user_entity.dart'; | 9 | import 'package:Parlando/account/models/user_entity.dart'; |
10 | +import 'package:Parlando/account/models/video_entity.dart'; | ||
10 | import 'package:Parlando/category/models/category_entity.dart'; | 11 | import 'package:Parlando/category/models/category_entity.dart'; |
11 | import 'package:Parlando/category/models/category_item_entity.dart'; | 12 | import 'package:Parlando/category/models/category_item_entity.dart'; |
12 | import 'package:Parlando/home/models/home_entity.dart'; | 13 | import 'package:Parlando/home/models/home_entity.dart'; |
... | @@ -31,6 +32,9 @@ class JsonConvert { | ... | @@ -31,6 +32,9 @@ class JsonConvert { |
31 | (UserEntity).toString(): UserEntity.fromJson, | 32 | (UserEntity).toString(): UserEntity.fromJson, |
32 | (UserData).toString(): UserData.fromJson, | 33 | (UserData).toString(): UserData.fromJson, |
33 | (UserError).toString(): UserError.fromJson, | 34 | (UserError).toString(): UserError.fromJson, |
35 | + (VideoEntity).toString(): VideoEntity.fromJson, | ||
36 | + (VideoData).toString(): VideoData.fromJson, | ||
37 | + (VideoError).toString(): VideoError.fromJson, | ||
34 | (CategoryEntity).toString(): CategoryEntity.fromJson, | 38 | (CategoryEntity).toString(): CategoryEntity.fromJson, |
35 | (CategoryData).toString(): CategoryData.fromJson, | 39 | (CategoryData).toString(): CategoryData.fromJson, |
36 | (CategoryDataData).toString(): CategoryDataData.fromJson, | 40 | (CategoryDataData).toString(): CategoryDataData.fromJson, |
... | @@ -186,6 +190,21 @@ class JsonConvert { | ... | @@ -186,6 +190,21 @@ class JsonConvert { |
186 | .map<UserError>((Map<String, dynamic> e) => UserError.fromJson(e)) | 190 | .map<UserError>((Map<String, dynamic> e) => UserError.fromJson(e)) |
187 | .toList() as M; | 191 | .toList() as M; |
188 | } | 192 | } |
193 | + if (<VideoEntity>[] is M) { | ||
194 | + return data | ||
195 | + .map<VideoEntity>((Map<String, dynamic> e) => VideoEntity.fromJson(e)) | ||
196 | + .toList() as M; | ||
197 | + } | ||
198 | + if (<VideoData>[] is M) { | ||
199 | + return data | ||
200 | + .map<VideoData>((Map<String, dynamic> e) => VideoData.fromJson(e)) | ||
201 | + .toList() as M; | ||
202 | + } | ||
203 | + if (<VideoError>[] is M) { | ||
204 | + return data | ||
205 | + .map<VideoError>((Map<String, dynamic> e) => VideoError.fromJson(e)) | ||
206 | + .toList() as M; | ||
207 | + } | ||
189 | if (<CategoryEntity>[] is M) { | 208 | if (<CategoryEntity>[] is M) { |
190 | return data | 209 | return data |
191 | .map<CategoryEntity>( | 210 | .map<CategoryEntity>( | ... | ... |
... | @@ -166,4 +166,4 @@ MyVideosError $MyVideosErrorFromJson(Map<String, dynamic> json) { | ... | @@ -166,4 +166,4 @@ MyVideosError $MyVideosErrorFromJson(Map<String, dynamic> json) { |
166 | Map<String, dynamic> $MyVideosErrorToJson(MyVideosError entity) { | 166 | Map<String, dynamic> $MyVideosErrorToJson(MyVideosError entity) { |
167 | final Map<String, dynamic> data = <String, dynamic>{}; | 167 | final Map<String, dynamic> data = <String, dynamic>{}; |
168 | return data; | 168 | return data; |
169 | -} | 169 | +} |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
lib/generated/json/video_entity.g.dart
0 → 100644
1 | +import 'package:Parlando/generated/json/base/json_convert_content.dart'; | ||
2 | +import 'package:Parlando/account/models/video_entity.dart'; | ||
3 | + | ||
4 | +VideoEntity $VideoEntityFromJson(Map<String, dynamic> json) { | ||
5 | + final VideoEntity videoEntity = VideoEntity(); | ||
6 | + final String? status = jsonConvert.convert<String>(json['status']); | ||
7 | + if (status != null) { | ||
8 | + videoEntity.status = status; | ||
9 | + } | ||
10 | + final int? code = jsonConvert.convert<int>(json['code']); | ||
11 | + if (code != null) { | ||
12 | + videoEntity.code = code; | ||
13 | + } | ||
14 | + final String? message = jsonConvert.convert<String>(json['message']); | ||
15 | + if (message != null) { | ||
16 | + videoEntity.message = message; | ||
17 | + } | ||
18 | + final VideoData? data = jsonConvert.convert<VideoData>(json['data']); | ||
19 | + if (data != null) { | ||
20 | + videoEntity.data = data; | ||
21 | + } | ||
22 | + final VideoError? error = jsonConvert.convert<VideoError>(json['error']); | ||
23 | + if (error != null) { | ||
24 | + videoEntity.error = error; | ||
25 | + } | ||
26 | + return videoEntity; | ||
27 | +} | ||
28 | + | ||
29 | +Map<String, dynamic> $VideoEntityToJson(VideoEntity entity) { | ||
30 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
31 | + data['status'] = entity.status; | ||
32 | + data['code'] = entity.code; | ||
33 | + data['message'] = entity.message; | ||
34 | + data['data'] = entity.data?.toJson(); | ||
35 | + data['error'] = entity.error?.toJson(); | ||
36 | + return data; | ||
37 | +} | ||
38 | + | ||
39 | +VideoData $VideoDataFromJson(Map<String, dynamic> json) { | ||
40 | + final VideoData videoData = VideoData(); | ||
41 | + final int? id = jsonConvert.convert<int>(json['id']); | ||
42 | + if (id != null) { | ||
43 | + videoData.id = id; | ||
44 | + } | ||
45 | + final int? userId = jsonConvert.convert<int>(json['user_id']); | ||
46 | + if (userId != null) { | ||
47 | + videoData.userId = userId; | ||
48 | + } | ||
49 | + final String? title = jsonConvert.convert<String>(json['title']); | ||
50 | + if (title != null) { | ||
51 | + videoData.title = title; | ||
52 | + } | ||
53 | + final String? content = jsonConvert.convert<String>(json['content']); | ||
54 | + if (content != null) { | ||
55 | + videoData.content = content; | ||
56 | + } | ||
57 | + final String? url = jsonConvert.convert<String>(json['url']); | ||
58 | + if (url != null) { | ||
59 | + videoData.url = url; | ||
60 | + } | ||
61 | + final int? type = jsonConvert.convert<int>(json['type']); | ||
62 | + if (type != null) { | ||
63 | + videoData.type = type; | ||
64 | + } | ||
65 | + final String? duration = jsonConvert.convert<String>(json['duration']); | ||
66 | + if (duration != null) { | ||
67 | + videoData.duration = duration; | ||
68 | + } | ||
69 | + final String? size = jsonConvert.convert<String>(json['size']); | ||
70 | + if (size != null) { | ||
71 | + videoData.size = size; | ||
72 | + } | ||
73 | + final int? poemId = jsonConvert.convert<int>(json['poem_id']); | ||
74 | + if (poemId != null) { | ||
75 | + videoData.poemId = poemId; | ||
76 | + } | ||
77 | + final int? tempId = jsonConvert.convert<int>(json['temp_id']); | ||
78 | + if (tempId != null) { | ||
79 | + videoData.tempId = tempId; | ||
80 | + } | ||
81 | + final String? thumbnail = jsonConvert.convert<String>(json['thumbnail']); | ||
82 | + if (thumbnail != null) { | ||
83 | + videoData.thumbnail = thumbnail; | ||
84 | + } | ||
85 | + final dynamic? bgm = jsonConvert.convert<dynamic>(json['bgm']); | ||
86 | + if (bgm != null) { | ||
87 | + videoData.bgm = bgm; | ||
88 | + } | ||
89 | + final String? praise = jsonConvert.convert<String>(json['praise']); | ||
90 | + if (praise != null) { | ||
91 | + videoData.praise = praise; | ||
92 | + } | ||
93 | + final String? view = jsonConvert.convert<String>(json['view']); | ||
94 | + if (view != null) { | ||
95 | + videoData.view = view; | ||
96 | + } | ||
97 | + final String? collect = jsonConvert.convert<String>(json['collect']); | ||
98 | + if (collect != null) { | ||
99 | + videoData.collect = collect; | ||
100 | + } | ||
101 | + final String? share = jsonConvert.convert<String>(json['share']); | ||
102 | + if (share != null) { | ||
103 | + videoData.share = share; | ||
104 | + } | ||
105 | + final String? comment = jsonConvert.convert<String>(json['comment']); | ||
106 | + if (comment != null) { | ||
107 | + videoData.comment = comment; | ||
108 | + } | ||
109 | + final String? state = jsonConvert.convert<String>(json['state']); | ||
110 | + if (state != null) { | ||
111 | + videoData.state = state; | ||
112 | + } | ||
113 | + final String? isPublish = jsonConvert.convert<String>(json['is_publish']); | ||
114 | + if (isPublish != null) { | ||
115 | + videoData.isPublish = isPublish; | ||
116 | + } | ||
117 | + final String? isCheck = jsonConvert.convert<String>(json['is_check']); | ||
118 | + if (isCheck != null) { | ||
119 | + videoData.isCheck = isCheck; | ||
120 | + } | ||
121 | + final String? createdAt = jsonConvert.convert<String>(json['created_at']); | ||
122 | + if (createdAt != null) { | ||
123 | + videoData.createdAt = createdAt; | ||
124 | + } | ||
125 | + final String? updatedAt = jsonConvert.convert<String>(json['updated_at']); | ||
126 | + if (updatedAt != null) { | ||
127 | + videoData.updatedAt = updatedAt; | ||
128 | + } | ||
129 | + return videoData; | ||
130 | +} | ||
131 | + | ||
132 | +Map<String, dynamic> $VideoDataToJson(VideoData entity) { | ||
133 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
134 | + data['id'] = entity.id; | ||
135 | + data['user_id'] = entity.userId; | ||
136 | + data['title'] = entity.title; | ||
137 | + data['content'] = entity.content; | ||
138 | + data['url'] = entity.url; | ||
139 | + data['type'] = entity.type; | ||
140 | + data['duration'] = entity.duration; | ||
141 | + data['size'] = entity.size; | ||
142 | + data['poem_id'] = entity.poemId; | ||
143 | + data['temp_id'] = entity.tempId; | ||
144 | + data['thumbnail'] = entity.thumbnail; | ||
145 | + data['bgm'] = entity.bgm; | ||
146 | + data['praise'] = entity.praise; | ||
147 | + data['view'] = entity.view; | ||
148 | + data['collect'] = entity.collect; | ||
149 | + data['share'] = entity.share; | ||
150 | + data['comment'] = entity.comment; | ||
151 | + data['state'] = entity.state; | ||
152 | + data['is_publish'] = entity.isPublish; | ||
153 | + data['is_check'] = entity.isCheck; | ||
154 | + data['created_at'] = entity.createdAt; | ||
155 | + data['updated_at'] = entity.updatedAt; | ||
156 | + return data; | ||
157 | +} | ||
158 | + | ||
159 | +VideoError $VideoErrorFromJson(Map<String, dynamic> json) { | ||
160 | + final VideoError videoError = VideoError(); | ||
161 | + return videoError; | ||
162 | +} | ||
163 | + | ||
164 | +Map<String, dynamic> $VideoErrorToJson(VideoError entity) { | ||
165 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
166 | + return data; | ||
167 | +} |
... | @@ -11,6 +11,9 @@ class HttpApi { | ... | @@ -11,6 +11,9 @@ class HttpApi { |
11 | static const String user = 'user'; | 11 | static const String user = 'user'; |
12 | static const String home = 'home'; | 12 | static const String home = 'home'; |
13 | static const String myVideos = '/my/videos'; | 13 | static const String myVideos = '/my/videos'; |
14 | + static const String praise = '/praise'; | ||
15 | + static const String addView = '/addview'; | ||
16 | + static const String collect = '/collect'; | ||
14 | static const String search = 'search/repositories'; | 17 | static const String search = 'search/repositories'; |
15 | static const String subscriptions = 'users/simplezhli/subscriptions'; | 18 | static const String subscriptions = 'users/simplezhli/subscriptions'; |
16 | static const String upload = 'uuc/upload-inco'; | 19 | static const String upload = 'uuc/upload-inco'; | ... | ... |
... | @@ -51,6 +51,9 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -51,6 +51,9 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
51 | String currentPoemId = ''; | 51 | String currentPoemId = ''; |
52 | String currentPoemType = ''; | 52 | String currentPoemType = ''; |
53 | 53 | ||
54 | + bool isFav = false; | ||
55 | + bool isPraise = false; | ||
56 | + | ||
54 | @override | 57 | @override |
55 | void didChangeAppLifecycleState(AppLifecycleState state) async { | 58 | void didChangeAppLifecycleState(AppLifecycleState state) async { |
56 | if (state != AppLifecycleState.resumed) { | 59 | if (state != AppLifecycleState.resumed) { |
... | @@ -81,11 +84,14 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -81,11 +84,14 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
81 | for (HomeData data in data!.data!) { | 84 | for (HomeData data in data!.data!) { |
82 | videoDataList.add( | 85 | videoDataList.add( |
83 | UserVideo( | 86 | UserVideo( |
87 | + id: data.id!, | ||
84 | image: '', | 88 | image: '', |
85 | url: data.url!, | 89 | url: data.url!, |
86 | desc: data.content, | 90 | desc: data.content, |
87 | poemId: '${data.poemId}', | 91 | poemId: '${data.poemId}', |
88 | poemType: '${data.type}', | 92 | poemType: '${data.type}', |
93 | + isPraise: data.praise == '1' ? true : false, | ||
94 | + isCollect: data.collect == '1' ? true : false, | ||
89 | ), | 95 | ), |
90 | ); | 96 | ); |
91 | } | 97 | } |
... | @@ -202,6 +208,17 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -202,6 +208,17 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
202 | _videoListController.currentPlayer.videoInfo!.poemId; | 208 | _videoListController.currentPlayer.videoInfo!.poemId; |
203 | currentPoemType = | 209 | currentPoemType = |
204 | _videoListController.currentPlayer.videoInfo!.poemType; | 210 | _videoListController.currentPlayer.videoInfo!.poemType; |
211 | + | ||
212 | + String url = | ||
213 | + '${HttpApi.addView}/${_videoListController.currentPlayer.videoInfo!.id}'; | ||
214 | + // 统计观看数 | ||
215 | + DioUtils.instance.asyncRequestNetwork( | ||
216 | + Method.get, | ||
217 | + url, | ||
218 | + params: [], | ||
219 | + onSuccess: (data) {}, | ||
220 | + onError: (code, msg) {}, | ||
221 | + ); | ||
205 | }, | 222 | }, |
206 | key: const Key('home'), | 223 | key: const Key('home'), |
207 | physics: const QuickerScrollPhysics(), | 224 | physics: const QuickerScrollPhysics(), |
... | @@ -214,11 +231,35 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -214,11 +231,35 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
214 | var data = player.videoInfo!; | 231 | var data = player.videoInfo!; |
215 | // 右侧按钮列 | 232 | // 右侧按钮列 |
216 | Widget buttons = TikTokButtonColumn( | 233 | Widget buttons = TikTokButtonColumn( |
217 | - isFavorite: false, | 234 | + isPraise: _videoListController |
235 | + .currentPlayer.videoInfo!.isPraise, | ||
236 | + isCollect: _videoListController | ||
237 | + .currentPlayer.videoInfo!.isCollect, | ||
218 | onAvatar: () { | 238 | onAvatar: () { |
219 | tkController.animateToPage(TikTokPagePosition.right); | 239 | tkController.animateToPage(TikTokPagePosition.right); |
220 | }, | 240 | }, |
221 | - onFavorite: () {}, | 241 | + onPraise: () { |
242 | + String url = | ||
243 | + '${HttpApi.praise}/${_videoListController.currentPlayer.videoInfo!.id}'; | ||
244 | + DioUtils.instance.asyncRequestNetwork( | ||
245 | + Method.post, | ||
246 | + url, | ||
247 | + params: [], | ||
248 | + onSuccess: (data) {}, | ||
249 | + onError: (code, msg) {}, | ||
250 | + ); | ||
251 | + }, | ||
252 | + onCollect: () { | ||
253 | + String url = | ||
254 | + '${HttpApi.collect}/${_videoListController.currentPlayer.videoInfo!.id}'; | ||
255 | + DioUtils.instance.asyncRequestNetwork( | ||
256 | + Method.post, | ||
257 | + url, | ||
258 | + params: [], | ||
259 | + onSuccess: (data) {}, | ||
260 | + onError: (code, msg) {}, | ||
261 | + ); | ||
262 | + }, | ||
222 | onShare: () {}, | 263 | onShare: () {}, |
223 | ); | 264 | ); |
224 | Widget poem = TikTokVidePoem( | 265 | Widget poem = TikTokVidePoem( |
... | @@ -276,7 +317,6 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -276,7 +317,6 @@ class PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
276 | onPress: () { | 317 | onPress: () { |
277 | String url = | 318 | String url = |
278 | '${PoemRouter.poemRecordVideoPage}?id=$currentPoemId&type=$currentPoemType'; | 319 | '${PoemRouter.poemRecordVideoPage}?id=$currentPoemId&type=$currentPoemType'; |
279 | - print("===========================" + url); | ||
280 | eventBus.fire(TransEvent()); | 320 | eventBus.fire(TransEvent()); |
281 | NavigatorUtils.push( | 321 | NavigatorUtils.push( |
282 | context, | 322 | context, | ... | ... |
... | @@ -8,18 +8,24 @@ var videoList = [ | ... | @@ -8,18 +8,24 @@ var videoList = [ |
8 | ]; | 8 | ]; |
9 | 9 | ||
10 | class UserVideo { | 10 | class UserVideo { |
11 | + final int id; | ||
11 | final String url; | 12 | final String url; |
12 | final String image; | 13 | final String image; |
13 | final String? desc; | 14 | final String? desc; |
14 | final String poemId; | 15 | final String poemId; |
15 | final String poemType; | 16 | final String poemType; |
17 | + final bool isPraise; | ||
18 | + final bool isCollect; | ||
16 | 19 | ||
17 | UserVideo({ | 20 | UserVideo({ |
21 | + required this.id, | ||
18 | required this.url, | 22 | required this.url, |
19 | required this.image, | 23 | required this.image, |
20 | this.desc, | 24 | this.desc, |
21 | required this.poemId, | 25 | required this.poemId, |
22 | required this.poemType, | 26 | required this.poemType, |
27 | + required this.isPraise, | ||
28 | + required this.isCollect, | ||
23 | }); | 29 | }); |
24 | 30 | ||
25 | @override | 31 | @override | ... | ... |
... | @@ -6,18 +6,21 @@ import 'package:Parlando/extension/int_extension.dart'; | ... | @@ -6,18 +6,21 @@ import 'package:Parlando/extension/int_extension.dart'; |
6 | 6 | ||
7 | class TikTokButtonColumn extends StatelessWidget { | 7 | class TikTokButtonColumn extends StatelessWidget { |
8 | final double? bottomPadding; | 8 | final double? bottomPadding; |
9 | - final bool isFavorite; | 9 | + final bool isPraise; |
10 | - final Function? onFavorite; | 10 | + final bool isCollect; |
11 | - final Function? onComment; | 11 | + final Function? onPraise; |
12 | + final Function? onCollect; | ||
12 | final Function? onShare; | 13 | final Function? onShare; |
13 | final Function? onAvatar; | 14 | final Function? onAvatar; |
15 | + | ||
14 | const TikTokButtonColumn({ | 16 | const TikTokButtonColumn({ |
15 | Key? key, | 17 | Key? key, |
16 | this.bottomPadding, | 18 | this.bottomPadding, |
17 | - this.onFavorite, | 19 | + this.onPraise, |
18 | - this.onComment, | 20 | + this.onCollect, |
19 | this.onShare, | 21 | this.onShare, |
20 | - this.isFavorite = false, | 22 | + this.isPraise = false, |
23 | + this.isCollect = false, | ||
21 | this.onAvatar, | 24 | this.onAvatar, |
22 | }) : super(key: key); | 25 | }) : super(key: key); |
23 | 26 | ||
... | @@ -34,13 +37,12 @@ class TikTokButtonColumn extends StatelessWidget { | ... | @@ -34,13 +37,12 @@ class TikTokButtonColumn extends StatelessWidget { |
34 | crossAxisAlignment: CrossAxisAlignment.end, | 37 | crossAxisAlignment: CrossAxisAlignment.end, |
35 | children: <Widget>[ | 38 | children: <Widget>[ |
36 | FavoriteIcon( | 39 | FavoriteIcon( |
37 | - onFavorite: onFavorite, | 40 | + onFavorite: onPraise, |
38 | - isFavorite: isFavorite, | 41 | + isFavorite: isPraise, |
39 | ), | 42 | ), |
40 | - _IconButton( | 43 | + CollectIcon( |
41 | - icon: IconToText(Icons.star_border, size: 20.px), | 44 | + onCollect: onCollect, |
42 | - text: '收藏', | 45 | + isCollect: isCollect, |
43 | - onTap: onComment, | ||
44 | ), | 46 | ), |
45 | _IconButton( | 47 | _IconButton( |
46 | icon: IconToText(Icons.share, size: 20.px), | 48 | icon: IconToText(Icons.share, size: 20.px), |
... | @@ -70,12 +72,35 @@ class FavoriteIcon extends StatelessWidget { | ... | @@ -70,12 +72,35 @@ class FavoriteIcon extends StatelessWidget { |
70 | size: 20, | 72 | size: 20, |
71 | color: isFavorite! ? ColorPlate.red : null, | 73 | color: isFavorite! ? ColorPlate.red : null, |
72 | ), | 74 | ), |
73 | - text: '喜爱', | 75 | + text: '点赞', |
74 | onTap: onFavorite, | 76 | onTap: onFavorite, |
75 | ); | 77 | ); |
76 | } | 78 | } |
77 | } | 79 | } |
78 | 80 | ||
81 | +class CollectIcon extends StatelessWidget { | ||
82 | + const CollectIcon({ | ||
83 | + Key? key, | ||
84 | + required this.onCollect, | ||
85 | + this.isCollect, | ||
86 | + }) : super(key: key); | ||
87 | + final bool? isCollect; | ||
88 | + final Function? onCollect; | ||
89 | + | ||
90 | + @override | ||
91 | + Widget build(BuildContext context) { | ||
92 | + return _IconButton( | ||
93 | + icon: IconToText( | ||
94 | + Icons.star_border_outlined, | ||
95 | + size: 20, | ||
96 | + color: isCollect! ? ColorPlate.red : null, | ||
97 | + ), | ||
98 | + text: '收藏', | ||
99 | + onTap: onCollect, | ||
100 | + ); | ||
101 | + } | ||
102 | +} | ||
103 | + | ||
79 | /// 把IconData转换为文字,使其可以使用文字样式 | 104 | /// 把IconData转换为文字,使其可以使用文字样式 |
80 | class IconToText extends StatelessWidget { | 105 | class IconToText extends StatelessWidget { |
81 | final IconData? icon; | 106 | final IconData? icon; |
... | @@ -90,6 +115,7 @@ class IconToText extends StatelessWidget { | ... | @@ -90,6 +115,7 @@ class IconToText extends StatelessWidget { |
90 | this.size, | 115 | this.size, |
91 | this.color, | 116 | this.color, |
92 | }) : super(key: key); | 117 | }) : super(key: key); |
118 | + | ||
93 | @override | 119 | @override |
94 | Widget build(BuildContext context) { | 120 | Widget build(BuildContext context) { |
95 | return Text( | 121 | return Text( |
... | @@ -109,6 +135,7 @@ class _IconButton extends StatelessWidget { | ... | @@ -109,6 +135,7 @@ class _IconButton extends StatelessWidget { |
109 | final Widget? icon; | 135 | final Widget? icon; |
110 | final String? text; | 136 | final String? text; |
111 | final Function? onTap; | 137 | final Function? onTap; |
138 | + | ||
112 | const _IconButton({ | 139 | const _IconButton({ |
113 | Key? key, | 140 | Key? key, |
114 | this.icon, | 141 | this.icon, |
... | @@ -130,8 +157,8 @@ class _IconButton extends StatelessWidget { | ... | @@ -130,8 +157,8 @@ class _IconButton extends StatelessWidget { |
130 | Widget body = Column( | 157 | Widget body = Column( |
131 | children: <Widget>[ | 158 | children: <Widget>[ |
132 | Tapped( | 159 | Tapped( |
133 | - child: icon ?? Container(), | ||
134 | onTap: onTap, | 160 | onTap: onTap, |
161 | + child: icon ?? Container(), | ||
135 | ), | 162 | ), |
136 | Container(height: 2.px), | 163 | Container(height: 2.px), |
137 | Text( | 164 | Text( |
... | @@ -146,8 +173,8 @@ class _IconButton extends StatelessWidget { | ... | @@ -146,8 +173,8 @@ class _IconButton extends StatelessWidget { |
146 | return Container( | 173 | return Container( |
147 | padding: EdgeInsets.symmetric(vertical: 10.px), | 174 | padding: EdgeInsets.symmetric(vertical: 10.px), |
148 | child: DefaultTextStyle( | 175 | child: DefaultTextStyle( |
149 | - child: body, | ||
150 | style: shadowStyle, | 176 | style: shadowStyle, |
177 | + child: body, | ||
151 | ), | 178 | ), |
152 | ); | 179 | ); |
153 | } | 180 | } | ... | ... |
-
Please register or login to post a comment