mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
@@ -101,7 +101,10 @@ class UserHttp {
|
|||||||
contentType: Headers.formUrlEncodedContentType,
|
contentType: Headers.formUrlEncodedContentType,
|
||||||
));
|
));
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': FavFolderItemData.fromJson(res.data['data'])
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return {'status': false, 'msg': res.data['message']};
|
return {'status': false, 'msg': res.data['message']};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:PiliPalaX/models/model_owner.dart';
|
import 'package:PiliPalaX/models/model_owner.dart';
|
||||||
|
import 'package:PiliPalaX/models/user/fav_folder.dart';
|
||||||
|
|
||||||
class FavDetailData {
|
class FavDetailData {
|
||||||
FavDetailData({
|
FavDetailData({
|
||||||
@@ -7,12 +8,13 @@ class FavDetailData {
|
|||||||
this.hasMore,
|
this.hasMore,
|
||||||
});
|
});
|
||||||
|
|
||||||
Map? info;
|
FavFolderItemData? info;
|
||||||
List<FavDetailItemData>? medias;
|
List<FavDetailItemData>? medias;
|
||||||
bool? hasMore;
|
bool? hasMore;
|
||||||
|
|
||||||
FavDetailData.fromJson(Map<String, dynamic> json) {
|
FavDetailData.fromJson(Map<String, dynamic> json) {
|
||||||
info = json['info'];
|
info =
|
||||||
|
json['info'] == null ? null : FavFolderItemData.fromJson(json['info']);
|
||||||
medias = json['medias'] != null
|
medias = json['medias'] != null
|
||||||
? json['medias']
|
? json['medias']
|
||||||
.map<FavDetailItemData>((e) => FavDetailItemData.fromJson(e))
|
.map<FavDetailItemData>((e) => FavDetailItemData.fromJson(e))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:PiliPalaX/common/skeleton/video_card_h.dart';
|
import 'package:PiliPalaX/common/skeleton/video_card_h.dart';
|
||||||
|
import 'package:PiliPalaX/common/widgets/refresh_indicator.dart';
|
||||||
import 'package:PiliPalaX/http/loading_state.dart';
|
import 'package:PiliPalaX/http/loading_state.dart';
|
||||||
import 'package:PiliPalaX/models/user/fav_folder.dart';
|
|
||||||
import 'package:PiliPalaX/pages/fav_search/view.dart';
|
import 'package:PiliPalaX/pages/fav_search/view.dart';
|
||||||
import 'package:PiliPalaX/utils/utils.dart';
|
import 'package:PiliPalaX/utils/utils.dart';
|
||||||
import 'package:easy_debounce/easy_throttle.dart';
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
@@ -57,17 +57,7 @@ class _FavPageState extends State<FavPage> {
|
|||||||
List list = _favController.loadingState.value is Success
|
List list = _favController.loadingState.value is Success
|
||||||
? (_favController.loadingState.value as Success).response
|
? (_favController.loadingState.value as Success).response
|
||||||
: [];
|
: [];
|
||||||
list.insert(
|
list.insert(list.isNotEmpty ? 1 : 0, data);
|
||||||
list.isNotEmpty ? 1 : 0,
|
|
||||||
FavFolderItemData(
|
|
||||||
id: data['id'],
|
|
||||||
fid: data['fid'],
|
|
||||||
attr: data['attr'],
|
|
||||||
title: data['title'],
|
|
||||||
favState: data['fav_state'],
|
|
||||||
mediaCount: data['media_count'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
_favController.loadingState.value =
|
_favController.loadingState.value =
|
||||||
LoadingState.success(list);
|
LoadingState.success(list);
|
||||||
}
|
}
|
||||||
@@ -95,14 +85,19 @@ class _FavPageState extends State<FavPage> {
|
|||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: CustomScrollView(
|
body: refreshIndicator(
|
||||||
controller: _favController.scrollController,
|
onRefresh: () async {
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
await _favController.onRefresh();
|
||||||
slivers: [
|
},
|
||||||
Obx(
|
child: CustomScrollView(
|
||||||
() => _buildBody(_favController.loadingState.value),
|
controller: _favController.scrollController,
|
||||||
),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
],
|
slivers: [
|
||||||
|
Obx(
|
||||||
|
() => _buildBody(_favController.loadingState.value),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -124,30 +119,34 @@ class _FavPageState extends State<FavPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success() => (loadingState.response as List?)?.isNotEmpty == true
|
Success() => (loadingState.response as List?)?.isNotEmpty == true
|
||||||
? SliverGrid(
|
? SliverPadding(
|
||||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
padding: EdgeInsets.only(
|
||||||
mainAxisSpacing: StyleString.cardSpace,
|
bottom: 80 + MediaQuery.paddingOf(context).bottom),
|
||||||
crossAxisSpacing: StyleString.safeSpace,
|
sliver: SliverGrid(
|
||||||
maxCrossAxisExtent: Grid.maxRowWidth * 2,
|
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||||
childAspectRatio: StyleString.aspectRatio * 2.4,
|
mainAxisSpacing: StyleString.cardSpace,
|
||||||
mainAxisExtent: 0),
|
crossAxisSpacing: StyleString.safeSpace,
|
||||||
delegate: SliverChildBuilderDelegate(
|
maxCrossAxisExtent: Grid.maxRowWidth * 2,
|
||||||
childCount: loadingState.response.length,
|
childAspectRatio: StyleString.aspectRatio * 2.4,
|
||||||
(BuildContext context, int index) {
|
mainAxisExtent: 0),
|
||||||
String heroTag =
|
delegate: SliverChildBuilderDelegate(
|
||||||
Utils.makeHeroTag(loadingState.response[index].fid);
|
childCount: loadingState.response.length,
|
||||||
return FavItem(
|
(BuildContext context, int index) {
|
||||||
heroTag: heroTag,
|
String heroTag =
|
||||||
favFolderItem: loadingState.response[index],
|
Utils.makeHeroTag(loadingState.response[index].fid);
|
||||||
onTap: () {
|
return FavItem(
|
||||||
Get.toNamed(
|
heroTag: heroTag,
|
||||||
'/favDetail',
|
favFolderItem: loadingState.response[index],
|
||||||
arguments: loadingState.response[index],
|
onTap: () async {
|
||||||
parameters: {
|
dynamic res = await Get.toNamed(
|
||||||
'heroTag': heroTag,
|
'/favDetail',
|
||||||
'mediaId': loadingState.response[index].id.toString(),
|
arguments: loadingState.response[index],
|
||||||
},
|
parameters: {
|
||||||
)?.then((res) {
|
'heroTag': heroTag,
|
||||||
|
'mediaId':
|
||||||
|
loadingState.response[index].id.toString(),
|
||||||
|
},
|
||||||
|
);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
List list =
|
List list =
|
||||||
(_favController.loadingState.value as Success)
|
(_favController.loadingState.value as Success)
|
||||||
@@ -155,11 +154,15 @@ class _FavPageState extends State<FavPage> {
|
|||||||
list.removeAt(index);
|
list.removeAt(index);
|
||||||
_favController.loadingState.value =
|
_favController.loadingState.value =
|
||||||
LoadingState.success(list);
|
LoadingState.success(list);
|
||||||
|
} else {
|
||||||
|
Future.delayed(const Duration(milliseconds: 150), () {
|
||||||
|
_favController.onRefresh();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
},
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:PiliPalaX/models/user/fav_folder.dart';
|
||||||
|
import 'package:PiliPalaX/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:PiliPalaX/common/constants.dart';
|
import 'package:PiliPalaX/common/constants.dart';
|
||||||
import 'package:PiliPalaX/common/widgets/network_img_layer.dart';
|
import 'package:PiliPalaX/common/widgets/network_img_layer.dart';
|
||||||
@@ -58,7 +60,7 @@ class FavItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class VideoContent extends StatelessWidget {
|
class VideoContent extends StatelessWidget {
|
||||||
final dynamic favFolderItem;
|
final FavFolderItemData favFolderItem;
|
||||||
const VideoContent({super.key, required this.favFolderItem});
|
const VideoContent({super.key, required this.favFolderItem});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -70,17 +72,16 @@ class VideoContent extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
favFolderItem.title,
|
favFolderItem.title ?? '',
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
letterSpacing: 0.3,
|
letterSpacing: 0.3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (favFolderItem.intro.isNotEmpty)
|
if (favFolderItem.intro?.isNotEmpty == true)
|
||||||
Text(
|
Text(
|
||||||
favFolderItem.intro,
|
favFolderItem.intro!,
|
||||||
textAlign: TextAlign.start,
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
color: Theme.of(context).colorScheme.outline,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
@@ -88,7 +89,14 @@ class VideoContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${favFolderItem.mediaCount}个内容',
|
'${favFolderItem.mediaCount}个内容',
|
||||||
textAlign: TextAlign.start,
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
Utils.isPublicText(favFolderItem.attr ?? 0),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
color: Theme.of(context).colorScheme.outline,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:PiliPalaX/http/loading_state.dart';
|
import 'package:PiliPalaX/http/loading_state.dart';
|
||||||
import 'package:PiliPalaX/http/user.dart';
|
import 'package:PiliPalaX/http/user.dart';
|
||||||
|
import 'package:PiliPalaX/models/user/fav_folder.dart';
|
||||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||||
import 'package:PiliPalaX/utils/extension.dart';
|
import 'package:PiliPalaX/utils/extension.dart';
|
||||||
import 'package:PiliPalaX/utils/storage.dart';
|
import 'package:PiliPalaX/utils/storage.dart';
|
||||||
@@ -8,15 +9,10 @@ import 'package:get/get.dart';
|
|||||||
import 'package:PiliPalaX/http/video.dart';
|
import 'package:PiliPalaX/http/video.dart';
|
||||||
|
|
||||||
class FavDetailController extends CommonController {
|
class FavDetailController extends CommonController {
|
||||||
// FavFolderItemData? item;
|
Rx<FavFolderItemData> item = FavFolderItemData().obs;
|
||||||
int? mediaId;
|
int? mediaId;
|
||||||
late String heroTag;
|
late String heroTag;
|
||||||
RxString loadingText = '加载中...'.obs;
|
RxString loadingText = '加载中...'.obs;
|
||||||
int mediaCount = 0;
|
|
||||||
RxString title = ''.obs;
|
|
||||||
RxString cover = ''.obs;
|
|
||||||
RxString name = ''.obs;
|
|
||||||
late int attr;
|
|
||||||
RxBool isOwner = false.obs;
|
RxBool isOwner = false.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -48,12 +44,8 @@ class FavDetailController extends CommonController {
|
|||||||
@override
|
@override
|
||||||
bool customHandleResponse(Success response) {
|
bool customHandleResponse(Success response) {
|
||||||
if (currentPage == 1) {
|
if (currentPage == 1) {
|
||||||
title.value = response.response.info['title'];
|
item.value = response.response.info;
|
||||||
cover.value = response.response.info['cover'];
|
isOwner.value = response.response.info.mid ==
|
||||||
name.value = response.response.info['upper']['name'];
|
|
||||||
mediaCount = response.response.info['media_count'];
|
|
||||||
attr = response.response.info['attr'];
|
|
||||||
isOwner.value = response.response.info['mid'] ==
|
|
||||||
GStorage.userInfo.get('userInfoCache')?.mid;
|
GStorage.userInfo.get('userInfoCache')?.mid;
|
||||||
}
|
}
|
||||||
List currentList = loadingState.value is Success
|
List currentList = loadingState.value is Success
|
||||||
@@ -63,7 +55,7 @@ class FavDetailController extends CommonController {
|
|||||||
? response.response.medias
|
? response.response.medias
|
||||||
: currentList + response.response.medias;
|
: currentList + response.response.medias;
|
||||||
loadingState.value = LoadingState.success(dataList);
|
loadingState.value = LoadingState.success(dataList);
|
||||||
if (dataList.length >= mediaCount) {
|
if (dataList.length >= response.response.info.mediaCount) {
|
||||||
loadingText.value = '没有更多了';
|
loadingText.value = '没有更多了';
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:PiliPalaX/http/loading_state.dart';
|
import 'package:PiliPalaX/http/loading_state.dart';
|
||||||
import 'package:PiliPalaX/http/user.dart';
|
import 'package:PiliPalaX/http/user.dart';
|
||||||
|
import 'package:PiliPalaX/models/user/fav_folder.dart';
|
||||||
import 'package:PiliPalaX/pages/fav_search/view.dart' show SearchType;
|
import 'package:PiliPalaX/pages/fav_search/view.dart' show SearchType;
|
||||||
import 'package:PiliPalaX/utils/utils.dart';
|
import 'package:PiliPalaX/utils/utils.dart';
|
||||||
import 'package:easy_debounce/easy_throttle.dart';
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
@@ -86,11 +87,11 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
_favDetailController.title.value,
|
_favDetailController.item.value.title ?? '',
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'共${_favDetailController.mediaCount}条视频',
|
'共${_favDetailController.item.value.mediaCount}条视频',
|
||||||
style: Theme.of(context).textTheme.labelMedium,
|
style: Theme.of(context).textTheme.labelMedium,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -125,11 +126,16 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
'/createFav',
|
'/createFav',
|
||||||
parameters: {'mediaId': mediaId},
|
parameters: {'mediaId': mediaId},
|
||||||
);
|
)?.then((res) {
|
||||||
|
if (res is FavFolderItemData) {
|
||||||
|
_favDetailController.item.value = res;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
child: Text('编辑信息'),
|
child: Text('编辑信息'),
|
||||||
),
|
),
|
||||||
if (!Utils.isDefault(_favDetailController.attr))
|
if (!Utils.isDefault(
|
||||||
|
_favDetailController.item.value.attr ?? 0))
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
UserHttp.deleteFolder(mediaIds: [mediaId])
|
UserHttp.deleteFolder(mediaIds: [mediaId])
|
||||||
@@ -152,13 +158,6 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
],
|
],
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
background: Container(
|
background: Container(
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// border: Border(
|
|
||||||
// bottom: BorderSide(
|
|
||||||
// color: Theme.of(context).dividerColor.withOpacity(0.2),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: kTextTabBarHeight +
|
top: kTextTabBarHeight +
|
||||||
MediaQuery.of(context).padding.top +
|
MediaQuery.of(context).padding.top +
|
||||||
@@ -167,65 +166,84 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
right: 20),
|
right: 20),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 110,
|
height: 110,
|
||||||
child: Row(
|
child: Obx(
|
||||||
// mainAxisAlignment: MainAxisAlignment.center,
|
() => Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Obx(
|
Hero(
|
||||||
() => Hero(
|
|
||||||
tag: _favDetailController.heroTag,
|
tag: _favDetailController.heroTag,
|
||||||
child: NetworkImgLayer(
|
child: NetworkImgLayer(
|
||||||
width: 180,
|
width: 180,
|
||||||
height: 110,
|
height: 110,
|
||||||
src: _favDetailController.cover.value,
|
src: _favDetailController.item.value.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 14),
|
||||||
const SizedBox(width: 14),
|
Expanded(
|
||||||
Obx(
|
child: SizedBox(
|
||||||
() => Expanded(
|
height: 110,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const SizedBox(height: 4),
|
children: [
|
||||||
Text(
|
const SizedBox(height: 4),
|
||||||
_favDetailController.title.value,
|
Text(
|
||||||
style: TextStyle(
|
_favDetailController.item.value.title ?? '',
|
||||||
fontSize: Theme.of(context)
|
style: TextStyle(
|
||||||
.textTheme
|
fontSize: Theme.of(context)
|
||||||
.titleMedium!
|
.textTheme
|
||||||
.fontSize,
|
.titleMedium!
|
||||||
fontWeight: FontWeight.bold),
|
.fontSize,
|
||||||
),
|
fontWeight: FontWeight.bold),
|
||||||
const SizedBox(height: 4),
|
),
|
||||||
Text(
|
if (_favDetailController
|
||||||
_favDetailController.name.value,
|
.item.value.intro?.isNotEmpty ==
|
||||||
style: TextStyle(
|
true)
|
||||||
fontSize: Theme.of(context)
|
Text(
|
||||||
.textTheme
|
_favDetailController.item.value.intro ?? '',
|
||||||
.labelSmall!
|
style: TextStyle(
|
||||||
.fontSize,
|
fontSize: Theme.of(context)
|
||||||
color:
|
.textTheme
|
||||||
Theme.of(context).colorScheme.outline),
|
.labelSmall!
|
||||||
),
|
.fontSize,
|
||||||
const Spacer(),
|
color: Theme.of(context)
|
||||||
Text(
|
.colorScheme
|
||||||
'共${_favDetailController.mediaCount}条视频',
|
.outline),
|
||||||
style: TextStyle(
|
),
|
||||||
fontSize: Theme.of(context)
|
const SizedBox(height: 4),
|
||||||
.textTheme
|
Text(
|
||||||
.labelSmall!
|
_favDetailController.item.value.upper?.name ??
|
||||||
.fontSize,
|
'',
|
||||||
color:
|
style: TextStyle(
|
||||||
Theme.of(context).colorScheme.outline),
|
fontSize: Theme.of(context)
|
||||||
),
|
.textTheme
|
||||||
const SizedBox(height: 20),
|
.labelSmall!
|
||||||
],
|
.fontSize,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
if (_favDetailController.item.value.attr !=
|
||||||
|
null)
|
||||||
|
Text(
|
||||||
|
'共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicText(_favDetailController.item.value.attr ?? 0)}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelSmall!
|
||||||
|
.fontSize,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -83,10 +83,12 @@ class _FavSearchPageState extends State<FavSearchPage> {
|
|||||||
|
|
||||||
Widget _buildBody(LoadingState loadingState) {
|
Widget _buildBody(LoadingState loadingState) {
|
||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => loadingWidget,
|
Loading() => errorWidget(),
|
||||||
Success() => (loadingState.response as List?)?.isNotEmpty == true
|
Success() => (loadingState.response as List?)?.isNotEmpty == true
|
||||||
? _favSearchCtr.searchType == SearchType.fav
|
? _favSearchCtr.searchType == SearchType.fav
|
||||||
? ListView.builder(
|
? ListView.separated(
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const SizedBox(height: 10),
|
||||||
controller: _favSearchCtr.scrollController,
|
controller: _favSearchCtr.scrollController,
|
||||||
itemCount: loadingState.response.length + 1,
|
itemCount: loadingState.response.length + 1,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
|
|||||||
@@ -134,7 +134,12 @@ class _MediaPageState extends State<MediaPage>
|
|||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () => Get.toNamed('/fav'),
|
onTap: () async {
|
||||||
|
await Get.toNamed('/fav');
|
||||||
|
Future.delayed(const Duration(milliseconds: 150), () {
|
||||||
|
mediaController.onRefresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
leading: null,
|
leading: null,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Padding(
|
title: Padding(
|
||||||
@@ -212,7 +217,12 @@ class _MediaPageState extends State<MediaPage>
|
|||||||
.withOpacity(0.5);
|
.withOpacity(0.5);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
onPressed: () => Get.toNamed('/fav'),
|
onPressed: () async {
|
||||||
|
await Get.toNamed('/fav');
|
||||||
|
Future.delayed(const Duration(milliseconds: 150), () {
|
||||||
|
mediaController.onRefresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
size: 18,
|
size: 18,
|
||||||
@@ -222,9 +232,25 @@ class _MediaPageState extends State<MediaPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
String heroTag =
|
||||||
|
Utils.makeHeroTag(loadingState.response.list[index].fid);
|
||||||
return FavFolderItem(
|
return FavFolderItem(
|
||||||
|
heroTag: heroTag,
|
||||||
item: loadingState.response.list[index],
|
item: loadingState.response.list[index],
|
||||||
index: index,
|
index: index,
|
||||||
|
onTap: () async {
|
||||||
|
await Get.toNamed(
|
||||||
|
'/favDetail',
|
||||||
|
arguments: loadingState.response.list[index],
|
||||||
|
parameters: {
|
||||||
|
'mediaId': loadingState.response.list[index].id.toString(),
|
||||||
|
'heroTag': heroTag,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Future.delayed(const Duration(milliseconds: 150), () {
|
||||||
|
mediaController.onRefresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -242,19 +268,25 @@ class _MediaPageState extends State<MediaPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FavFolderItem extends StatelessWidget {
|
class FavFolderItem extends StatelessWidget {
|
||||||
const FavFolderItem({super.key, this.item, this.index});
|
const FavFolderItem({
|
||||||
|
super.key,
|
||||||
|
this.item,
|
||||||
|
this.index,
|
||||||
|
required this.onTap,
|
||||||
|
required this.heroTag,
|
||||||
|
});
|
||||||
|
|
||||||
final FavFolderItemData? item;
|
final FavFolderItemData? item;
|
||||||
final int? index;
|
final int? index;
|
||||||
|
final GestureTapCallback onTap;
|
||||||
|
final String heroTag;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String heroTag = Utils.makeHeroTag(item!.fid);
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14),
|
margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => Get.toNamed('/favDetail',
|
onTap: onTap,
|
||||||
arguments: item,
|
|
||||||
parameters: {'mediaId': item!.id.toString(), 'heroTag': heroTag}),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -302,7 +334,7 @@ class FavFolderItem extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
' 共${item!.mediaCount}条视频',
|
' 共${item!.mediaCount}条视频 · ${Utils.isPublicText(item?.attr ?? 0)}',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.labelSmall!
|
.labelSmall!
|
||||||
|
|||||||
@@ -119,25 +119,28 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
|||||||
children: [
|
children: [
|
||||||
...(data.mediaListResponse?.list as List<FavList>).map(
|
...(data.mediaListResponse?.list as List<FavList>).map(
|
||||||
(item1) => ListTile(
|
(item1) => ListTile(
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
if (item1.state == 1) {
|
if (item1.state == 1) {
|
||||||
// invalid
|
// invalid
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item1.type == 0) {
|
if (item1.type == 0) {
|
||||||
Get.toNamed(
|
dynamic res = await Get.toNamed(
|
||||||
'/favDetail',
|
'/favDetail',
|
||||||
parameters: {
|
parameters: {
|
||||||
'mediaId': item1.id.toString(),
|
'mediaId': item1.id.toString(),
|
||||||
'heroTag': widget.heroTag ?? '',
|
'heroTag': widget.heroTag ?? '',
|
||||||
},
|
},
|
||||||
)?.then((res) {
|
);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
_controller.first.value.mediaListResponse?.list
|
_controller.first.value.mediaListResponse?.list
|
||||||
?.remove(item1);
|
?.remove(item1);
|
||||||
_controller.first.refresh();
|
_controller.first.refresh();
|
||||||
}
|
} else {
|
||||||
});
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
|
_controller.onRefresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (item1.type == 21) {
|
} else if (item1.type == 21) {
|
||||||
PiliScheme.routePush(Uri.parse(item1.link ?? ''));
|
PiliScheme.routePush(Uri.parse(item1.link ?? ''));
|
||||||
} else if (item1.type == 11) {
|
} else if (item1.type == 11) {
|
||||||
@@ -213,7 +216,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
|||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
item1.type == 0
|
item1.type == 0
|
||||||
? '${item1.mediaCount}个内容 · ${Utils.isPublic(item1.attr ?? 0) ? '公开' : '私密'}'
|
? '${item1.mediaCount}个内容 · ${Utils.isPublicText(item1.attr ?? 0)}'
|
||||||
: item1.type == 11
|
: item1.type == 11
|
||||||
? '${item1.mediaCount}个内容 · ${item1.upper?.name}'
|
? '${item1.mediaCount}个内容 · ${item1.upper?.name}'
|
||||||
: item1.type == 21
|
: item1.type == 21
|
||||||
|
|||||||
@@ -64,17 +64,7 @@ class _FavPanelState extends State<FavPanel> {
|
|||||||
if (data != null) {
|
if (data != null) {
|
||||||
(widget.ctr?.favFolderData.value as FavFolderData?)
|
(widget.ctr?.favFolderData.value as FavFolderData?)
|
||||||
?.list
|
?.list
|
||||||
?.insert(
|
?.insert(1, data);
|
||||||
1,
|
|
||||||
FavFolderItemData(
|
|
||||||
id: data['id'],
|
|
||||||
fid: data['fid'],
|
|
||||||
attr: data['attr'],
|
|
||||||
title: data['title'],
|
|
||||||
favState: data['fav_state'],
|
|
||||||
mediaCount: data['media_count'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
widget.ctr?.favFolderData.refresh();
|
widget.ctr?.favFolderData.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -125,7 +115,7 @@ class _FavPanelState extends State<FavPanel> {
|
|||||||
title: Text(widget.ctr!.favFolderData.value
|
title: Text(widget.ctr!.favFolderData.value
|
||||||
.list![index].title!),
|
.list![index].title!),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'${widget.ctr!.favFolderData.value.list![index].mediaCount}个内容 . ${Utils.isPublic(widget.ctr!.favFolderData.value.list![index].attr) ? '公开' : '私密'}',
|
'${widget.ctr!.favFolderData.value.list![index].mediaCount}个内容 . ${Utils.isPublicText(widget.ctr!.favFolderData.value.list![index].attr)}',
|
||||||
),
|
),
|
||||||
trailing: Transform.scale(
|
trailing: Transform.scale(
|
||||||
scale: 0.9,
|
scale: 0.9,
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ class Utils {
|
|||||||
return (attr & 2) == 0;
|
return (attr & 2) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String isPublicText(int attr) {
|
||||||
|
return isPublic(attr) ? '公开' : '私密';
|
||||||
|
}
|
||||||
|
|
||||||
static bool isPublic(int attr) {
|
static bool isPublic(int attr) {
|
||||||
return (attr & 1) == 0;
|
return (attr & 1) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user