refa fav/group panel

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-06-19 10:54:34 +08:00
parent f440edf43b
commit 5644e9a0e1
9 changed files with 294 additions and 341 deletions

View File

@@ -0,0 +1,37 @@
import 'package:PiliPlus/models_new/fav/fav_folder/data.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/list.dart';
import 'package:PiliPlus/models_new/video/video_tag/data.dart';
import 'package:PiliPlus/services/account_service.dart';
import 'package:PiliPlus/utils/feed_back.dart';
import 'package:get/get.dart';
abstract class CommonIntroController extends GetxController {
// 是否点赞
RxBool hasLike = false.obs;
// 投币数量
final RxInt coinNum = 0.obs;
// 是否投币
bool get hasCoin => coinNum.value != 0;
// 是否收藏
RxBool hasFav = false.obs;
List<VideoTagItem>? videoTags;
Set? favIds;
Rx<FavFolderData> favFolderData = FavFolderData().obs;
AccountService accountService = Get.find<AccountService>();
Future queryVideoInFolder();
Future<void> actionFavVideo();
void onChoose(bool checkValue, int index) {
feedBack();
FavFolderInfo item = favFolderData.value.list![index];
item
..favState = checkValue ? 1 : 0
..mediaCount = checkValue ? item.mediaCount + 1 : item.mediaCount - 1;
favFolderData.refresh();
}
}

View File

