mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-08-06 10:40:09 +08:00
@@ -196,8 +196,11 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
|||||||
List<Widget> _buildRcmd(ThemeData theme) => [
|
List<Widget> _buildRcmd(ThemeData theme) => [
|
||||||
_buildRcmdTitle(theme),
|
_buildRcmdTitle(theme),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: const EdgeInsets.fromLTRB(
|
padding: EdgeInsets.only(
|
||||||
StyleString.safeSpace, 0, StyleString.safeSpace, 0),
|
left: StyleString.safeSpace,
|
||||||
|
right: StyleString.safeSpace,
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
|
),
|
||||||
sliver: Obx(
|
sliver: Obx(
|
||||||
() => _buildRcmdBody(controller.loadingState.value),
|
() => _buildRcmdBody(controller.loadingState.value),
|
||||||
),
|
),
|
||||||
@@ -330,11 +333,15 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
|||||||
? Column(
|
? Column(
|
||||||
children: [
|
children: [
|
||||||
_buildFollowTitle(theme),
|
_buildFollowTitle(theme),
|
||||||
SizedBox(
|
MediaQuery.removePadding(
|
||||||
height: Grid.smallCardWidth / 2 / 0.75 +
|
context: context,
|
||||||
MediaQuery.textScalerOf(context).scale(50),
|
removeLeft: context.orientation == Orientation.landscape,
|
||||||
child: Obx(
|
child: SizedBox(
|
||||||
() => _buildFollowBody(controller.followState.value),
|
height: Grid.smallCardWidth / 2 / 0.75 +
|
||||||
|
MediaQuery.textScalerOf(context).scale(50),
|
||||||
|
child: Obx(
|
||||||
|
() => _buildFollowBody(controller.followState.value),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -415,31 +422,27 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
|||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => loadingWidget,
|
Loading() => loadingWidget,
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? MediaQuery.removePadding(
|
? ListView.builder(
|
||||||
context: context,
|
controller: controller.followController,
|
||||||
removeLeft: context.orientation == Orientation.landscape,
|
scrollDirection: Axis.horizontal,
|
||||||
child: ListView.builder(
|
itemCount: response!.length,
|
||||||
controller: controller.followController,
|
itemBuilder: (context, index) {
|
||||||
scrollDirection: Axis.horizontal,
|
if (index == response.length - 1) {
|
||||||
itemCount: response!.length,
|
controller.queryBangumiFollow(false);
|
||||||
itemBuilder: (context, index) {
|
}
|
||||||
if (index == response.length - 1) {
|
return Container(
|
||||||
controller.queryBangumiFollow(false);
|
width: Grid.smallCardWidth / 2,
|
||||||
}
|
margin: EdgeInsets.only(
|
||||||
return Container(
|
left: StyleString.safeSpace,
|
||||||
width: Grid.smallCardWidth / 2,
|
right: index == response.length - 1
|
||||||
margin: EdgeInsets.only(
|
? StyleString.safeSpace
|
||||||
left: StyleString.safeSpace,
|
: 0,
|
||||||
right: index == response.length - 1
|
),
|
||||||
? StyleString.safeSpace
|
child: BangumiCardV(
|
||||||
: 0,
|
bangumiItem: response[index],
|
||||||
),
|
),
|
||||||
child: BangumiCardV(
|
);
|
||||||
bangumiItem: response[index],
|
},
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: Center(
|
: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@@ -46,7 +46,12 @@ class _BlackListPageState extends State<BlackListPage> {
|
|||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: _blackListController.scrollController,
|
controller: _blackListController.scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(() => _buildBody(_blackListController.loadingState.value))
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||||
|
sliver: Obx(
|
||||||
|
() => _buildBody(_blackListController.loadingState.value)),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -55,7 +55,12 @@ abstract class CommonSearchPageState<S extends CommonSearchPage, R, T>
|
|||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: controller.scrollController,
|
controller: controller.scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(() => _buildBody(controller.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||||
|
),
|
||||||
|
sliver: Obx(() => _buildBody(controller.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -124,7 +124,12 @@ class _DynamicsTabPageState
|
|||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: controller.scrollController,
|
controller: controller.scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(() => _buildBody(controller.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
|
),
|
||||||
|
sliver: Obx(() => _buildBody(controller.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -134,57 +139,51 @@ class _DynamicsTabPageState
|
|||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => DynamicsTabPage.dynSkeleton(dynamicsWaterfallFlow),
|
Loading() => DynamicsTabPage.dynSkeleton(dynamicsWaterfallFlow),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? dynamicsWaterfallFlow
|
||||||
padding: EdgeInsets.only(
|
? SliverWaterfallFlow.extent(
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||||
),
|
crossAxisSpacing: StyleString.cardSpace / 2,
|
||||||
sliver: dynamicsWaterfallFlow
|
lastChildLayoutTypeBuilder: (index) {
|
||||||
? SliverWaterfallFlow.extent(
|
if (index == response.length - 1) {
|
||||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
controller.onLoadMore();
|
||||||
crossAxisSpacing: StyleString.cardSpace / 2,
|
}
|
||||||
lastChildLayoutTypeBuilder: (index) {
|
return index == response.length
|
||||||
if (index == response.length - 1) {
|
? LastChildLayoutType.foot
|
||||||
controller.onLoadMore();
|
: LastChildLayoutType.none;
|
||||||
}
|
},
|
||||||
return index == response.length
|
children: [
|
||||||
? LastChildLayoutType.foot
|
for (int index = 0; index < response!.length; index++)
|
||||||
: LastChildLayoutType.none;
|
DynamicPanel(
|
||||||
},
|
item: response[index],
|
||||||
children: [
|
onRemove: (idStr) => controller.onRemove(index, idStr),
|
||||||
for (int index = 0; index < response!.length; index++)
|
onBlock: () => controller.onBlock(index),
|
||||||
DynamicPanel(
|
)
|
||||||
item: response[index],
|
],
|
||||||
|
)
|
||||||
|
: SliverCrossAxisGroup(
|
||||||
|
slivers: [
|
||||||
|
const SliverFillRemaining(),
|
||||||
|
SliverConstrainedCrossAxis(
|
||||||
|
maxExtent: Grid.smallCardWidth * 2,
|
||||||
|
sliver: SliverList.builder(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == response.length - 1) {
|
||||||
|
controller.onLoadMore();
|
||||||
|
}
|
||||||
|
final item = response[index];
|
||||||
|
return DynamicPanel(
|
||||||
|
item: item,
|
||||||
onRemove: (idStr) =>
|
onRemove: (idStr) =>
|
||||||
controller.onRemove(index, idStr),
|
controller.onRemove(index, idStr),
|
||||||
onBlock: () => controller.onBlock(index),
|
onBlock: () => controller.onBlock(index),
|
||||||
)
|
);
|
||||||
],
|
},
|
||||||
)
|
itemCount: response!.length,
|
||||||
: SliverCrossAxisGroup(
|
),
|
||||||
slivers: [
|
|
||||||
const SliverFillRemaining(),
|
|
||||||
SliverConstrainedCrossAxis(
|
|
||||||
maxExtent: Grid.smallCardWidth * 2,
|
|
||||||
sliver: SliverList.builder(
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (index == response.length - 1) {
|
|
||||||
controller.onLoadMore();
|
|
||||||
}
|
|
||||||
final item = response[index];
|
|
||||||
return DynamicPanel(
|
|
||||||
item: item,
|
|
||||||
onRemove: (idStr) =>
|
|
||||||
controller.onRemove(index, idStr),
|
|
||||||
onBlock: () => controller.onBlock(index),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
itemCount: response!.length,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SliverFillRemaining(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
const SliverFillRemaining(),
|
||||||
|
],
|
||||||
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
onReload: controller.onReload,
|
onReload: controller.onReload,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -109,7 +109,12 @@ class _DynTopicPageState extends State<DynTopicPage> {
|
|||||||
}
|
}
|
||||||
return const SliverToBoxAdapter();
|
return const SliverToBoxAdapter();
|
||||||
}),
|
}),
|
||||||
Obx(() => _buildBody(_controller.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
|
),
|
||||||
|
sliver: Obx(() => _buildBody(_controller.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -302,56 +307,51 @@ class _DynTopicPageState extends State<DynTopicPage> {
|
|||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => DynamicsTabPage.dynSkeleton(dynamicsWaterfallFlow),
|
Loading() => DynamicsTabPage.dynSkeleton(dynamicsWaterfallFlow),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? dynamicsWaterfallFlow
|
||||||
padding: EdgeInsets.only(
|
? SliverWaterfallFlow.extent(
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||||
),
|
crossAxisSpacing: StyleString.cardSpace / 2,
|
||||||
sliver: dynamicsWaterfallFlow
|
lastChildLayoutTypeBuilder: (index) {
|
||||||
? SliverWaterfallFlow.extent(
|
if (index == response.length - 1) {
|
||||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
_controller.onLoadMore();
|
||||||
crossAxisSpacing: StyleString.cardSpace / 2,
|
}
|
||||||
lastChildLayoutTypeBuilder: (index) {
|
return index == response.length
|
||||||
if (index == response.length - 1) {
|
? LastChildLayoutType.foot
|
||||||
_controller.onLoadMore();
|
: LastChildLayoutType.none;
|
||||||
}
|
},
|
||||||
return index == response.length
|
children: [
|
||||||
? LastChildLayoutType.foot
|
for (var item in response!)
|
||||||
: LastChildLayoutType.none;
|
if (item.dynamicCardItem != null)
|
||||||
},
|
DynamicPanel(item: item.dynamicCardItem!)
|
||||||
children: [
|
else
|
||||||
for (var item in response!)
|
Text(item.topicType ?? 'err'),
|
||||||
if (item.dynamicCardItem != null)
|
],
|
||||||
DynamicPanel(item: item.dynamicCardItem!)
|
)
|
||||||
else
|
: SliverCrossAxisGroup(
|
||||||
Text(item.topicType ?? 'err'),
|
slivers: [
|
||||||
],
|
const SliverFillRemaining(),
|
||||||
)
|
SliverConstrainedCrossAxis(
|
||||||
: SliverCrossAxisGroup(
|
maxExtent: Grid.smallCardWidth * 2,
|
||||||
slivers: [
|
sliver: SliverList.builder(
|
||||||
const SliverFillRemaining(),
|
itemBuilder: (context, index) {
|
||||||
SliverConstrainedCrossAxis(
|
if (index == response.length - 1) {
|
||||||
maxExtent: Grid.smallCardWidth * 2,
|
_controller.onLoadMore();
|
||||||
sliver: SliverList.builder(
|
}
|
||||||
itemBuilder: (context, index) {
|
final item = response[index];
|
||||||
if (index == response.length - 1) {
|
if (item.dynamicCardItem != null) {
|
||||||
_controller.onLoadMore();
|
return DynamicPanel(
|
||||||
}
|
item: item.dynamicCardItem!,
|
||||||
final item = response[index];
|
);
|
||||||
if (item.dynamicCardItem != null) {
|
} else {
|
||||||
return DynamicPanel(
|
return Text(item.topicType ?? 'err');
|
||||||
item: item.dynamicCardItem!,
|
}
|
||||||
);
|
},
|
||||||
} else {
|
itemCount: response!.length,
|
||||||
return Text(item.topicType ?? 'err');
|
),
|
||||||
}
|
|
||||||
},
|
|
||||||
itemCount: response!.length,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SliverFillRemaining(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
const SliverFillRemaining(),
|
||||||
|
],
|
||||||
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
onReload: _controller.onReload,
|
onReload: _controller.onReload,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -61,7 +61,12 @@ class _FansPageState extends State<FansPage> {
|
|||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: _fansController.scrollController,
|
controller: _fansController.scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(() => _buildBody(_fansController.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||||
|
sliver:
|
||||||
|
Obx(() => _buildBody(_fansController.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -84,74 +89,70 @@ class _FansPageState extends State<FansPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||||
sliver: SliverGrid(
|
mainAxisExtent: 66,
|
||||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
),
|
||||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
delegate: SliverChildBuilderDelegate(
|
||||||
mainAxisExtent: 66,
|
(BuildContext context, int index) {
|
||||||
),
|
if (index == response.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
_fansController.onLoadMore();
|
||||||
(BuildContext context, int index) {
|
}
|
||||||
if (index == response.length - 1) {
|
final item = response[index];
|
||||||
_fansController.onLoadMore();
|
String heroTag = Utils.makeHeroTag(item.mid);
|
||||||
}
|
return ListTile(
|
||||||
final item = response[index];
|
onTap: () {
|
||||||
String heroTag = Utils.makeHeroTag(item.mid);
|
if (widget.onSelect != null) {
|
||||||
return ListTile(
|
widget.onSelect!(UserModel(
|
||||||
onTap: () {
|
mid: item.mid!,
|
||||||
if (widget.onSelect != null) {
|
name: item.uname!,
|
||||||
widget.onSelect!(UserModel(
|
avatar: item.face!,
|
||||||
mid: item.mid!,
|
));
|
||||||
name: item.uname!,
|
return;
|
||||||
avatar: item.face!,
|
}
|
||||||
));
|
Get.toNamed(
|
||||||
return;
|
'/member?mid=${item.mid}',
|
||||||
}
|
arguments: {'face': item.face, 'heroTag': heroTag},
|
||||||
Get.toNamed(
|
);
|
||||||
'/member?mid=${item.mid}',
|
},
|
||||||
arguments: {'face': item.face, 'heroTag': heroTag},
|
onLongPress: widget.onSelect != null
|
||||||
);
|
? null
|
||||||
},
|
: isOwner
|
||||||
onLongPress: widget.onSelect != null
|
? () {
|
||||||
? null
|
showConfirmDialog(
|
||||||
: isOwner
|
context: context,
|
||||||
? () {
|
title: '确定移除 ${item.uname} ?',
|
||||||
showConfirmDialog(
|
onConfirm: () {
|
||||||
context: context,
|
_fansController.onRemoveFan(
|
||||||
title: '确定移除 ${item.uname} ?',
|
index, item.mid!);
|
||||||
onConfirm: () {
|
},
|
||||||
_fansController.onRemoveFan(
|
);
|
||||||
index, item.mid!);
|
}
|
||||||
},
|
: null,
|
||||||
);
|
leading: Hero(
|
||||||
}
|
tag: heroTag,
|
||||||
: null,
|
child: NetworkImgLayer(
|
||||||
leading: Hero(
|
width: 45,
|
||||||
tag: heroTag,
|
height: 45,
|
||||||
child: NetworkImgLayer(
|
type: ImageType.avatar,
|
||||||
width: 45,
|
src: item.face,
|
||||||
height: 45,
|
|
||||||
type: ImageType.avatar,
|
|
||||||
src: item.face,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
title: Text(
|
),
|
||||||
item.uname!,
|
title: Text(
|
||||||
style: const TextStyle(fontSize: 14),
|
item.uname!,
|
||||||
),
|
style: const TextStyle(fontSize: 14),
|
||||||
subtitle: Text(
|
),
|
||||||
item.sign ?? '',
|
subtitle: Text(
|
||||||
maxLines: 1,
|
item.sign ?? '',
|
||||||
overflow: TextOverflow.ellipsis,
|
maxLines: 1,
|
||||||
),
|
overflow: TextOverflow.ellipsis,
|
||||||
dense: true,
|
),
|
||||||
trailing: const SizedBox(width: 6),
|
dense: true,
|
||||||
);
|
trailing: const SizedBox(width: 6),
|
||||||
},
|
);
|
||||||
childCount: response!.length,
|
},
|
||||||
),
|
childCount: response!.length,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
|
|||||||
@@ -37,7 +37,12 @@ class _FavNoteChildPageState extends State<FavNoteChildPage>
|
|||||||
onRefresh: _favNoteController.onRefresh,
|
onRefresh: _favNoteController.onRefresh,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(() => _buildBody(_favNoteController.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||||
|
sliver: Obx(
|
||||||
|
() => _buildBody(_favNoteController.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -139,26 +144,22 @@ class _FavNoteChildPageState extends State<FavNoteChildPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context),
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
delegate: SliverChildBuilderDelegate(
|
||||||
sliver: SliverGrid(
|
(context, index) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context),
|
if (index == response.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
_favNoteController.onLoadMore();
|
||||||
(context, index) {
|
}
|
||||||
if (index == response.length - 1) {
|
return FavNoteItem(
|
||||||
_favNoteController.onLoadMore();
|
item: response[index],
|
||||||
}
|
ctr: _favNoteController,
|
||||||
return FavNoteItem(
|
onSelect: () {
|
||||||
item: response[index],
|
_favNoteController.onSelect(index);
|
||||||
ctr: _favNoteController,
|
},
|
||||||
onSelect: () {
|
);
|
||||||
_favNoteController.onSelect(index);
|
},
|
||||||
},
|
childCount: response!.length,
|
||||||
);
|
|
||||||
},
|
|
||||||
childCount: response!.length,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(onReload: _favNoteController.onReload),
|
: HttpError(onReload: _favNoteController.onReload),
|
||||||
|
|||||||
@@ -44,7 +44,12 @@ class _FavPgcChildPageState extends State<FavPgcChildPage>
|
|||||||
onRefresh: _favPgcController.onRefresh,
|
onRefresh: _favPgcController.onRefresh,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(() => _buildBody(_favPgcController.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||||
|
sliver: Obx(
|
||||||
|
() => _buildBody(_favPgcController.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -162,48 +167,44 @@ class _FavPgcChildPageState extends State<FavPgcChildPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context),
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
delegate: SliverChildBuilderDelegate(
|
||||||
sliver: SliverGrid(
|
(context, index) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context),
|
if (index == response.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
_favPgcController.onLoadMore();
|
||||||
(context, index) {
|
}
|
||||||
if (index == response.length - 1) {
|
final item = response[index];
|
||||||
_favPgcController.onLoadMore();
|
return FavPgcItem(
|
||||||
}
|
item: item,
|
||||||
final item = response[index];
|
ctr: _favPgcController,
|
||||||
return FavPgcItem(
|
onSelect: () {
|
||||||
item: item,
|
_favPgcController.onSelect(index);
|
||||||
ctr: _favPgcController,
|
},
|
||||||
onSelect: () {
|
onUpdateStatus: () {
|
||||||
_favPgcController.onSelect(index);
|
showPgcFollowDialog(
|
||||||
},
|
context: context,
|
||||||
onUpdateStatus: () {
|
type: widget.type == 0 ? '追番' : '追剧',
|
||||||
showPgcFollowDialog(
|
followStatus: widget.followStatus,
|
||||||
context: context,
|
onUpdateStatus: (followStatus) {
|
||||||
type: widget.type == 0 ? '追番' : '追剧',
|
if (followStatus == -1) {
|
||||||
followStatus: widget.followStatus,
|
_favPgcController.bangumiDel(
|
||||||
onUpdateStatus: (followStatus) {
|
index,
|
||||||
if (followStatus == -1) {
|
item.seasonId,
|
||||||
_favPgcController.bangumiDel(
|
);
|
||||||
index,
|
} else {
|
||||||
item.seasonId,
|
_favPgcController.onUpdate(
|
||||||
);
|
index,
|
||||||
} else {
|
followStatus,
|
||||||
_favPgcController.onUpdate(
|
item.seasonId,
|
||||||
index,
|
);
|
||||||
followStatus,
|
}
|
||||||
item.seasonId,
|
},
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
},
|
);
|
||||||
);
|
},
|
||||||
},
|
childCount: response!.length,
|
||||||
);
|
|
||||||
},
|
|
||||||
childCount: response!.length,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(onReload: _favPgcController.onReload),
|
: HttpError(onReload: _favPgcController.onReload),
|
||||||
|
|||||||
@@ -70,8 +70,13 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
controller: _favDetailController.scrollController,
|
controller: _favDetailController.scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
_buildHeader(theme),
|
_buildHeader(theme),
|
||||||
Obx(() => _buildBody(
|
SliverPadding(
|
||||||
theme, _favDetailController.loadingState.value)),
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 85,
|
||||||
|
),
|
||||||
|
sliver: Obx(() => _buildBody(
|
||||||
|
theme, _favDetailController.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -365,123 +370,116 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context),
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 85,
|
delegate: SliverChildBuilderDelegate(
|
||||||
),
|
(context, index) {
|
||||||
sliver: SliverGrid(
|
if (index == response.length) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context),
|
_favDetailController.onLoadMore();
|
||||||
delegate: SliverChildBuilderDelegate(
|
return Container(
|
||||||
(context, index) {
|
height: 60,
|
||||||
if (index == response.length) {
|
alignment: Alignment.center,
|
||||||
_favDetailController.onLoadMore();
|
child: Text(
|
||||||
return Container(
|
_favDetailController.isEnd ? '没有更多了' : '加载中...',
|
||||||
height: 60,
|
style: TextStyle(
|
||||||
alignment: Alignment.center,
|
color: theme.colorScheme.outline,
|
||||||
child: Text(
|
fontSize: 13,
|
||||||
_favDetailController.isEnd ? '没有更多了' : '加载中...',
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.outline,
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
FavDetailItemData item = response[index];
|
}
|
||||||
return Stack(
|
FavDetailItemData item = response[index];
|
||||||
clipBehavior: Clip.none,
|
return Stack(
|
||||||
children: [
|
clipBehavior: Clip.none,
|
||||||
Positioned.fill(
|
children: [
|
||||||
child: FavVideoCardH(
|
Positioned.fill(
|
||||||
videoItem: item,
|
child: FavVideoCardH(
|
||||||
onDelFav: _favDetailController.isOwner.value
|
videoItem: item,
|
||||||
? () => _favDetailController.onCancelFav(
|
onDelFav: _favDetailController.isOwner.value
|
||||||
index,
|
? () => _favDetailController.onCancelFav(
|
||||||
item.id!,
|
index,
|
||||||
item.type!,
|
item.id!,
|
||||||
)
|
item.type!,
|
||||||
: null,
|
)
|
||||||
onViewFav: () {
|
: null,
|
||||||
PageUtils.toVideoPage(
|
onViewFav: () {
|
||||||
'bvid=${item.bvid}&cid=${item.cid}',
|
PageUtils.toVideoPage(
|
||||||
arguments: {
|
'bvid=${item.bvid}&cid=${item.cid}',
|
||||||
'videoItem': item,
|
arguments: {
|
||||||
'heroTag': Utils.makeHeroTag(item.bvid),
|
'videoItem': item,
|
||||||
'sourceType': 'fav',
|
'heroTag': Utils.makeHeroTag(item.bvid),
|
||||||
'mediaId': _favDetailController.item.value.id,
|
'sourceType': 'fav',
|
||||||
'oid': item.id,
|
'mediaId': _favDetailController.item.value.id,
|
||||||
'favTitle':
|
'oid': item.id,
|
||||||
_favDetailController.item.value.title,
|
'favTitle':
|
||||||
'count': _favDetailController
|
_favDetailController.item.value.title,
|
||||||
.item.value.mediaCount,
|
'count':
|
||||||
'desc': true,
|
_favDetailController.item.value.mediaCount,
|
||||||
'isContinuePlaying': index != 0,
|
'desc': true,
|
||||||
'isOwner': _favDetailController.isOwner.value,
|
'isContinuePlaying': index != 0,
|
||||||
},
|
'isOwner': _favDetailController.isOwner.value,
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
onTap: _favDetailController.enableMultiSelect.value
|
},
|
||||||
? () {
|
onTap: _favDetailController.enableMultiSelect.value
|
||||||
|
? () {
|
||||||
|
_favDetailController.onSelect(index);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
onLongPress: _favDetailController.isOwner.value
|
||||||
|
? () {
|
||||||
|
if (_favDetailController
|
||||||
|
.enableMultiSelect.value.not) {
|
||||||
|
_favDetailController
|
||||||
|
.enableMultiSelect.value = true;
|
||||||
_favDetailController.onSelect(index);
|
_favDetailController.onSelect(index);
|
||||||
}
|
}
|
||||||
: null,
|
}
|
||||||
onLongPress: _favDetailController.isOwner.value
|
: null,
|
||||||
? () {
|
|
||||||
if (_favDetailController
|
|
||||||
.enableMultiSelect.value.not) {
|
|
||||||
_favDetailController
|
|
||||||
.enableMultiSelect.value = true;
|
|
||||||
_favDetailController.onSelect(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Positioned(
|
),
|
||||||
top: 5,
|
Positioned(
|
||||||
left: 12,
|
top: 5,
|
||||||
bottom: 5,
|
left: 12,
|
||||||
child: IgnorePointer(
|
bottom: 5,
|
||||||
child: LayoutBuilder(
|
child: IgnorePointer(
|
||||||
builder: (context, constraints) =>
|
child: LayoutBuilder(
|
||||||
AnimatedOpacity(
|
builder: (context, constraints) => AnimatedOpacity(
|
||||||
opacity: item.checked == true ? 1 : 0,
|
opacity: item.checked == true ? 1 : 0,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
height: constraints.maxHeight,
|
height: constraints.maxHeight,
|
||||||
width: constraints.maxHeight *
|
width: constraints.maxHeight *
|
||||||
StyleString.aspectRatio,
|
StyleString.aspectRatio,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: StyleString.mdRadius,
|
borderRadius: StyleString.mdRadius,
|
||||||
color: Colors.black.withValues(alpha: 0.6),
|
color: Colors.black.withValues(alpha: 0.6),
|
||||||
),
|
),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 34,
|
width: 34,
|
||||||
height: 34,
|
height: 34,
|
||||||
child: AnimatedScale(
|
child: AnimatedScale(
|
||||||
scale: item.checked == true ? 1 : 0,
|
scale: item.checked == true ? 1 : 0,
|
||||||
duration:
|
duration: const Duration(milliseconds: 250),
|
||||||
const Duration(milliseconds: 250),
|
curve: Curves.easeInOut,
|
||||||
curve: Curves.easeInOut,
|
child: IconButton(
|
||||||
child: IconButton(
|
style: ButtonStyle(
|
||||||
style: ButtonStyle(
|
padding: WidgetStateProperty.all(
|
||||||
padding: WidgetStateProperty.all(
|
EdgeInsets.zero),
|
||||||
EdgeInsets.zero),
|
backgroundColor:
|
||||||
backgroundColor:
|
WidgetStateProperty.resolveWith(
|
||||||
WidgetStateProperty.resolveWith(
|
(states) {
|
||||||
(states) {
|
return theme.colorScheme.surface
|
||||||
return theme.colorScheme.surface
|
.withValues(alpha: 0.8);
|
||||||
.withValues(alpha: 0.8);
|
},
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: null,
|
|
||||||
icon: Icon(
|
|
||||||
Icons.done_all_outlined,
|
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onPressed: null,
|
||||||
|
icon: Icon(
|
||||||
|
Icons.done_all_outlined,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -489,11 +487,11 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
);
|
],
|
||||||
},
|
);
|
||||||
childCount: response!.length + 1,
|
},
|
||||||
),
|
childCount: response!.length + 1,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
|
|||||||
@@ -25,49 +25,44 @@ class _FavSearchPageState extends CommonSearchPageState<FavSearchPage,
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(List<FavDetailItemData> list) {
|
Widget buildList(List<FavDetailItemData> list) {
|
||||||
return SliverPadding(
|
return SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
delegate: SliverChildBuilderDelegate(
|
||||||
),
|
childCount: list.length,
|
||||||
sliver: SliverGrid(
|
(context, index) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
if (index == list.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
controller.onLoadMore();
|
||||||
childCount: list.length,
|
}
|
||||||
(context, index) {
|
final item = list[index];
|
||||||
if (index == list.length - 1) {
|
return FavVideoCardH(
|
||||||
controller.onLoadMore();
|
videoItem: item,
|
||||||
}
|
onDelFav: controller.isOwner == true
|
||||||
final item = list[index];
|
? () {
|
||||||
return FavVideoCardH(
|
controller.onCancelFav(
|
||||||
videoItem: item,
|
index,
|
||||||
onDelFav: controller.isOwner == true
|
item.id!,
|
||||||
? () {
|
item.type,
|
||||||
controller.onCancelFav(
|
);
|
||||||
index,
|
}
|
||||||
item.id!,
|
: null,
|
||||||
item.type,
|
onViewFav: () {
|
||||||
);
|
PageUtils.toVideoPage(
|
||||||
}
|
'bvid=${item.bvid}&cid=${item.cid}',
|
||||||
: null,
|
arguments: {
|
||||||
onViewFav: () {
|
'videoItem': item,
|
||||||
PageUtils.toVideoPage(
|
'heroTag': Utils.makeHeroTag(item.bvid),
|
||||||
'bvid=${item.bvid}&cid=${item.cid}',
|
'sourceType': 'fav',
|
||||||
arguments: {
|
'mediaId': controller.mediaId,
|
||||||
'videoItem': item,
|
'oid': item.id,
|
||||||
'heroTag': Utils.makeHeroTag(item.bvid),
|
'favTitle': controller.title,
|
||||||
'sourceType': 'fav',
|
'count': controller.count,
|
||||||
'mediaId': controller.mediaId,
|
'desc': true,
|
||||||
'oid': item.id,
|
'isContinuePlaying': true,
|
||||||
'favTitle': controller.title,
|
},
|
||||||
'count': controller.count,
|
);
|
||||||
'desc': true,
|
},
|
||||||
'isContinuePlaying': true,
|
);
|
||||||
},
|
},
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,26 +30,21 @@ class _FollowSearchPageState extends CommonSearchPageState<FollowSearchPage,
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(List<FollowItemModel> list) {
|
Widget buildList(List<FollowItemModel> list) {
|
||||||
return SliverPadding(
|
return SliverList.builder(
|
||||||
padding: EdgeInsets.only(
|
itemCount: list.length,
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
itemBuilder: ((context, index) {
|
||||||
),
|
if (index == list.length - 1) {
|
||||||
sliver: SliverList.builder(
|
controller.onLoadMore();
|
||||||
itemCount: list.length,
|
}
|
||||||
itemBuilder: ((context, index) {
|
return FollowItem(
|
||||||
if (index == list.length - 1) {
|
item: list[index],
|
||||||
controller.onLoadMore();
|
onSelect: widget.mid != null && widget.isFromSelect != false
|
||||||
}
|
? (userModel) {
|
||||||
return FollowItem(
|
Get.back(result: userModel);
|
||||||
item: list[index],
|
}
|
||||||
onSelect: widget.mid != null && widget.isFromSelect != false
|
: null,
|
||||||
? (userModel) {
|
);
|
||||||
Get.back(result: userModel);
|
}),
|
||||||
}
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,29 +24,24 @@ class _HistorySearchPageState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(List<HisListItem> list) {
|
Widget buildList(List<HisListItem> list) {
|
||||||
return SliverPadding(
|
return SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
delegate: SliverChildBuilderDelegate(
|
||||||
),
|
childCount: list.length,
|
||||||
sliver: SliverGrid(
|
(context, index) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
if (index == list.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
controller.onLoadMore();
|
||||||
childCount: list.length,
|
}
|
||||||
(context, index) {
|
final item = list[index];
|
||||||
if (index == list.length - 1) {
|
return HistoryItem(
|
||||||
controller.onLoadMore();
|
videoItem: item,
|
||||||
}
|
ctr: controller,
|
||||||
final item = list[index];
|
onChoose: null,
|
||||||
return HistoryItem(
|
onDelete: (kid, business) {
|
||||||
videoItem: item,
|
controller.onDelHistory(index, kid, business);
|
||||||
ctr: controller,
|
},
|
||||||
onChoose: null,
|
);
|
||||||
onDelete: (kid, business) {
|
},
|
||||||
controller.onDelHistory(index, kid, business);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,64 +26,59 @@ class _LaterSearchPageState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(List<HotVideoItemModel> list) {
|
Widget buildList(List<HotVideoItemModel> list) {
|
||||||
return SliverPadding(
|
return SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
delegate: SliverChildBuilderDelegate(
|
||||||
),
|
childCount: list.length,
|
||||||
sliver: SliverGrid(
|
(context, index) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
if (index == list.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
controller.onLoadMore();
|
||||||
childCount: list.length,
|
}
|
||||||
(context, index) {
|
final item = list[index];
|
||||||
if (index == list.length - 1) {
|
return Stack(
|
||||||
controller.onLoadMore();
|
clipBehavior: Clip.none,
|
||||||
}
|
children: [
|
||||||
final item = list[index];
|
VideoCardH(
|
||||||
return Stack(
|
videoItem: item,
|
||||||
clipBehavior: Clip.none,
|
source: 'later',
|
||||||
children: [
|
onViewLater: (cid) {
|
||||||
VideoCardH(
|
PageUtils.toVideoPage(
|
||||||
videoItem: item,
|
'bvid=${item.bvid}&cid=$cid',
|
||||||
source: 'later',
|
arguments: {
|
||||||
onViewLater: (cid) {
|
'videoItem': item,
|
||||||
PageUtils.toVideoPage(
|
'oid': item.aid,
|
||||||
'bvid=${item.bvid}&cid=$cid',
|
'heroTag': Utils.makeHeroTag(item.bvid),
|
||||||
arguments: {
|
'sourceType': 'watchLater',
|
||||||
'videoItem': item,
|
'count': controller.count,
|
||||||
'oid': item.aid,
|
'favTitle': '稍后再看',
|
||||||
'heroTag': Utils.makeHeroTag(item.bvid),
|
'mediaId': controller.mid,
|
||||||
'sourceType': 'watchLater',
|
'desc': false,
|
||||||
'count': controller.count,
|
'isContinuePlaying': index != 0,
|
||||||
'favTitle': '稍后再看',
|
},
|
||||||
'mediaId': controller.mid,
|
);
|
||||||
'desc': false,
|
},
|
||||||
'isContinuePlaying': index != 0,
|
),
|
||||||
},
|
Positioned(
|
||||||
|
right: 12,
|
||||||
|
bottom: 0,
|
||||||
|
child: iconButton(
|
||||||
|
tooltip: '移除',
|
||||||
|
context: context,
|
||||||
|
onPressed: () {
|
||||||
|
controller.toViewDel(
|
||||||
|
context,
|
||||||
|
index,
|
||||||
|
item.aid,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
icon: Icons.clear,
|
||||||
|
iconColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
bgColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
Positioned(
|
),
|
||||||
right: 12,
|
],
|
||||||
bottom: 0,
|
);
|
||||||
child: iconButton(
|
},
|
||||||
tooltip: '移除',
|
|
||||||
context: context,
|
|
||||||
onPressed: () {
|
|
||||||
controller.toViewDel(
|
|
||||||
context,
|
|
||||||
index,
|
|
||||||
item.aid,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: Icons.clear,
|
|
||||||
iconColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
|
||||||
bgColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,14 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
|||||||
return refreshIndicator(
|
return refreshIndicator(
|
||||||
onRefresh: _controller.onRefresh,
|
onRefresh: _controller.onRefresh,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [Obx(() => _buildBody(theme, _controller.loadingState.value))],
|
slivers: [
|
||||||
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||||
|
sliver:
|
||||||
|
Obx(() => _buildBody(theme, _controller.loadingState.value)),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -68,11 +75,6 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
|||||||
child: Obx(
|
child: Obx(
|
||||||
() => _buildItem(theme, _controller.second.value, false)),
|
() => _buildItem(theme, _controller.second.value, false)),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: SizedBox(
|
|
||||||
height: 80 + MediaQuery.of(context).padding.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ class _MemberVideoState extends State<MemberVideo>
|
|||||||
}
|
}
|
||||||
final SpaceArchiveItem item = response[index];
|
final SpaceArchiveItem item = response[index];
|
||||||
return VideoCardHMemberVideo(
|
return VideoCardHMemberVideo(
|
||||||
key: ValueKey('${item.param}'),
|
// key: ValueKey('${item.param}'),
|
||||||
videoItem: item,
|
videoItem: item,
|
||||||
fromViewAid: _controller.fromViewAid,
|
fromViewAid: _controller.fromViewAid,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -121,8 +121,12 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
|||||||
filterQuality: FilterQuality.low,
|
filterQuality: FilterQuality.low,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(() =>
|
SliverPadding(
|
||||||
_buildBody(theme, _controller.loadingState.value)),
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 100),
|
||||||
|
sliver: Obx(() =>
|
||||||
|
_buildBody(theme, _controller.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -138,77 +142,73 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
|||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => const SliverToBoxAdapter(child: LinearProgressIndicator()),
|
Loading() => const SliverToBoxAdapter(child: LinearProgressIndicator()),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? SliverList.separated(
|
||||||
padding: EdgeInsets.only(
|
itemCount: response!.length,
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 100),
|
itemBuilder: (context, index) {
|
||||||
sliver: SliverList.separated(
|
final item = response[index];
|
||||||
itemCount: response!.length,
|
return ListTile(
|
||||||
itemBuilder: (context, index) {
|
dense: true,
|
||||||
final item = response[index];
|
onTap: () {
|
||||||
return ListTile(
|
Get.toNamed(
|
||||||
dense: true,
|
'/searchResult',
|
||||||
onTap: () {
|
parameters: {
|
||||||
Get.toNamed(
|
'keyword': item.keyword!,
|
||||||
'/searchResult',
|
},
|
||||||
parameters: {
|
);
|
||||||
'keyword': item.keyword!,
|
},
|
||||||
},
|
leading: index < _controller.topCount
|
||||||
);
|
? const Icon(
|
||||||
},
|
size: 17,
|
||||||
leading: index < _controller.topCount
|
Icons.vertical_align_top_outlined,
|
||||||
? const Icon(
|
color: Color(0xFFd1403e),
|
||||||
size: 17,
|
)
|
||||||
Icons.vertical_align_top_outlined,
|
: Text(
|
||||||
color: Color(0xFFd1403e),
|
'${index + 1 - _controller.topCount}',
|
||||||
)
|
style: TextStyle(
|
||||||
: Text(
|
fontWeight: FontWeight.bold,
|
||||||
'${index + 1 - _controller.topCount}',
|
color: switch (index - _controller.topCount) {
|
||||||
style: TextStyle(
|
0 => const Color(0xFFfdad13),
|
||||||
fontWeight: FontWeight.bold,
|
1 => const Color(0xFF8aace1),
|
||||||
color: switch (index - _controller.topCount) {
|
2 => const Color(0xFFdfa777),
|
||||||
0 => const Color(0xFFfdad13),
|
_ => theme.colorScheme.outline,
|
||||||
1 => const Color(0xFF8aace1),
|
},
|
||||||
2 => const Color(0xFFdfa777),
|
fontSize: 17,
|
||||||
_ => theme.colorScheme.outline,
|
fontStyle: FontStyle.italic,
|
||||||
},
|
|
||||||
fontSize: 17,
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Row(
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
item.keyword!,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
strutStyle: const StrutStyle(height: 1, leading: 0),
|
|
||||||
style: const TextStyle(height: 1, fontSize: 15),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (item.icon?.isNotEmpty == true) ...[
|
title: Row(
|
||||||
const SizedBox(width: 4),
|
children: [
|
||||||
CachedNetworkImage(
|
Flexible(
|
||||||
imageUrl: Utils.thumbnailImgUrl(item.icon!),
|
child: Text(
|
||||||
height: 16,
|
item.keyword!,
|
||||||
),
|
maxLines: 1,
|
||||||
] else if (item.showLiveIcon == true) ...[
|
overflow: TextOverflow.ellipsis,
|
||||||
const SizedBox(width: 4),
|
strutStyle: const StrutStyle(height: 1, leading: 0),
|
||||||
Image.asset(
|
style: const TextStyle(height: 1, fontSize: 15),
|
||||||
'assets/images/live/live.gif',
|
),
|
||||||
width: 51,
|
),
|
||||||
height: 16,
|
if (item.icon?.isNotEmpty == true) ...[
|
||||||
),
|
const SizedBox(width: 4),
|
||||||
],
|
CachedNetworkImage(
|
||||||
|
imageUrl: Utils.thumbnailImgUrl(item.icon!),
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
] else if (item.showLiveIcon == true) ...[
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/live/live.gif',
|
||||||
|
width: 51,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
separatorBuilder: (context, index) => Divider(
|
},
|
||||||
height: 1,
|
separatorBuilder: (context, index) => Divider(
|
||||||
indent: 48,
|
height: 1,
|
||||||
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
indent: 48,
|
||||||
),
|
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
|
|||||||
@@ -82,20 +82,20 @@ class _SettingsSearchPageState extends State<SettingsSearchPage> {
|
|||||||
bottom: false,
|
bottom: false,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
Obx(
|
SliverPadding(
|
||||||
() => _list.isEmpty
|
padding: EdgeInsets.only(
|
||||||
? const HttpError()
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
: SliverPadding(
|
),
|
||||||
padding: EdgeInsets.only(
|
sliver: Obx(
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
() => _list.isEmpty
|
||||||
),
|
? const HttpError()
|
||||||
sliver: SliverWaterfallFlow.extent(
|
: SliverWaterfallFlow.extent(
|
||||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||||
children: [
|
children: [
|
||||||
..._list.map((item) => item.widget),
|
..._list.map((item) => item.widget),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -40,7 +40,13 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
|||||||
slivers: [
|
slivers: [
|
||||||
_buildAppBar(theme),
|
_buildAppBar(theme),
|
||||||
_buildCount(theme),
|
_buildCount(theme),
|
||||||
Obx(() => _buildBody(_subDetailController.loadingState.value)),
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
|
),
|
||||||
|
sliver: Obx(
|
||||||
|
() => _buildBody(_subDetailController.loadingState.value)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -58,23 +64,18 @@ class _SubDetailPageState extends State<SubDetailPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? SliverPadding(
|
? SliverGrid(
|
||||||
padding: EdgeInsets.only(
|
gridDelegate: Grid.videoCardHDelegate(context),
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
delegate: SliverChildBuilderDelegate(
|
||||||
),
|
childCount: response!.length,
|
||||||
sliver: SliverGrid(
|
(context, index) {
|
||||||
gridDelegate: Grid.videoCardHDelegate(context),
|
if (index == response.length - 1) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
_subDetailController.onLoadMore();
|
||||||
childCount: response!.length,
|
}
|
||||||
(context, index) {
|
return SubVideoCardH(
|
||||||
if (index == response.length - 1) {
|
videoItem: response[index],
|
||||||
_subDetailController.onLoadMore();
|
);
|
||||||
}
|
},
|
||||||
return SubVideoCardH(
|
|
||||||
videoItem: response[index],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: HttpError(
|
: HttpError(
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class _MediaListPanelState
|
|||||||
widget.loadMoreMedia();
|
widget.loadMoreMedia();
|
||||||
}
|
}
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
key: ValueKey('${item.aid}'),
|
// key: ValueKey('${item.aid}'),
|
||||||
height: 98,
|
height: 98,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ import 'package:PiliPlus/models/common/member/contribute_type.dart';
|
|||||||
import 'package:PiliPlus/models/member/info.dart';
|
import 'package:PiliPlus/models/member/info.dart';
|
||||||
import 'package:PiliPlus/models/space_archive/data.dart';
|
import 'package:PiliPlus/models/space_archive/data.dart';
|
||||||
import 'package:PiliPlus/models/space_archive/item.dart';
|
import 'package:PiliPlus/models/space_archive/item.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||||
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class HorizontalMemberPageController extends CommonDataController {
|
class HorizontalMemberPageController
|
||||||
HorizontalMemberPageController({this.mid, required this.lastAid});
|
extends CommonListController<SpaceArchiveData, SpaceArchiveItem> {
|
||||||
|
HorizontalMemberPageController({this.mid, required this.currAid});
|
||||||
|
|
||||||
dynamic mid;
|
dynamic mid;
|
||||||
|
|
||||||
int currentPage = 0;
|
|
||||||
|
|
||||||
Rx<LoadingState<MemberInfoModel>> userState =
|
Rx<LoadingState<MemberInfoModel>> userState =
|
||||||
LoadingState<MemberInfoModel>.loading().obs;
|
LoadingState<MemberInfoModel>.loading().obs;
|
||||||
RxMap userStat = {}.obs;
|
RxMap userStat = {}.obs;
|
||||||
@@ -54,27 +54,29 @@ class HorizontalMemberPageController extends CommonDataController {
|
|||||||
bool customHandleResponse(bool isRefresh, Success response) {
|
bool customHandleResponse(bool isRefresh, Success response) {
|
||||||
SpaceArchiveData data = response.response;
|
SpaceArchiveData data = response.response;
|
||||||
count.value = data.count ?? -1;
|
count.value = data.count ?? -1;
|
||||||
if (currentPage == 0 || isLoadPrevious) {
|
if (isRefresh) {
|
||||||
hasPrev = data.hasPrev ?? false;
|
|
||||||
}
|
|
||||||
if (currentPage == 0 || !isLoadPrevious) {
|
|
||||||
hasNext = data.hasNext ?? false;
|
|
||||||
}
|
|
||||||
if (currentPage != 0 && loadingState.value is Success) {
|
|
||||||
data.item ??= <SpaceArchiveItem>[];
|
|
||||||
if (isLoadPrevious) {
|
if (isLoadPrevious) {
|
||||||
data.item!.addAll((loadingState.value as Success).response);
|
hasPrev = data.hasPrev ?? false;
|
||||||
} else {
|
} else {
|
||||||
data.item!.insertAll(0, (loadingState.value as Success).response);
|
hasNext = data.hasNext ?? false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isLoadPrevious && loadingState.value is Success) {
|
||||||
|
data.item ??= <SpaceArchiveItem>[];
|
||||||
|
data.item!.addAll((loadingState.value as Success).response);
|
||||||
|
} else if (!isRefresh && loadingState.value is Success) {
|
||||||
|
data.item ??= <SpaceArchiveItem>[];
|
||||||
|
data.item!.insertAll(0, (loadingState.value as Success).response);
|
||||||
|
}
|
||||||
firstAid = data.item?.firstOrNull?.param;
|
firstAid = data.item?.firstOrNull?.param;
|
||||||
lastAid = data.item?.lastOrNull?.param;
|
lastAid = data.item?.lastOrNull?.param;
|
||||||
loadingState.value = Success(data.item);
|
loadingState.value = Success(data.item);
|
||||||
isLoadPrevious = false;
|
isLoadPrevious = false;
|
||||||
|
page++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? currAid;
|
||||||
String? firstAid;
|
String? firstAid;
|
||||||
String? lastAid;
|
String? lastAid;
|
||||||
RxString order = 'pubdate'.obs;
|
RxString order = 'pubdate'.obs;
|
||||||
@@ -84,27 +86,45 @@ class HorizontalMemberPageController extends CommonDataController {
|
|||||||
bool hasNext = true;
|
bool hasNext = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LoadingState> customGetData() => MemberHttp.spaceArchive(
|
Future<LoadingState<SpaceArchiveData>> customGetData() =>
|
||||||
|
MemberHttp.spaceArchive(
|
||||||
type: ContributeType.video,
|
type: ContributeType.video,
|
||||||
mid: mid,
|
mid: mid,
|
||||||
aid: isLoadPrevious ? firstAid : lastAid,
|
aid: page == 1
|
||||||
|
? currAid
|
||||||
|
: isLoadPrevious
|
||||||
|
? firstAid
|
||||||
|
: lastAid,
|
||||||
order: order.value,
|
order: order.value,
|
||||||
sort: isLoadPrevious ? 'asc' : null,
|
sort: page != 1 && isLoadPrevious ? 'asc' : null,
|
||||||
pn: null,
|
pn: null,
|
||||||
next: null,
|
next: null,
|
||||||
seasonId: null,
|
seasonId: null,
|
||||||
seriesId: null,
|
seriesId: null,
|
||||||
includeCursor: currentPage == 0 ? true : null,
|
includeCursor: page == 1 ? true : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onRefresh() {
|
Future<void> onRefresh() {
|
||||||
currentPage = 0;
|
if (!hasPrev) {
|
||||||
hasPrev = true;
|
return Future.value();
|
||||||
hasNext = true;
|
}
|
||||||
|
isLoadPrevious = true;
|
||||||
return queryData();
|
return queryData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onReload() {
|
||||||
|
firstAid = null;
|
||||||
|
lastAid = null;
|
||||||
|
hasNext = true;
|
||||||
|
hasPrev = true;
|
||||||
|
isEnd = false;
|
||||||
|
page = 1;
|
||||||
|
scrollController.jumpToTop();
|
||||||
|
return super.onReload();
|
||||||
|
}
|
||||||
|
|
||||||
void queryBySort() {
|
void queryBySort() {
|
||||||
order.value = order.value == 'pubdate' ? 'click' : 'pubdate';
|
order.value = order.value == 'pubdate' ? 'click' : 'pubdate';
|
||||||
onReload();
|
onReload();
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import 'package:PiliPlus/common/skeleton/video_card_h.dart';
|
||||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||||
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
|
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
|
||||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||||
|
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||||
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
|
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
|
||||||
import 'package:PiliPlus/common/widgets/scroll_physics.dart';
|
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||||
import 'package:PiliPlus/common/widgets/video_card/video_card_h_member_video.dart';
|
import 'package:PiliPlus/common/widgets/video_card/video_card_h_member_video.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/models/common/image_preview_type.dart';
|
import 'package:PiliPlus/models/common/image_preview_type.dart';
|
||||||
@@ -49,31 +51,12 @@ class _HorizontalMemberPageState extends State<HorizontalMemberPage> {
|
|||||||
_controller = Get.put(
|
_controller = Get.put(
|
||||||
HorizontalMemberPageController(
|
HorizontalMemberPageController(
|
||||||
mid: widget.mid,
|
mid: widget.mid,
|
||||||
lastAid: widget.videoDetailController.oid.value.toString(),
|
currAid: widget.videoDetailController.oid.value.toString(),
|
||||||
),
|
),
|
||||||
tag: widget.videoDetailController.heroTag,
|
tag: widget.videoDetailController.heroTag,
|
||||||
);
|
);
|
||||||
_bvid = widget.videoDetailController.bvid;
|
_bvid = widget.videoDetailController.bvid;
|
||||||
_ownerMid = Accounts.main.mid;
|
_ownerMid = Accounts.main.mid;
|
||||||
if (_controller.hasPrev) {
|
|
||||||
_controller.scrollController.addListener(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void listener() {
|
|
||||||
if (_controller.scrollController.position.pixels == 0) {
|
|
||||||
if (_controller.hasPrev) {
|
|
||||||
_controller
|
|
||||||
..isLoadPrevious = true
|
|
||||||
..onLoadMore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_controller.scrollController.removeListener(listener);
|
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -104,10 +87,22 @@ class _HorizontalMemberPageState extends State<HorizontalMemberPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
_buildUserInfo(theme, response),
|
_buildUserInfo(theme, response),
|
||||||
const SizedBox(height: 5),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Obx(
|
child: refreshIndicator(
|
||||||
() => _buildVideoList(theme, _controller.loadingState.value)),
|
onRefresh: _controller.onRefresh,
|
||||||
|
child: CustomScrollView(
|
||||||
|
controller: _controller.scrollController,
|
||||||
|
// physics: PositionRetainedScrollPhysics(
|
||||||
|
// shouldRetain: _controller.hasPrev,
|
||||||
|
// parent: const ClampingScrollPhysics(),
|
||||||
|
// ),
|
||||||
|
slivers: [
|
||||||
|
_buildSliverHeader(theme),
|
||||||
|
Obx(() =>
|
||||||
|
_buildVideoList(theme, _controller.loadingState.value)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -176,33 +171,34 @@ class _HorizontalMemberPageState extends State<HorizontalMemberPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildVideoList(ThemeData theme, LoadingState loadingState) {
|
Widget _buildVideoList(
|
||||||
|
ThemeData theme, LoadingState<List<SpaceArchiveItem>?> loadingState) {
|
||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => loadingWidget,
|
Loading() => SliverGrid(
|
||||||
Success(:var response) => Material(
|
gridDelegate: Grid.videoCardHDelegate(context),
|
||||||
color: Colors.transparent,
|
delegate: SliverChildBuilderDelegate(
|
||||||
child: CustomScrollView(
|
childCount: 10,
|
||||||
controller: _controller.scrollController,
|
(context, index) {
|
||||||
physics: PositionRetainedScrollPhysics(
|
return const VideoCardHSkeleton();
|
||||||
shouldRetain: _controller.hasPrev,
|
},
|
||||||
parent: const ClampingScrollPhysics(),
|
),
|
||||||
),
|
),
|
||||||
slivers: [
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
_buildSliverHeader(theme),
|
? SliverPadding(
|
||||||
SliverPadding(
|
padding: EdgeInsets.only(
|
||||||
padding: EdgeInsets.only(
|
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
),
|
||||||
),
|
sliver: SliverGrid(
|
||||||
sliver: SliverGrid(
|
gridDelegate: Grid.videoCardHDelegate(context),
|
||||||
gridDelegate: Grid.videoCardHDelegate(context),
|
delegate: SliverChildBuilderDelegate(
|
||||||
delegate: SliverChildBuilderDelegate(
|
(context, index) {
|
||||||
(context, index) {
|
if (index == response.length - 1 && _controller.hasNext) {
|
||||||
if (index == response.length - 1 && _controller.hasNext) {
|
_controller.onLoadMore();
|
||||||
_controller.onLoadMore();
|
}
|
||||||
}
|
final SpaceArchiveItem videoItem = response[index];
|
||||||
final SpaceArchiveItem videoItem = response[index];
|
return Material(
|
||||||
return VideoCardHMemberVideo(
|
color: Colors.transparent,
|
||||||
key: ValueKey('${videoItem.param}'),
|
child: VideoCardHMemberVideo(
|
||||||
videoItem: videoItem,
|
videoItem: videoItem,
|
||||||
bvid: _bvid,
|
bvid: _bvid,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -219,17 +215,15 @@ class _HorizontalMemberPageState extends State<HorizontalMemberPage> {
|
|||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
childCount: response.length,
|
},
|
||||||
),
|
childCount: response!.length,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
)
|
||||||
),
|
: HttpError(onReload: _controller.onReload),
|
||||||
),
|
Error(:var errMsg) => HttpError(
|
||||||
Error(:var errMsg) => scrollErrorWidget(
|
|
||||||
controller: _controller.scrollController,
|
|
||||||
errMsg: errMsg,
|
errMsg: errMsg,
|
||||||
onReload: _controller.onReload,
|
onReload: _controller.onReload,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import 'package:PiliPlus/pages/video/note/controller.dart';
|
|||||||
import 'package:PiliPlus/pages/webview/view.dart';
|
import 'package:PiliPlus/pages/webview/view.dart';
|
||||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart' show Accounts;
|
||||||
import 'package:flutter/material.dart';
|
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';
|
||||||
@@ -84,52 +84,73 @@ class _NoteListPageState extends CommonSlidePageState<NoteListPage> {
|
|||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: enableSlide
|
body: enableSlide ? slideList(theme) : buildList(theme),
|
||||||
? slideList(theme,
|
),
|
||||||
Obx(() => _buildBody(theme, _controller.loadingState.value)))
|
);
|
||||||
: Obx(() => _buildBody(theme, _controller.loadingState.value)),
|
}
|
||||||
bottomNavigationBar: Container(
|
|
||||||
padding: EdgeInsets.only(
|
@override
|
||||||
left: 12,
|
Widget buildList(ThemeData theme) {
|
||||||
right: 12,
|
return refreshIndicator(
|
||||||
top: 6,
|
onRefresh: _controller.onRefresh,
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 6,
|
child: Column(
|
||||||
),
|
children: [
|
||||||
width: double.infinity,
|
Expanded(
|
||||||
decoration: BoxDecoration(
|
child: CustomScrollView(
|
||||||
color: theme.colorScheme.onInverseSurface,
|
controller: _controller.scrollController,
|
||||||
border: Border(
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
top: BorderSide(
|
slivers: [
|
||||||
width: 0.5,
|
SliverPadding(
|
||||||
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
padding: const EdgeInsets.only(bottom: 80),
|
||||||
),
|
sliver: Obx(
|
||||||
),
|
() => _buildBody(theme, _controller.loadingState.value)),
|
||||||
),
|
|
||||||
child: FilledButton.tonal(
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if (!Accounts.main.isLogin) {
|
|
||||||
SmartDialog.showToast('账号未登录');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_key.currentState?.showBottomSheet(
|
|
||||||
(context) => WebviewPage(
|
|
||||||
oid: widget.oid,
|
|
||||||
title: widget.title,
|
|
||||||
url:
|
|
||||||
'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}',
|
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
child: const Text('开始记笔记'),
|
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
top: 6,
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom + 6,
|
||||||
|
),
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: theme.colorScheme.onInverseSurface,
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
width: 0.5,
|
||||||
|
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: FilledButton.tonal(
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if (!Accounts.main.isLogin) {
|
||||||
|
SmartDialog.showToast('账号未登录');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_key.currentState?.showBottomSheet(
|
||||||
|
(context) => WebviewPage(
|
||||||
|
oid: widget.oid,
|
||||||
|
title: widget.title,
|
||||||
|
url:
|
||||||
|
'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('开始记笔记'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -137,59 +158,37 @@ class _NoteListPageState extends CommonSlidePageState<NoteListPage> {
|
|||||||
Widget _buildBody(
|
Widget _buildBody(
|
||||||
ThemeData theme, LoadingState<List<dynamic>?> loadingState) {
|
ThemeData theme, LoadingState<List<dynamic>?> loadingState) {
|
||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => CustomScrollView(
|
Loading() => SliverToBoxAdapter(
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
child: ListView.builder(
|
||||||
slivers: [
|
shrinkWrap: true,
|
||||||
SliverList.builder(
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return const VideoReplySkeleton();
|
return const VideoReplySkeleton();
|
||||||
},
|
},
|
||||||
itemCount: 8,
|
itemCount: 8,
|
||||||
)
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? refreshIndicator(
|
? SliverList.separated(
|
||||||
onRefresh: _controller.onRefresh,
|
itemBuilder: (context, index) {
|
||||||
child: CustomScrollView(
|
if (index == response.length - 1) {
|
||||||
controller: _controller.scrollController,
|
_controller.onLoadMore();
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
}
|
||||||
slivers: [
|
return _itemWidget(context, theme, response[index]);
|
||||||
SliverList.separated(
|
},
|
||||||
itemBuilder: (context, index) {
|
itemCount: response!.length,
|
||||||
if (index == response.length - 1) {
|
separatorBuilder: (context, index) => Divider(
|
||||||
_controller.onLoadMore();
|
height: 1,
|
||||||
}
|
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
||||||
return _itemWidget(context, theme, response[index]);
|
|
||||||
},
|
|
||||||
itemCount: response!.length,
|
|
||||||
separatorBuilder: (context, index) => Divider(
|
|
||||||
height: 1,
|
|
||||||
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: SizedBox(
|
|
||||||
height: MediaQuery.paddingOf(context).bottom + 80,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: errWidget(),
|
: HttpError(onReload: _controller.onReload),
|
||||||
Error(:var errMsg) => errWidget(errMsg),
|
Error(:var errMsg) => HttpError(
|
||||||
|
errMsg: errMsg,
|
||||||
|
onReload: _controller.onReload,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget errWidget([errMsg]) => CustomScrollView(
|
|
||||||
controller: _controller.scrollController,
|
|
||||||
slivers: [
|
|
||||||
HttpError(
|
|
||||||
errMsg: errMsg,
|
|
||||||
onReload: _controller.onReload,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _itemWidget(BuildContext context, ThemeData theme, dynamic item) {
|
Widget _itemWidget(BuildContext context, ThemeData theme, dynamic item) {
|
||||||
|
|||||||
@@ -387,17 +387,13 @@ class _VideoReplyReplyPanelState
|
|||||||
ThemeData theme, LoadingState<List<ReplyInfo>?> loadingState, int index) {
|
ThemeData theme, LoadingState<List<ReplyInfo>?> loadingState, int index) {
|
||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => IgnorePointer(
|
Loading() => IgnorePointer(
|
||||||
child: CustomScrollView(
|
child: ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
slivers: [
|
itemBuilder: (context, index) {
|
||||||
SliverList.builder(
|
return const VideoReplySkeleton();
|
||||||
itemBuilder: (context, index) {
|
},
|
||||||
return const VideoReplySkeleton();
|
itemCount: 8,
|
||||||
},
|
|
||||||
itemCount: 8,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success(:var response) => () {
|
Success(:var response) => () {
|
||||||
|
|||||||
@@ -123,8 +123,11 @@ class _WhisperDetailPageState
|
|||||||
hidePanel();
|
hidePanel();
|
||||||
},
|
},
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
child: Obx(() =>
|
child: refreshIndicator(
|
||||||
_buildBody(_whisperDetailController.loadingState.value)),
|
onRefresh: _whisperDetailController.onRefresh,
|
||||||
|
child: Obx(() =>
|
||||||
|
_buildBody(_whisperDetailController.loadingState.value)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_whisperDetailController.mid != null) ...[
|
if (_whisperDetailController.mid != null) ...[
|
||||||
@@ -142,66 +145,63 @@ class _WhisperDetailPageState
|
|||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => loadingWidget,
|
Loading() => loadingWidget,
|
||||||
Success(:var response) => response?.isNotEmpty == true
|
Success(:var response) => response?.isNotEmpty == true
|
||||||
? refreshIndicator(
|
? ListView.separated(
|
||||||
onRefresh: _whisperDetailController.onRefresh,
|
shrinkWrap: true,
|
||||||
child: ListView.separated(
|
reverse: true,
|
||||||
shrinkWrap: true,
|
itemCount: response!.length,
|
||||||
reverse: true,
|
padding: const EdgeInsets.all(12),
|
||||||
itemCount: response!.length,
|
physics: const AlwaysScrollableScrollPhysics(
|
||||||
padding: const EdgeInsets.all(12),
|
parent: ClampingScrollPhysics(),
|
||||||
physics: const AlwaysScrollableScrollPhysics(
|
|
||||||
parent: ClampingScrollPhysics(),
|
|
||||||
),
|
|
||||||
controller: _whisperDetailController.scrollController,
|
|
||||||
itemBuilder: (context, int index) {
|
|
||||||
if (index == response.length - 1) {
|
|
||||||
_whisperDetailController.onLoadMore();
|
|
||||||
}
|
|
||||||
final item = response[index];
|
|
||||||
return ChatItem(
|
|
||||||
item: item,
|
|
||||||
eInfos: _whisperDetailController.eInfos,
|
|
||||||
onLongPress: item.senderUid ==
|
|
||||||
_whisperDetailController.ownerMid
|
|
||||||
? () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
clipBehavior: Clip.hardEdge,
|
|
||||||
contentPadding:
|
|
||||||
const EdgeInsets.symmetric(vertical: 12),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
ListTile(
|
|
||||||
onTap: () {
|
|
||||||
Get.back();
|
|
||||||
_whisperDetailController.sendMsg(
|
|
||||||
message: '${item.msgKey}',
|
|
||||||
onClearText: editController.clear,
|
|
||||||
msgType: 5,
|
|
||||||
index: index,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
dense: true,
|
|
||||||
title: const Text(
|
|
||||||
'撤回',
|
|
||||||
style: TextStyle(fontSize: 14),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
separatorBuilder: (BuildContext context, int index) =>
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
),
|
),
|
||||||
|
controller: _whisperDetailController.scrollController,
|
||||||
|
itemBuilder: (context, int index) {
|
||||||
|
if (index == response.length - 1) {
|
||||||
|
_whisperDetailController.onLoadMore();
|
||||||
|
}
|
||||||
|
final item = response[index];
|
||||||
|
return ChatItem(
|
||||||
|
item: item,
|
||||||
|
eInfos: _whisperDetailController.eInfos,
|
||||||
|
onLongPress: item.senderUid ==
|
||||||
|
_whisperDetailController.ownerMid
|
||||||
|
? () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
clipBehavior: Clip.hardEdge,
|
||||||
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 12),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
onTap: () {
|
||||||
|
Get.back();
|
||||||
|
_whisperDetailController.sendMsg(
|
||||||
|
message: '${item.msgKey}',
|
||||||
|
onClearText: editController.clear,
|
||||||
|
msgType: 5,
|
||||||
|
index: index,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
dense: true,
|
||||||
|
title: const Text(
|
||||||
|
'撤回',
|
||||||
|
style: TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (BuildContext context, int index) =>
|
||||||
|
const SizedBox(height: 12),
|
||||||
)
|
)
|
||||||
: scrollErrorWidget(
|
: scrollErrorWidget(
|
||||||
onReload: _whisperDetailController.onReload,
|
onReload: _whisperDetailController.onReload,
|
||||||
|
|||||||
Reference in New Issue
Block a user