diff --git a/lib/http/api.dart b/lib/http/api.dart index 0f29db31..72d1ddef 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -234,4 +234,7 @@ class Api { // w_rid=d893cf98a4e010cf326373194a648360& // wts=1689767832 static const String memberArchive = '/x/space/wbi/arc/search'; + + // 用户动态 + static const String memberDynamic = '/x/polymer/web-dynamic/v1/feed/space'; } diff --git a/lib/http/member.dart b/lib/http/member.dart index 63442b04..995ccc23 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -1,4 +1,5 @@ import 'package:pilipala/http/index.dart'; +import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/models/member/archive.dart'; import 'package:pilipala/models/member/info.dart'; import 'package:pilipala/utils/wbi_sign.dart'; @@ -96,4 +97,26 @@ class MemberHttp { }; } } + + // 用户动态 + static Future memberDynamic({String? offset, int? mid}) async { + var res = await Request().get(Api.memberDynamic, data: { + 'offset': offset ?? '', + 'host_mid': mid, + 'timezone_offset': '-480', + 'features': 'itemOpusStyle', + }); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': DynamicsDataModel.fromJson(res.data['data']), + }; + } else { + return { + 'status': false, + 'data': [], + 'msg': res.data['message'], + }; + } + } } diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index 6d91d5c9..abf42af4 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -234,7 +234,7 @@ class Vote { int? endTime; int? joinNum; int? status; - String? type; + int? type; int? uid; int? voteId; diff --git a/lib/pages/member/archive/view.dart b/lib/pages/member/archive/view.dart index d477ae13..ba223ab1 100644 --- a/lib/pages/member/archive/view.dart +++ b/lib/pages/member/archive/view.dart @@ -36,11 +36,12 @@ class _ArchivePanelState extends State Column( children: [ // 下拉刷新指示器 - PullToRefreshContainer( - (PullToRefreshScrollNotificationInfo? info) { - return PullToRefreshHeader(info, lastRefreshTime); - }, - ), + // PullToRefreshContainer( + // (PullToRefreshScrollNotificationInfo? info) { + // return PullToRefreshHeader(info, lastRefreshTime); + // }, + // ), + const SizedBox(height: 4), Expanded( child: LoadingMoreList( ListConfig( diff --git a/lib/pages/member/dynamic/controller.dart b/lib/pages/member/dynamic/controller.dart new file mode 100644 index 00000000..ff45e056 --- /dev/null +++ b/lib/pages/member/dynamic/controller.dart @@ -0,0 +1,25 @@ +import 'package:get/get.dart'; +import 'package:pilipala/http/member.dart'; + +class MemberDynamicPanelController extends GetxController { + int? mid; + String offset = ''; + int count = 0; + + @override + void onInit() { + super.onInit(); + mid = int.parse(Get.parameters['mid']!); + } + + Future getMemberDynamic() async { + var res = await MemberHttp.memberDynamic( + offset: offset, + mid: mid, + ); + if (res['status']) { + offset = res['data'].offset; + } + return res; + } +} diff --git a/lib/pages/member/dynamic/index.dart b/lib/pages/member/dynamic/index.dart new file mode 100644 index 00000000..de6f3f89 --- /dev/null +++ b/lib/pages/member/dynamic/index.dart @@ -0,0 +1,4 @@ +library dynamic_panel; + +export './controller.dart'; +export './view.dart'; diff --git a/lib/pages/member/dynamic/view.dart b/lib/pages/member/dynamic/view.dart new file mode 100644 index 00000000..975e0857 --- /dev/null +++ b/lib/pages/member/dynamic/view.dart @@ -0,0 +1,138 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:loading_more_list/loading_more_list.dart'; +import 'package:pilipala/models/dynamics/result.dart'; +import 'package:pilipala/pages/dynamics/widgets/dynamic_panel.dart'; + +import 'controller.dart'; + +class MemberDynamicPanel extends StatefulWidget { + const MemberDynamicPanel({super.key}); + + @override + State createState() => _MemberDynamicPanelState(); +} + +class _MemberDynamicPanelState extends State + with AutomaticKeepAliveClientMixin { + DateTime lastRefreshTime = DateTime.now(); + late final LoadMoreListSource source = LoadMoreListSource(); + + @override + bool get wantKeepAlive => true; + + @override + Widget build(BuildContext context) { + return Expanded( + child: LoadingMoreList( + ListConfig( + sourceList: source, + itemBuilder: (BuildContext c, DynamicItemModel item, int index) { + return DynamicPanel(item: item); + }, + indicatorBuilder: _buildIndicator, + ), + ), + ); + } + + Widget _buildIndicator(BuildContext context, IndicatorStatus status) { + TextStyle style = + TextStyle(fontSize: 13, color: Theme.of(context).colorScheme.outline); + Widget? widget; + switch (status) { + case IndicatorStatus.none: + widget = Container(height: 0.0); + break; + case IndicatorStatus.loadingMoreBusying: + widget = Text('加载中...', style: style); + widget = _setbackground(false, widget, height: 60.0); + break; + case IndicatorStatus.fullScreenBusying: + widget = Text('加载中...', style: style); + widget = _setbackground(true, widget); + break; + case IndicatorStatus.error: + + /// TODO 异常逻辑 + widget = Text('没有更多了', style: style); + widget = _setbackground(false, widget); + + widget = GestureDetector( + onTap: () {}, + child: widget, + ); + + break; + case IndicatorStatus.fullScreenError: + + /// TODO 异常逻辑 + widget = Text('没有更多了', style: style); + widget = _setbackground(true, widget); + widget = GestureDetector( + onTap: () {}, + child: widget, + ); + break; + case IndicatorStatus.noMoreLoad: + widget = Text('没有更多了', style: style); + widget = _setbackground(false, widget, height: 60.0); + break; + case IndicatorStatus.empty: + widget = Text('用户没有投稿', style: style); + widget = _setbackground(true, widget); + break; + } + return widget; + } + + Widget _setbackground(bool full, Widget widget, {double height = 100}) { + widget = Padding( + padding: height == double.infinity + ? EdgeInsets.zero + : EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + child: Container( + width: double.infinity, + height: height, + color: Theme.of(context).colorScheme.background, + alignment: Alignment.center, + child: widget, + ), + ); + return widget; + } + + Widget getIndicator(BuildContext context) { + final TargetPlatform platform = Theme.of(context).platform; + return platform == TargetPlatform.iOS + ? const CupertinoActivityIndicator( + animating: true, + radius: 16.0, + ) + : CircularProgressIndicator( + strokeWidth: 2.0, + valueColor: + AlwaysStoppedAnimation(Theme.of(context).primaryColor), + ); + } +} + +class LoadMoreListSource extends LoadingMoreBase { + final _dynamicController = Get.put(MemberDynamicPanelController()); + + // @override + Future loadData([bool isloadMoreAction = false]) async { + bool isSuccess = false; + var res = await _dynamicController.getMemberDynamic(); + if (res['status']) { + addAll(res['data'].items); + } + if (res['data'].hasMore) { + isSuccess = true; + } else { + isSuccess = false; + } + return isSuccess; + } +} diff --git a/lib/pages/member/view.dart b/lib/pages/member/view.dart index 6eafbe6f..839c5685 100644 --- a/lib/pages/member/view.dart +++ b/lib/pages/member/view.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:pilipala/pages/member/archive/view.dart'; +import 'package:pilipala/pages/member/dynamic/index.dart'; import 'package:pilipala/pages/member/index.dart'; import 'widgets/profile.dart'; @@ -266,7 +267,7 @@ class _MemberPageState extends State controller: _tabController, children: const [ Text('主页'), - Text('动态'), + MemberDynamicPanel(), ArchivePanel(), ], ))