mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-06 10:07:48 +08:00
@@ -3,7 +3,7 @@ import 'dart:async';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart' show ScrollController;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
mixin ScrollOrRefreshMixin {
|
||||
|
||||
@@ -32,32 +32,38 @@ class ActionPanel extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton.icon(
|
||||
onPressed: () => showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (_) => RepostPanel(
|
||||
item: item,
|
||||
onSuccess: () {
|
||||
int count = forward.count ?? 0;
|
||||
forward.count = count + 1;
|
||||
if (context.mounted) {
|
||||
(context as Element?)?.markNeedsBuild();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
FontAwesomeIcons.shareFromSquare,
|
||||
size: 16,
|
||||
color: outline,
|
||||
semanticLabel: "转发",
|
||||
),
|
||||
style: btnStyle,
|
||||
label: Text(
|
||||
forward.count != null ? NumUtils.numFormat(forward.count) : '转发',
|
||||
),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return TextButton.icon(
|
||||
onPressed: () => showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (_) => RepostPanel(
|
||||
item: item,
|
||||
onSuccess: () {
|
||||
int count = forward.count ?? 0;
|
||||
forward.count = count + 1;
|
||||
if (context.mounted) {
|
||||
(context as Element?)?.markNeedsBuild();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
FontAwesomeIcons.shareFromSquare,
|
||||
size: 16,
|
||||
color: outline,
|
||||
semanticLabel: "转发",
|
||||
),
|
||||
style: btnStyle,
|
||||
label: Text(
|
||||
forward.count != null
|
||||
? NumUtils.numFormat(forward.count)
|
||||
: '转发',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
@@ -76,32 +82,40 @@ class ActionPanel extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextButton.icon(
|
||||
onPressed: () => RequestUtils.onLikeDynamic(item, () {
|
||||
if (context.mounted) {
|
||||
(context as Element?)?.markNeedsBuild();
|
||||
}
|
||||
}),
|
||||
icon: Icon(
|
||||
like.status!
|
||||
? FontAwesomeIcons.solidThumbsUp
|
||||
: FontAwesomeIcons.thumbsUp,
|
||||
size: 16,
|
||||
color: like.status! ? primary : outline,
|
||||
semanticLabel: like.status! ? "已赞" : "点赞",
|
||||
),
|
||||
style: btnStyle,
|
||||
label: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
like.count != null ? NumUtils.numFormat(like.count) : '点赞',
|
||||
key: ValueKey<int?>(like.count),
|
||||
style: TextStyle(color: like.status! ? primary : outline),
|
||||
),
|
||||
),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final likeIcon = Icon(
|
||||
like.status!
|
||||
? FontAwesomeIcons.solidThumbsUp
|
||||
: FontAwesomeIcons.thumbsUp,
|
||||
size: 16,
|
||||
color: like.status! ? primary : outline,
|
||||
semanticLabel: like.status! ? "已赞" : "点赞",
|
||||
);
|
||||
return TextButton.icon(
|
||||
onPressed: () => RequestUtils.onLikeDynamic(
|
||||
item,
|
||||
likeIcon.color == primary,
|
||||
() {
|
||||
if (context.mounted) {
|
||||
(context as Element?)?.markNeedsBuild();
|
||||
}
|
||||
},
|
||||
),
|
||||
icon: likeIcon,
|
||||
style: btnStyle,
|
||||
label: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
transitionBuilder: (child, animation) =>
|
||||
ScaleTransition(scale: animation, child: child),
|
||||
child: Text(
|
||||
like.count != null ? NumUtils.numFormat(like.count) : '点赞',
|
||||
key: ValueKey<int?>(like.count),
|
||||
style: TextStyle(color: like.status! ? primary : outline),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -368,18 +368,19 @@ class _DynamicDetailPageState extends CommonDynPageState<DynamicDetailPage> {
|
||||
required IconData icon,
|
||||
required String text,
|
||||
required DynamicStat? stat,
|
||||
required VoidCallback onPressed,
|
||||
required ValueChanged<Color> onPressed,
|
||||
IconData? activatedIcon,
|
||||
}) {
|
||||
final status = stat?.status == true;
|
||||
final color = status ? primary : outline;
|
||||
final iconWidget = Icon(
|
||||
status ? activatedIcon : icon,
|
||||
size: 16,
|
||||
color: color,
|
||||
);
|
||||
return TextButton.icon(
|
||||
onPressed: onPressed,
|
||||
icon: Icon(
|
||||
status ? activatedIcon : icon,
|
||||
size: 16,
|
||||
color: color,
|
||||
),
|
||||
onPressed: () => onPressed(iconWidget.color!),
|
||||
icon: iconWidget,
|
||||
style: btnStyle,
|
||||
label: Text(
|
||||
stat?.count != null ? NumUtils.numFormat(stat!.count) : text,
|
||||
@@ -422,7 +423,7 @@ class _DynamicDetailPageState extends CommonDynPageState<DynamicDetailPage> {
|
||||
icon: FontAwesomeIcons.shareFromSquare,
|
||||
text: '转发',
|
||||
stat: forward,
|
||||
onPressed: () => showModalBottomSheet(
|
||||
onPressed: (_) => showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
@@ -449,7 +450,7 @@ class _DynamicDetailPageState extends CommonDynPageState<DynamicDetailPage> {
|
||||
icon: CustomIcons.share_node,
|
||||
text: '分享',
|
||||
stat: null,
|
||||
onPressed: () => Utils.shareText(
|
||||
onPressed: (_) => Utils.shareText(
|
||||
'${HttpString.dynamicShareBaseUrl}/${controller.dynItem.idStr}',
|
||||
),
|
||||
),
|
||||
@@ -462,14 +463,16 @@ class _DynamicDetailPageState extends CommonDynPageState<DynamicDetailPage> {
|
||||
activatedIcon: FontAwesomeIcons.solidThumbsUp,
|
||||
text: '点赞',
|
||||
stat: moduleStat?.like,
|
||||
onPressed: () => RequestUtils.onLikeDynamic(
|
||||
controller.dynItem,
|
||||
() {
|
||||
if (context.mounted) {
|
||||
(context as Element).markNeedsBuild();
|
||||
}
|
||||
},
|
||||
),
|
||||
onPressed: (iconColor) =>
|
||||
RequestUtils.onLikeDynamic(
|
||||
controller.dynItem,
|
||||
iconColor == primary,
|
||||
() {
|
||||
if (context.mounted) {
|
||||
(context as Element).markNeedsBuild();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -8,6 +8,8 @@ import 'package:PiliPlus/models_new/live/live_second_list/data.dart';
|
||||
import 'package:PiliPlus/models_new/live/live_second_list/tag.dart';
|
||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:PiliPlus/services/account_service.dart';
|
||||
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
|
||||
import 'package:flutter/widgets.dart' show ScrollController;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class LiveController extends CommonListController with AccountMixin {
|
||||
@@ -32,6 +34,8 @@ class LiveController extends CommonListController with AccountMixin {
|
||||
final Rx<Pair<LiveCardList?, LiveCardList?>> topState =
|
||||
Pair<LiveCardList?, LiveCardList?>(first: null, second: null).obs;
|
||||
|
||||
final followController = ScrollController();
|
||||
|
||||
@override
|
||||
void checkIsEnd(int length) {
|
||||
if (count != null && length >= count!) {
|
||||
@@ -87,9 +91,10 @@ class LiveController extends CommonListController with AccountMixin {
|
||||
page = 1;
|
||||
isEnd = false;
|
||||
if (areaIndex.value != 0) {
|
||||
queryTop();
|
||||
queryTop().whenComplete(followController.jumpToTop);
|
||||
return queryData();
|
||||
}
|
||||
return queryData();
|
||||
return queryData().whenComplete(followController.jumpToTop);
|
||||
}
|
||||
|
||||
Future<void> queryTop() async {
|
||||
@@ -143,4 +148,10 @@ class LiveController extends CommonListController with AccountMixin {
|
||||
|
||||
@override
|
||||
void onChangeAccount(bool isLogin) => onReload();
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
followController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +295,7 @@ class _LivePageState extends State<LivePage>
|
||||
height: 68.0 + textScaler.scale(12),
|
||||
child: CustomScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: controller.followController,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverFixedExtentList.builder(
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
||||
import 'package:PiliPlus/services/account_service.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
|
||||
import 'package:PiliPlus/utils/login_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
@@ -135,6 +136,7 @@ class MineController extends CommonDataController<FavFolderData, FavFolderData>
|
||||
bool customHandleResponse(bool isRefresh, Success<FavFolderData> response) {
|
||||
favFolderCount = response.response.count;
|
||||
loadingState.value = response;
|
||||
scrollController.jumpToTop();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,6 @@ class _MediaPageState extends CommonPageState<MinePage>
|
||||
child: onBuild(
|
||||
ListView(
|
||||
padding: const .only(bottom: 100),
|
||||
controller: controller.scrollController,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
children: [
|
||||
_buildUserInfo(theme, secondary),
|
||||
@@ -505,6 +504,7 @@ class _MediaPageState extends CommonPageState<MinePage>
|
||||
return SizedBox(
|
||||
height: 200,
|
||||
child: ListView.separated(
|
||||
controller: controller.scrollController,
|
||||
padding: const .only(left: 20, top: 10, right: 20),
|
||||
itemCount: response.list.length + (flag ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
|
||||
@@ -9,14 +9,17 @@ import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:PiliPlus/services/account_service.dart';
|
||||
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart' show ScrollController;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class PgcController
|
||||
extends CommonListController<List<PgcIndexItem>?, PgcIndexItem>
|
||||
with AccountMixin {
|
||||
PgcController({required this.tabType});
|
||||
PgcController({required this.tabType})
|
||||
: indexType = tabType == HomeTabType.cinema ? 102 : null;
|
||||
|
||||
final HomeTabType tabType;
|
||||
final int? indexType;
|
||||
|
||||
late final showPgcTimeline =
|
||||
tabType == HomeTabType.bangumi && Pref.showPgcTimeline;
|
||||
@@ -33,9 +36,6 @@ class PgcController
|
||||
if (showPgcTimeline) {
|
||||
queryPgcTimeline();
|
||||
}
|
||||
if (accountService.isLogin.value) {
|
||||
followController = ScrollController();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -62,7 +62,7 @@ class PgcController
|
||||
late bool followEnd = false;
|
||||
late Rx<LoadingState<List<FavPgcItemModel>?>> followState =
|
||||
LoadingState<List<FavPgcItemModel>?>.loading().obs;
|
||||
ScrollController? followController;
|
||||
final followController = ScrollController();
|
||||
|
||||
// timeline
|
||||
late Rx<LoadingState<List<TimelineResult>?>> timelineState =
|
||||
@@ -117,7 +117,7 @@ class PgcController
|
||||
followEnd = true;
|
||||
}
|
||||
followState.value = Success(list);
|
||||
followController?.animToTop();
|
||||
followController.jumpToTop();
|
||||
} else if (followState.value case Success(:final response)) {
|
||||
final currentList = response!..addAll(list);
|
||||
if (currentList.length >= followCount.value) {
|
||||
@@ -135,12 +135,12 @@ class PgcController
|
||||
@override
|
||||
Future<LoadingState<List<PgcIndexItem>?>> customGetData() => PgcHttp.pgcIndex(
|
||||
page: page,
|
||||
indexType: tabType == HomeTabType.cinema ? 102 : null,
|
||||
indexType: indexType,
|
||||
);
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
followController?.dispose();
|
||||
followController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
|
||||
@@ -417,9 +417,7 @@ class _PgcPageState extends State<PgcPage> with AutomaticKeepAliveClientMixin {
|
||||
? StyleString.safeSpace
|
||||
: 0,
|
||||
),
|
||||
child: PgcCardV(
|
||||
item: response[index],
|
||||
),
|
||||
child: PgcCardV(item: response[index]),
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user