@@ -1,5 +1,7 @@
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/data.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/list.dart';
import 'package:PiliPlus/pages/common/common_intro_controller.dart';
import 'package:PiliPlus/utils/fav_util.dart'; import 'package:PiliPlus/utils/fav_util.dart';
import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/feed_back.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -8,11 +10,11 @@ import 'package:get/get.dart';
class FavPanel extends StatefulWidget { class FavPanel extends StatefulWidget {
const FavPanel({ const FavPanel({
super.key, super.key,
this.ctr, required this.ctr,
this.scrollController, this.scrollController,
}); });
final dynamic ctr; final CommonIntroController ctr;
final ScrollController? scrollController; final ScrollController? scrollController;
@override @override
@@ -20,12 +22,66 @@ class FavPanel extends StatefulWidget {
} }
class _FavPanelState extends State<FavPanel> { class _FavPanelState extends State<FavPanel> {
late Future _futureBuilderFuture; LoadingState loadingState = LoadingState.loading();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_futureBuilderFuture = widget.ctr.queryVideoInFolder(); _query();
}
Future<void> _query() async {
var res = await widget.ctr.queryVideoInFolder();
if (mounted) {
if (res['status']) {
loadingState = const Success(null);
} else {
loadingState = Error(res['msg']);
}
setState(() {});
}
}
Widget get _buildBody {
return switch (loadingState) {
Loading() => loadingWidget,
Success() => ListView.builder(
controller: widget.scrollController,
itemCount: widget.ctr.favFolderData.value.list!.length,
itemBuilder: (context, index) {
FavFolderInfo item = widget.ctr.favFolderData.value.list![index];
return Material(
type: MaterialType.transparency,
child: ListTile(
onTap: () => setState(
() => widget.ctr.onChoose(item.favState != 1, index)),
dense: true,
leading: FavUtil.isPublicFav(item.attr)
? const Icon(Icons.folder_outlined)
: const Icon(Icons.lock_outline),
minLeadingWidth: 0,
title: Text(item.title),
subtitle: Text(
'${item.mediaCount}个内容 . ${FavUtil.isPublicFavText(item.attr)}',
),
trailing: Transform.scale(
scale: 0.9,
child: Checkbox(
value: item.favState == 1,
onChanged: (bool? checkValue) =>
setState(() => widget.ctr.onChoose(checkValue!, index)),
),
),
),
);
},
),
Error(:var errMsg) => scrollErrorWidget(
controller: widget.scrollController,
errMsg: errMsg,
onReload: _query,
),
};
} }
@override @override
@@ -45,7 +101,7 @@ class _FavPanelState extends State<FavPanel> {
TextButton.icon( TextButton.icon(
onPressed: () => Get.toNamed('/createFav')?.then((data) { onPressed: () => Get.toNamed('/createFav')?.then((data) {
if (data != null) { if (data != null) {
(widget.ctr?.favFolderData as Rx<FavFolderData>) widget.ctr.favFolderData
..value.list?.insert(1, data) ..value.list?.insert(1, data)
..refresh(); ..refresh();
} }
@@ -64,83 +120,7 @@ class _FavPanelState extends State<FavPanel> {
const SizedBox(width: 16), const SizedBox(width: 16),
], ],
), ),
Expanded( Expanded(child: _buildBody),
child: FutureBuilder(
future: _futureBuilderFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// TODO: refactor
if (snapshot.data is! Map) {
return HttpError(
isSliver: false,
onReload: () => setState(() {
_futureBuilderFuture = widget.ctr.queryVideoInFolder();
}),
);
}
Map data = snapshot.data as Map;
if (data['status']) {
return Obx(
() => ListView.builder(
controller: widget.scrollController,
itemCount: widget.ctr.favFolderData.value.list.length,
itemBuilder: (context, index) {
return Material(
type: MaterialType.transparency,
child: ListTile(
onTap: () => widget.ctr.onChoose(
widget.ctr.favFolderData.value.list[index]
.favState !=
1,
index),
dense: true,
leading: FavUtil.isPublicFav(widget
.ctr.favFolderData.value.list[index].attr)
? const Icon(Icons.folder_outlined)
: const Icon(Icons.lock_outline),
minLeadingWidth: 0,
title: Text(widget
.ctr.favFolderData.value.list[index].title!),
subtitle: Text(
'${widget.ctr.favFolderData.value.list[index].mediaCount}个内容 . ${FavUtil.isPublicFavText(widget.ctr.favFolderData.value.list[index].attr)}',
),
trailing: Transform.scale(
scale: 0.9,
child: Checkbox(
value: widget.ctr.favFolderData.value
.list[index].favState ==
1,
onChanged: (bool? checkValue) =>
widget.ctr.onChoose(checkValue!, index),
),
),
),
);
},
),
);
} else {
return CustomScrollView(
controller: widget.scrollController,
slivers: [
HttpError(
errMsg: data['msg'],
onReload: () => setState(() {
_futureBuilderFuture =
widget.ctr.queryVideoInFolder();
}),
)
],
);
}
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
),
Divider( Divider(
height: 1, height: 1,
color: theme.disabledColor.withValues(alpha: 0.08), color: theme.disabledColor.withValues(alpha: 0.08),

View File

@@ -1,4 +1,5 @@
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/member.dart'; import 'package:PiliPlus/http/member.dart';
import 'package:PiliPlus/models/member/tags.dart'; import 'package:PiliPlus/models/member/tags.dart';
import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/feed_back.dart';
@@ -22,32 +23,44 @@ class GroupPanel extends StatefulWidget {
} }
class _GroupPanelState extends State<GroupPanel> { class _GroupPanelState extends State<GroupPanel> {
late Future _futureBuilderFuture; LoadingState<List<MemberTagItemModel>> loadingState =
late List<MemberTagItemModel> tagsList; LoadingState<List<MemberTagItemModel>>.loading();
bool showDefaultBtn = true; bool showDefaultBtn = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_futureBuilderFuture = MemberHttp.followUpTags(); _query();
() async { }
var result = await _futureBuilderFuture;
if (result['status']) { void _query() {
tagsList = result['data']; MemberHttp.followUpTags().then((res) {
tagsList.removeWhere((item) => item.tagid == 0); if (mounted) {
tagsList = tagsList.map((item) { if (res['status']) {
return item..checked = widget.tags?.contains(item.tagid) == true; List<MemberTagItemModel> tagsList = (res['data']
}).toList(); as List<MemberTagItemModel>)
setState(() { ..removeWhere((item) => item.tagid == 0)
..map((item) {
return item.checked = widget.tags?.contains(item.tagid) == true;
}).toList();
showDefaultBtn = !tagsList.any((e) => e.checked == true); showDefaultBtn = !tagsList.any((e) => e.checked == true);
}); loadingState = Success(tagsList);
} else {
loadingState = Error(res['msg']);
}
setState(() {});
} }
}(); });
} }
Future<void> onSave() async { Future<void> onSave() async {
if (!loadingState.isSuccess) {
Get.back();
return;
}
feedBack(); feedBack();
// 是否有选中的 有选中的带id没选使用默认0 // 是否有选中的 有选中的带id没选使用默认0
List<MemberTagItemModel> tagsList = loadingState.data;
final bool anyHasChecked = final bool anyHasChecked =
tagsList.any((MemberTagItemModel e) => e.checked == true); tagsList.any((MemberTagItemModel e) => e.checked == true);
late List<int> tagidList; late List<int> tagidList;
@@ -66,6 +79,50 @@ class _GroupPanelState extends State<GroupPanel> {
} }
} }
Widget get _buildBody {
return switch (loadingState) {
Loading() => loadingWidget,
Success(:var response) => ListView.builder(
controller: widget.scrollController,
itemCount: response.length,
itemBuilder: (context, index) {
final item = response[index];
return Material(
type: MaterialType.transparency,
child: ListTile(
onTap: () {
item.checked = !item.checked!;
showDefaultBtn = !response.any((e) => e.checked == true);
setState(() {});
},
dense: true,
leading: const Icon(Icons.group_outlined),
minLeadingWidth: 0,
title: Text(item.name ?? ''),
subtitle: item.tip?.isNotEmpty == true ? Text(item.tip!) : null,
trailing: Transform.scale(
scale: 0.9,
child: Checkbox(
value: item.checked,
onChanged: (bool? checkValue) {
item.checked = checkValue;
showDefaultBtn = !response.any((e) => e.checked == true);
setState(() {});
},
),
),
),
);
},
),
Error(:var errMsg) => scrollErrorWidget(
controller: widget.scrollController,
errMsg: errMsg,
onReload: _query,
),
};
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
@@ -79,77 +136,7 @@ class _GroupPanelState extends State<GroupPanel> {
icon: const Icon(Icons.close_outlined)), icon: const Icon(Icons.close_outlined)),
title: const Text('设置关注分组'), title: const Text('设置关注分组'),
), ),
Expanded( Expanded(child: _buildBody),
child: FutureBuilder(
future: _futureBuilderFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// TODO: refactor
if (snapshot.data is! Map) {
return HttpError(
isSliver: false,
onReload: () => setState(() {
_futureBuilderFuture = MemberHttp.followUpTags();
}),
);
}
Map data = snapshot.data as Map;
if (data['status']) {
return ListView.builder(
controller: widget.scrollController,
itemCount: tagsList.length,
itemBuilder: (context, index) {
return Material(
type: MaterialType.transparency,
child: ListTile(
onTap: () {
tagsList[index].checked = !tagsList[index].checked!;
showDefaultBtn =
!tagsList.any((e) => e.checked == true);
setState(() {});
},
dense: true,
leading: const Icon(Icons.group_outlined),
minLeadingWidth: 0,
title: Text(tagsList[index].name ?? ''),
subtitle: tagsList[index].tip != ''
? Text(tagsList[index].tip ?? '')
: null,
trailing: Transform.scale(
scale: 0.9,
child: Checkbox(
value: tagsList[index].checked,
onChanged: (bool? checkValue) {
tagsList[index].checked = checkValue;
showDefaultBtn =
!tagsList.any((e) => e.checked == true);
setState(() {});
},
),
),
),
);
},
);
} else {
return CustomScrollView(
controller: widget.scrollController,
slivers: [
HttpError(
errMsg: data['msg'],
onReload: () => setState(() {}),
),
],
);
}
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
),
Divider( Divider(
height: 1, height: 1,
color: theme.disabledColor.withValues(alpha: 0.08), color: theme.disabledColor.withValues(alpha: 0.08),

View File

@@ -78,64 +78,66 @@ class _LikeMePageState extends State<LikeMePage> {
return const MsgFeedTopSkeleton(); return const MsgFeedTopSkeleton();
}, },
), ),
Success(:var response) => () { Success(:var response) => Builder(
Pair<List<MsgLikeItem>, List<MsgLikeItem>> pair = response; builder: (context) {
List<MsgLikeItem> latest = pair.first; Pair<List<MsgLikeItem>, List<MsgLikeItem>> pair = response;
List<MsgLikeItem> total = pair.second; List<MsgLikeItem> latest = pair.first;
if (latest.isNotEmpty || total.isNotEmpty) { List<MsgLikeItem> total = pair.second;
return SliverMainAxisGroup( if (latest.isNotEmpty || total.isNotEmpty) {
slivers: [ return SliverMainAxisGroup(
if (latest.isNotEmpty) ...[ slivers: [
_buildHeader(theme, '最新'), if (latest.isNotEmpty) ...[
SliverList.separated( _buildHeader(theme, '最新'),
itemBuilder: (context, index) { SliverList.separated(
if (total.isEmpty && index == latest.length - 1) { itemBuilder: (context, index) {
_likeMeController.onLoadMore(); if (total.isEmpty && index == latest.length - 1) {
} _likeMeController.onLoadMore();
return _buildItem( }
theme, return _buildItem(
latest[index], theme,
(id) { latest[index],
_likeMeController.onRemove(id, index, true); (id) {
}, _likeMeController.onRemove(id, index, true);
(isNotice, id) { },
_likeMeController.onSetNotice( (isNotice, id) {
id, index, isNotice, true); _likeMeController.onSetNotice(
}, id, index, isNotice, true);
); },
}, );
itemCount: latest.length, },
separatorBuilder: (context, index) => divider, itemCount: latest.length,
), separatorBuilder: (context, index) => divider,
),
],
if (total.isNotEmpty) ...[
_buildHeader(theme, '累计'),
SliverList.separated(
itemBuilder: (context, index) {
if (index == total.length - 1) {
_likeMeController.onLoadMore();
}
return _buildItem(
theme,
total[index],
(id) {
_likeMeController.onRemove(id, index, false);
},
(isNotice, id) {
_likeMeController.onSetNotice(
id, index, isNotice, false);
},
);
},
itemCount: total.length,
separatorBuilder: (context, index) => divider,
),
],
], ],
if (total.isNotEmpty) ...[ );
_buildHeader(theme, '累计'), }
SliverList.separated( return HttpError(onReload: _likeMeController.onReload);
itemBuilder: (context, index) { },
if (index == total.length - 1) { ),
_likeMeController.onLoadMore();
}
return _buildItem(
theme,
total[index],
(id) {
_likeMeController.onRemove(id, index, false);
},
(isNotice, id) {
_likeMeController.onSetNotice(
id, index, isNotice, false);
},
);
},
itemCount: total.length,
separatorBuilder: (context, index) => divider,
),
],
],
);
}
return HttpError(onReload: _likeMeController.onReload);
}(),
Error(:var errMsg) => HttpError( Error(:var errMsg) => HttpError(
errMsg: errMsg, errMsg: errMsg,
onReload: _likeMeController.onReload, onReload: _likeMeController.onReload,

View File

@@ -8,19 +8,16 @@ import 'package:PiliPlus/http/fav.dart';
import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/pgc_lcf.dart'; import 'package:PiliPlus/models/pgc_lcf.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/data.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/list.dart';
import 'package:PiliPlus/models_new/pgc/pgc_info_model/episode.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/episode.dart';
import 'package:PiliPlus/models_new/pgc/pgc_info_model/result.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/result.dart';
import 'package:PiliPlus/models_new/triple/pgc_triple.dart'; import 'package:PiliPlus/models_new/triple/pgc_triple.dart';
import 'package:PiliPlus/models_new/video/video_tag/data.dart'; import 'package:PiliPlus/pages/common/common_intro_controller.dart';
import 'package:PiliPlus/pages/dynamics_repost/view.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart';
import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/controller.dart';
import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
import 'package:PiliPlus/pages/video/pay_coins/view.dart'; import 'package:PiliPlus/pages/video/pay_coins/view.dart';
import 'package:PiliPlus/pages/video/reply/controller.dart'; import 'package:PiliPlus/pages/video/reply/controller.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart';
import 'package:PiliPlus/services/account_service.dart';
import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/feed_back.dart';
import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/global_data.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
@@ -30,7 +27,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
class PgcIntroController extends GetxController { class PgcIntroController extends CommonIntroController {
// 视频bvid // 视频bvid
String bvid = Get.parameters['bvid'] ?? ''; String bvid = Get.parameters['bvid'] ?? '';
var seasonId = Get.parameters['seasonId'] != null var seasonId = Get.parameters['seasonId'] != null
@@ -47,22 +44,6 @@ class PgcIntroController extends GetxController {
final PgcInfoModel pgcItem = Get.arguments['pgcItem']; final PgcInfoModel pgcItem = Get.arguments['pgcItem'];
// 是否点赞
RxBool hasLike = false.obs;
// 投币数量
final RxInt _coinNum = 0.obs;
// 是否投币
bool get hasCoin => _coinNum.value != 0;
// 是否收藏
RxBool hasFav = false.obs;
List<VideoTagItem>? videoTags;
List? favIds;
Rx<FavFolderData> favFolderData = FavFolderData().obs;
AccountService accountService = Get.find<AccountService>();
late final enableQuickFav = late final enableQuickFav =
GStorage.setting.get(SettingBoxKey.enableQuickFav, defaultValue: false); GStorage.setting.get(SettingBoxKey.enableQuickFav, defaultValue: false);
@@ -93,7 +74,7 @@ class PgcIntroController extends GetxController {
if (result['status']) { if (result['status']) {
PgcLCF data = result['data']; PgcLCF data = result['data'];
hasLike.value = data.like == 1; hasLike.value = data.like == 1;
_coinNum.value = data.coinNumber!; coinNum.value = data.coinNumber!;
hasFav.value = data.favorite == 1; hasFav.value = data.favorite == 1;
} else { } else {
SmartDialog.showToast(result['msg']); SmartDialog.showToast(result['msg']);
@@ -125,7 +106,7 @@ class PgcIntroController extends GetxController {
hasLike.value = true; hasLike.value = true;
pgcItem.stat!.likes = pgcItem.stat!.likes! + 1; pgcItem.stat!.likes = pgcItem.stat!.likes! + 1;
} }
_coinNum.value += coin; coinNum.value += coin;
GlobalData().afterCoin(coin); GlobalData().afterCoin(coin);
} else { } else {
SmartDialog.showToast(res['msg']); SmartDialog.showToast(res['msg']);
@@ -139,7 +120,7 @@ class PgcIntroController extends GetxController {
return; return;
} }
if (_coinNum.value >= 2) { if (coinNum.value >= 2) {
SmartDialog.showToast('达到投币上限啦~'); SmartDialog.showToast('达到投币上限啦~');
return; return;
} }
@@ -151,11 +132,12 @@ class PgcIntroController extends GetxController {
PayCoinsPage.toPayCoinsPage( PayCoinsPage.toPayCoinsPage(
onPayCoin: coinVideo, onPayCoin: coinVideo,
hasCoin: _coinNum.value == 1, hasCoin: coinNum.value == 1,
); );
} }
// (取消)收藏 pgc // (取消)收藏 pgc
@override
Future<void> actionFavVideo({String type = 'choose'}) async { Future<void> actionFavVideo({String type = 'choose'}) async {
// 收藏至默认文件夹 // 收藏至默认文件夹
if (type == 'default') { if (type == 'default') {
@@ -349,16 +331,6 @@ class PgcIntroController extends GetxController {
}); });
} }
// 选择文件夹
void onChoose(bool checkValue, int index) {
feedBack();
FavFolderInfo item = favFolderData.value.list![index];
item
..favState = checkValue ? 1 : 0
..mediaCount = checkValue ? item.mediaCount + 1 : item.mediaCount - 1;
favFolderData.refresh();
}
// 修改分P或番剧分集 // 修改分P或番剧分集
void changeSeasonOrbangu(dynamic epId, bvid, cid, aid, cover) { void changeSeasonOrbangu(dynamic epId, bvid, cid, aid, cover) {
// 重新获取视频资源 // 重新获取视频资源
@@ -431,6 +403,7 @@ class PgcIntroController extends GetxController {
SmartDialog.showToast(result['msg']); SmartDialog.showToast(result['msg']);
} }
@override
Future queryVideoInFolder() async { Future queryVideoInFolder() async {
favIds = null; favIds = null;
var result = await FavHttp.videoInFolder( var result = await FavHttp.videoInFolder(
@@ -443,7 +416,7 @@ class PgcIntroController extends GetxController {
favIds = favFolderData.value.list favIds = favFolderData.value.list
?.where((item) => item.favState == 1) ?.where((item) => item.favState == 1)
.map((item) => item.id) .map((item) => item.id)
.toList(); .toSet();
} }
return result; return result;
} }
@@ -522,7 +495,7 @@ class PgcIntroController extends GetxController {
PgcTriple data = result['data']; PgcTriple data = result['data'];
hasLike.value = data.like == 1; hasLike.value = data.like == 1;
if (data.coin == 1) { if (data.coin == 1) {
_coinNum.value = 2; coinNum.value = 2;
GlobalData().afterCoin(2); GlobalData().afterCoin(2);
} }
hasFav.value = data.favorite == 1; hasFav.value = data.favorite == 1;

View File

@@ -9,8 +9,6 @@ import 'package:PiliPlus/http/member.dart';
import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/http/search.dart';
import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/data.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/list.dart';
import 'package:PiliPlus/models_new/triple/ugc_triple.dart'; import 'package:PiliPlus/models_new/triple/ugc_triple.dart';
import 'package:PiliPlus/models_new/video/video_ai_conclusion/data.dart'; import 'package:PiliPlus/models_new/video/video_ai_conclusion/data.dart';
import 'package:PiliPlus/models_new/video/video_ai_conclusion/model_result.dart'; import 'package:PiliPlus/models_new/video/video_ai_conclusion/model_result.dart';
@@ -21,14 +19,13 @@ import 'package:PiliPlus/models_new/video/video_detail/section.dart';
import 'package:PiliPlus/models_new/video/video_detail/staff.dart'; import 'package:PiliPlus/models_new/video/video_detail/staff.dart';
import 'package:PiliPlus/models_new/video/video_detail/ugc_season.dart'; import 'package:PiliPlus/models_new/video/video_detail/ugc_season.dart';
import 'package:PiliPlus/models_new/video/video_relation/data.dart'; import 'package:PiliPlus/models_new/video/video_relation/data.dart';
import 'package:PiliPlus/models_new/video/video_tag/data.dart'; import 'package:PiliPlus/pages/common/common_intro_controller.dart';
import 'package:PiliPlus/pages/dynamics_repost/view.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart';
import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/controller.dart';
import 'package:PiliPlus/pages/video/pay_coins/view.dart'; import 'package:PiliPlus/pages/video/pay_coins/view.dart';
import 'package:PiliPlus/pages/video/related/controller.dart'; import 'package:PiliPlus/pages/video/related/controller.dart';
import 'package:PiliPlus/pages/video/reply/controller.dart'; import 'package:PiliPlus/pages/video/reply/controller.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart';
import 'package:PiliPlus/services/account_service.dart';
import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/services/service_locator.dart';
import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/feed_back.dart';
@@ -44,42 +41,26 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
class VideoIntroController extends GetxController { class VideoIntroController extends CommonIntroController {
// 视频bvid // 视频bvid
late String bvid; late String bvid;
// 是否预渲染 骨架屏
bool preRender = false;
// 视频详情 上个页面传入 // 视频详情 上个页面传入
Map videoItem = {}; Map videoItem = {};
late final RxMap staffRelations = {}.obs; late final RxMap staffRelations = {}.obs;
// 请求状态
RxBool isLoading = false.obs;
// 视频详情 请求返回 // 视频详情 请求返回
Rx<VideoDetailData> videoDetail = VideoDetailData().obs; Rx<VideoDetailData> videoDetail = VideoDetailData().obs;
// up主粉丝数 // up主粉丝数
RxMap<String, dynamic> userStat = RxMap<String, dynamic>({'follower': '-'}); RxMap<String, dynamic> userStat = RxMap<String, dynamic>({'follower': '-'});
List<VideoTagItem>? videoTags;
// 是否点赞
RxBool hasLike = false.obs;
// 是否点踩 // 是否点踩
RxBool hasDislike = false.obs; RxBool hasDislike = false.obs;
// 投币数量
final RxInt _coinNum = 0.obs;
// 是否投币
bool get hasCoin => _coinNum.value != 0;
// 是否收藏
RxBool hasFav = false.obs;
// 是否稍后再看 // 是否稍后再看
RxBool hasLater = false.obs; RxBool hasLater = false.obs;
Rx<FavFolderData> favFolderData = FavFolderData().obs;
Set? favIds;
// 关注状态 默认未关注 // 关注状态 默认未关注
RxMap followStatus = {}.obs; RxMap followStatus = {}.obs;
@@ -102,8 +83,6 @@ class VideoIntroController extends GetxController {
late final enableQuickFav = late final enableQuickFav =
GStorage.setting.get(SettingBoxKey.enableQuickFav, defaultValue: false); GStorage.setting.get(SettingBoxKey.enableQuickFav, defaultValue: false);
AccountService accountService = Get.find<AccountService>();
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
@@ -115,7 +94,6 @@ class VideoIntroController extends GetxController {
} catch (_) {} } catch (_) {}
if (Get.arguments.isNotEmpty) { if (Get.arguments.isNotEmpty) {
if (Get.arguments.containsKey('videoItem')) { if (Get.arguments.containsKey('videoItem')) {
preRender = true;
var args = Get.arguments['videoItem']; var args = Get.arguments['videoItem'];
var keys = Get.arguments.keys.toList(); var keys = Get.arguments.keys.toList();
try { try {
@@ -243,7 +221,7 @@ class VideoIntroController extends GetxController {
VideoRelation data = result['data']; VideoRelation data = result['data'];
hasLike.value = data.like!; hasLike.value = data.like!;
hasDislike.value = data.dislike!; hasDislike.value = data.dislike!;
_coinNum.value = data.coin!; coinNum.value = data.coin!;
hasFav.value = data.favorite!; hasFav.value = data.favorite!;
} }
} }
@@ -265,7 +243,7 @@ class VideoIntroController extends GetxController {
UgcTriple data = result['data']; UgcTriple data = result['data'];
hasLike.value = data.like!; hasLike.value = data.like!;
if (data.coin == true) { if (data.coin == true) {
_coinNum.value = 2; coinNum.value = 2;
GlobalData().afterCoin(2); GlobalData().afterCoin(2);
} }
hasFav.value = data.fav!; hasFav.value = data.fav!;
@@ -342,7 +320,7 @@ class VideoIntroController extends GetxController {
); );
if (res['status']) { if (res['status']) {
SmartDialog.showToast('投币成功'); SmartDialog.showToast('投币成功');
_coinNum.value += coin; coinNum.value += coin;
GlobalData().afterCoin(coin); GlobalData().afterCoin(coin);
videoDetail.value.stat!.coin = videoDetail.value.stat!.coin! + coin; videoDetail.value.stat!.coin = videoDetail.value.stat!.coin! + coin;
if (selectLike && !hasLike.value) { if (selectLike && !hasLike.value) {
@@ -363,7 +341,7 @@ class VideoIntroController extends GetxController {
int copyright = int copyright =
(queryVideoIntroData['data'] as VideoDetailData?)?.copyright ?? 1; (queryVideoIntroData['data'] as VideoDetailData?)?.copyright ?? 1;
if ((copyright != 1 && _coinNum.value >= 1) || _coinNum.value >= 2) { if ((copyright != 1 && coinNum.value >= 1) || coinNum.value >= 2) {
SmartDialog.showToast('达到投币上限啦~'); SmartDialog.showToast('达到投币上限啦~');
return; return;
} }
@@ -376,11 +354,12 @@ class VideoIntroController extends GetxController {
PayCoinsPage.toPayCoinsPage( PayCoinsPage.toPayCoinsPage(
onPayCoin: coinVideo, onPayCoin: coinVideo,
copyright: copyright, copyright: copyright,
hasCoin: _coinNum.value == 1, hasCoin: coinNum.value == 1,
); );
} }
// (取消)收藏 // (取消)收藏
@override
Future<void> actionFavVideo({String type = 'choose'}) async { Future<void> actionFavVideo({String type = 'choose'}) async {
// 收藏至默认文件夹 // 收藏至默认文件夹
if (type == 'default') { if (type == 'default') {
@@ -546,6 +525,7 @@ class VideoIntroController extends GetxController {
}); });
} }
@override
Future queryVideoInFolder() async { Future queryVideoInFolder() async {
favIds = null; favIds = null;
var result = await FavHttp.videoInFolder( var result = await FavHttp.videoInFolder(
@@ -562,16 +542,6 @@ class VideoIntroController extends GetxController {
return result; return result;
} }
// 选择文件夹
void onChoose(bool checkValue, int index) {
feedBack();
FavFolderInfo item = favFolderData.value.list![index];
item
..favState = checkValue ? 1 : 0
..mediaCount = checkValue ? item.mediaCount + 1 : item.mediaCount - 1;
favFolderData.refresh();
}
// 查询关注状态 // 查询关注状态
Future<void> queryFollowStatus() async { Future<void> queryFollowStatus() async {
if (videoDetail.value.owner == null) { if (videoDetail.value.owner == null) {

View File

@@ -380,43 +380,45 @@ class _VideoReplyReplyPanelState
itemCount: 8, itemCount: 8,
), ),
), ),
Success(:var response) => () { Success(:var response) => Builder(
if (index == response!.length) { builder: (context) {
_videoReplyReplyController.onLoadMore(); if (index == response!.length) {
return Container( _videoReplyReplyController.onLoadMore();
alignment: Alignment.center, return Container(
margin: alignment: Alignment.center,
EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom), margin: EdgeInsets.only(
height: 125, bottom: MediaQuery.paddingOf(context).bottom),
child: Text( height: 125,
_videoReplyReplyController.isEnd ? '没有更多了' : '加载中...', child: Text(
style: TextStyle( _videoReplyReplyController.isEnd ? '没有更多了' : '加载中...',
fontSize: 12, style: TextStyle(
color: theme.colorScheme.outline, fontSize: 12,
color: theme.colorScheme.outline,
),
), ),
),
);
} else {
if (_videoReplyReplyController.index != null &&
_videoReplyReplyController.index == index) {
colorAnimation ??= ColorTween(
begin: theme.colorScheme.onInverseSurface,
end: theme.colorScheme.surface,
).animate(_videoReplyReplyController.controller!);
return AnimatedBuilder(
animation: colorAnimation!,
builder: (context, child) {
return ColoredBox(
color: colorAnimation!.value ??
theme.colorScheme.onInverseSurface,
child: _replyItem(response[index], index),
);
},
); );
} else {
if (_videoReplyReplyController.index != null &&
_videoReplyReplyController.index == index) {
colorAnimation ??= ColorTween(
begin: theme.colorScheme.onInverseSurface,
end: theme.colorScheme.surface,
).animate(_videoReplyReplyController.controller!);
return AnimatedBuilder(
animation: colorAnimation!,
builder: (context, child) {
return ColoredBox(
color: colorAnimation!.value ??
theme.colorScheme.onInverseSurface,
child: _replyItem(response[index], index),
);
},
);
}
return _replyItem(response[index], index);
} }
return _replyItem(response[index], index); },
} ),
}(),
Error(:var errMsg) => errorWidget( Error(:var errMsg) => errorWidget(
errMsg: errMsg, errMsg: errMsg,
onReload: _videoReplyReplyController.onReload, onReload: _videoReplyReplyController.onReload,

View File

@@ -10,6 +10,7 @@ import 'package:PiliPlus/models/dynamics/result.dart';
import 'package:PiliPlus/models_new/pgc/pgc_info_model/episode.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/episode.dart';
import 'package:PiliPlus/models_new/pgc/pgc_info_model/result.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/result.dart';
import 'package:PiliPlus/models_new/pgc/pgc_info_model/section.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/section.dart';
import 'package:PiliPlus/pages/common/common_intro_controller.dart';
import 'package:PiliPlus/pages/contact/view.dart'; import 'package:PiliPlus/pages/contact/view.dart';
import 'package:PiliPlus/pages/fav_panel/view.dart'; import 'package:PiliPlus/pages/fav_panel/view.dart';
import 'package:PiliPlus/pages/share/view.dart'; import 'package:PiliPlus/pages/share/view.dart';
@@ -279,7 +280,7 @@ class PageUtils {
static void showFavBottomSheet({ static void showFavBottomSheet({
required BuildContext context, required BuildContext context,
required dynamic ctr, required CommonIntroController ctr,
}) { }) {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,

View File

@@ -110,7 +110,7 @@ class RequestUtils {
callback?.call(2); callback?.call(2);
} }
} else { } else {
if (followStatus == null) { if (followStatus?['tag'] == null) {
Map<String, dynamic> result = await UserHttp.hasFollow(mid); Map<String, dynamic> result = await UserHttp.hasFollow(mid);
if (result['status']) { if (result['status']) {
followStatus = result['data']; followStatus = result['data'];
@@ -119,6 +119,7 @@ class RequestUtils {
return; return;
} }
} }
if (context.mounted) { if (context.mounted) {
showDialog( showDialog(
context: context, context: context,