mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
refactor: member dynamic page
fix: DynamicsDataModel parsing error Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/models/common/reply_type.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/pages/video/detail/reply_new/reply_page.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -56,7 +57,7 @@ abstract class ReplyController extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (noMore.value == '没有更多了') return Future.value();
|
||||
if (isRefresh.not && noMore.value == '没有更多了') return Future.value();
|
||||
return super.queryData(isRefresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:PiliPalaX/http/fan.dart';
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:PiliPalaX/utils/storage.dart';
|
||||
@@ -36,7 +37,7 @@ class FansController extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (isEnd) {
|
||||
if (isRefresh.not && isEnd) {
|
||||
return Future.value();
|
||||
}
|
||||
return super.queryData(isRefresh);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:PiliPalaX/http/user.dart';
|
||||
import 'package:PiliPalaX/models/user/info.dart';
|
||||
@@ -23,7 +24,7 @@ class FavController extends CommonController {
|
||||
loadingState.value = LoadingState.error('账号未登录');
|
||||
return Future.value();
|
||||
}
|
||||
if (!hasMore) {
|
||||
if (isRefresh.not && hasMore.not) {
|
||||
return Future.value();
|
||||
}
|
||||
return super.queryData(isRefresh);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/http/user.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:PiliPalaX/utils/storage.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -38,7 +39,7 @@ class FavDetailController extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (loadingText.value == '没有更多了') {
|
||||
if (isRefresh.not && loadingText.value == '没有更多了') {
|
||||
return Future.value();
|
||||
}
|
||||
return super.queryData(isRefresh);
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/http/member.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/pages/fav_search/view.dart' show SearchType;
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -58,7 +59,7 @@ class FavSearchController extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (!hasMore) {
|
||||
if (isRefresh.not && hasMore.not) {
|
||||
return Future.value();
|
||||
}
|
||||
return super.queryData(isRefresh);
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/http/member.dart';
|
||||
import 'package:PiliPalaX/models/space_article/data.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
|
||||
class MemberArticleCtr extends CommonController {
|
||||
MemberArticleCtr({
|
||||
@@ -27,7 +28,7 @@ class MemberArticleCtr extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (isEnd) return Future.value();
|
||||
if (isRefresh.not && isEnd) return Future.value();
|
||||
return super.queryData(isRefresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/pages/member/new/content/member_contribute/member_contribute.dart'
|
||||
show ContributeType;
|
||||
import 'package:PiliPalaX/pages/member/new/controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class MemberBangumiCtr extends CommonController {
|
||||
@@ -38,7 +39,7 @@ class MemberBangumiCtr extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (isEnd) return Future.value();
|
||||
if (isRefresh.not && isEnd) return Future.value();
|
||||
return super.queryData(isRefresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:PiliPalaX/models/space_archive/data.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/pages/member/new/content/member_contribute/member_contribute.dart'
|
||||
show ContributeType;
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class MemberVideoCtr extends CommonController {
|
||||
@@ -43,7 +44,7 @@ class MemberVideoCtr extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (isEnd) return Future.value();
|
||||
if (isRefresh.not && isEnd) return Future.value();
|
||||
return super.queryData(isRefresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:PiliPalaX/grpc/app/dynamic/v2/dynamic.pb.dart';
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/http/member.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
|
||||
class MemberDynamicCtr extends CommonController {
|
||||
MemberDynamicCtr({
|
||||
@@ -24,7 +25,7 @@ class MemberDynamicCtr extends CommonController {
|
||||
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (isEnd) return Future.value();
|
||||
if (isRefresh.not && isEnd) return Future.value();
|
||||
return super.queryData(isRefresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ class _MemberPageNewState extends State<MemberPageNew>
|
||||
|
||||
Widget get _buildBody => SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: TabBarView(
|
||||
controller: _userController.tabController,
|
||||
children: _userController.tab2!.map((item) {
|
||||
|
||||
@@ -1,48 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:PiliPalaX/http/member.dart';
|
||||
import 'package:PiliPalaX/models/dynamics/result.dart';
|
||||
|
||||
class MemberDynamicsController extends GetxController {
|
||||
class MemberDynamicsController extends CommonController {
|
||||
MemberDynamicsController(this.mid);
|
||||
final ScrollController scrollController = ScrollController();
|
||||
int? mid;
|
||||
int mid;
|
||||
String offset = '';
|
||||
int count = 0;
|
||||
bool hasMore = true;
|
||||
RxList<DynamicItemModel> dynamicsList = <DynamicItemModel>[].obs;
|
||||
|
||||
// TODO: refactor
|
||||
late Future futureBuilderFuture;
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
futureBuilderFuture = getMemberDynamic('onRefresh');
|
||||
queryData();
|
||||
}
|
||||
|
||||
Future getMemberDynamic(type) async {
|
||||
if (type == 'onRefresh') {
|
||||
offset = '';
|
||||
dynamicsList.clear();
|
||||
}
|
||||
if (offset == '-1') {
|
||||
return;
|
||||
}
|
||||
var res = await MemberHttp.memberDynamic(
|
||||
offset: offset,
|
||||
mid: mid,
|
||||
);
|
||||
if (res['status']) {
|
||||
dynamicsList.addAll(res['data'].items);
|
||||
offset = res['data'].offset != '' ? res['data'].offset : '-1';
|
||||
hasMore = res['data'].hasMore;
|
||||
}
|
||||
return res;
|
||||
@override
|
||||
Future onRefresh() {
|
||||
offset = '';
|
||||
hasMore = true;
|
||||
return super.onRefresh();
|
||||
}
|
||||
|
||||
// 上拉加载
|
||||
Future onLoad() async {
|
||||
getMemberDynamic('onLoad');
|
||||
@override
|
||||
Future queryData([bool isRefresh = true]) {
|
||||
if (isRefresh.not && (hasMore.not || offset == '-1')) {
|
||||
return Future.value();
|
||||
}
|
||||
return super.queryData(isRefresh);
|
||||
}
|
||||
|
||||
@override
|
||||
bool customHandleResponse(Success response) {
|
||||
DynamicsDataModel data = response.response;
|
||||
offset = data.offset?.isNotEmpty == true ? data.offset! : '-1';
|
||||
hasMore = data.hasMore ?? false;
|
||||
if (currentPage != 1 && loadingState.value is Success) {
|
||||
data.items?.insertAll(0, (loadingState.value as Success).response);
|
||||
}
|
||||
loadingState.value = LoadingState.success(data.items);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LoadingState> customGetData() => MemberHttp.memberDynamic(
|
||||
offset: offset,
|
||||
mid: mid,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:PiliPalaX/common/widgets/refresh_indicator.dart';
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -36,29 +38,10 @@ class _MemberDynamicsPageState extends State<MemberDynamicsPage>
|
||||
final String heroTag = Utils.makeHeroTag(mid);
|
||||
_memberDynamicController =
|
||||
Get.put(MemberDynamicsController(mid), tag: heroTag);
|
||||
// _memberDynamicController.scrollController.addListener(
|
||||
// () {
|
||||
// if (_memberDynamicController.scrollController.position.pixels >=
|
||||
// _memberDynamicController.scrollController.position.maxScrollExtent -
|
||||
// 200) {
|
||||
// EasyThrottle.throttle(
|
||||
// 'member_dynamics', const Duration(milliseconds: 1000), () {
|
||||
// _memberDynamicController.onLoad();
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// );
|
||||
dynamicsWaterfallFlow = GStorage.setting
|
||||
.get(SettingBoxKey.dynamicsWaterfallFlow, defaultValue: true);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// _memberDynamicController.scrollController.removeListener(() {});
|
||||
_memberDynamicController.scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
@@ -75,106 +58,91 @@ class _MemberDynamicsPageState extends State<MemberDynamicsPage>
|
||||
: _buildBody;
|
||||
}
|
||||
|
||||
Widget get _buildBody => CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
// controller: _memberDynamicController.scrollController,
|
||||
slivers: [
|
||||
FutureBuilder(
|
||||
future: _memberDynamicController.futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.data != null) {
|
||||
Map data = snapshot.data as Map;
|
||||
List list = _memberDynamicController.dynamicsList;
|
||||
if (data['status']) {
|
||||
return Obx(() {
|
||||
if (list.isEmpty) {
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
if (!dynamicsWaterfallFlow) {
|
||||
return SliverCrossAxisGroup(
|
||||
slivers: [
|
||||
const SliverFillRemaining(),
|
||||
SliverConstrainedCrossAxis(
|
||||
maxExtent: Grid.maxRowWidth * 2,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == list.length - 1) {
|
||||
EasyThrottle.throttle('member_dynamics',
|
||||
const Duration(milliseconds: 1000),
|
||||
() {
|
||||
_memberDynamicController.onLoad();
|
||||
});
|
||||
}
|
||||
return DynamicPanel(item: list[index]);
|
||||
},
|
||||
childCount: list.length,
|
||||
),
|
||||
)),
|
||||
const SliverFillRemaining(),
|
||||
],
|
||||
);
|
||||
}
|
||||
return SliverWaterfallFlow.extent(
|
||||
maxCrossAxisExtent: Grid.maxRowWidth * 2,
|
||||
//cacheExtent: 0.0,
|
||||
crossAxisSpacing: StyleString.safeSpace,
|
||||
mainAxisSpacing: StyleString.safeSpace,
|
||||
|
||||
/// follow max child trailing layout offset and layout with full cross axis extend
|
||||
/// last child as loadmore item/no more item in [GridView] and [WaterfallFlow]
|
||||
/// with full cross axis extend
|
||||
// LastChildLayoutType.fullCrossAxisExtend,
|
||||
|
||||
/// as foot at trailing and layout with full cross axis extend
|
||||
/// show no more item at trailing when children are not full of viewport
|
||||
/// if children is full of viewport, it's the same as fullCrossAxisExtend
|
||||
// LastChildLayoutType.foot,
|
||||
lastChildLayoutTypeBuilder: (index) {
|
||||
if (index == list.length - 1) {
|
||||
EasyThrottle.throttle('member_dynamics',
|
||||
const Duration(milliseconds: 1000), () {
|
||||
_memberDynamicController.onLoad();
|
||||
});
|
||||
}
|
||||
return index == list.length
|
||||
? LastChildLayoutType.foot
|
||||
: LastChildLayoutType.none;
|
||||
},
|
||||
children: [
|
||||
for (var i in list) DynamicPanel(item: i),
|
||||
]);
|
||||
});
|
||||
} else {
|
||||
return HttpError(
|
||||
errMsg: snapshot.data['msg'],
|
||||
fn: () {
|
||||
setState(() {
|
||||
_memberDynamicController.futureBuilderFuture =
|
||||
_memberDynamicController
|
||||
.getMemberDynamic('onRefresh');
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return HttpError(
|
||||
errMsg: 'NULL',
|
||||
fn: () {
|
||||
setState(() {
|
||||
_memberDynamicController.futureBuilderFuture =
|
||||
_memberDynamicController
|
||||
.getMemberDynamic('onRefresh');
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
Widget get _buildBody => refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _memberDynamicController.onRefresh();
|
||||
},
|
||||
child: Obx(
|
||||
() => _memberDynamicController.loadingState.value is Loading
|
||||
? Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
_buildContent(_memberDynamicController.loadingState.value),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
_buildContent(LoadingState loadingState) {
|
||||
return loadingState is Success
|
||||
? SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom,
|
||||
),
|
||||
sliver: dynamicsWaterfallFlow
|
||||
? SliverWaterfallFlow.extent(
|
||||
maxCrossAxisExtent: Grid.maxRowWidth * 2,
|
||||
//cacheExtent: 0.0,
|
||||
crossAxisSpacing: StyleString.safeSpace,
|
||||
mainAxisSpacing: StyleString.safeSpace,
|
||||
|
||||
/// follow max child trailing layout offset and layout with full cross axis extend
|
||||
/// last child as loadmore item/no more item in [GridView] and [WaterfallFlow]
|
||||
/// with full cross axis extend
|
||||
// LastChildLayoutType.fullCrossAxisExtend,
|
||||
|
||||
/// as foot at trailing and layout with full cross axis extend
|
||||
/// show no more item at trailing when children are not full of viewport
|
||||
/// if children is full of viewport, it's the same as fullCrossAxisExtend
|
||||
// LastChildLayoutType.foot,
|
||||
lastChildLayoutTypeBuilder: (index) {
|
||||
if (index == loadingState.response.length - 1) {
|
||||
EasyThrottle.throttle('member_dynamics',
|
||||
const Duration(milliseconds: 1000), () {
|
||||
_memberDynamicController.onLoadMore();
|
||||
});
|
||||
}
|
||||
return index == loadingState.response.length
|
||||
? LastChildLayoutType.foot
|
||||
: LastChildLayoutType.none;
|
||||
},
|
||||
children: (loadingState.response as List)
|
||||
.map((item) => DynamicPanel(item: item))
|
||||
.toList(),
|
||||
)
|
||||
: SliverCrossAxisGroup(
|
||||
slivers: [
|
||||
const SliverFillRemaining(),
|
||||
SliverConstrainedCrossAxis(
|
||||
maxExtent: Grid.maxRowWidth * 2,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == loadingState.response.length - 1) {
|
||||
EasyThrottle.throttle('member_dynamics',
|
||||
const Duration(milliseconds: 1000), () {
|
||||
_memberDynamicController.onLoadMore();
|
||||
});
|
||||
}
|
||||
return DynamicPanel(
|
||||
item: loadingState.response[index]);
|
||||
},
|
||||
childCount: loadingState.response.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SliverFillRemaining(),
|
||||
],
|
||||
),
|
||||
)
|
||||
: HttpError(
|
||||
errMsg: loadingState is Error ? loadingState.errMsg : null,
|
||||
fn: () {
|
||||
_memberDynamicController.onReload();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user