1+ import 'package:easy_refresh/easy_refresh.dart' ;
2+ import 'package:flutter/foundation.dart' ;
13import 'package:flutter/material.dart' ;
24import 'package:fluttertoast/fluttertoast.dart' ;
35import 'package:gsy_github_app_flutter/common/localization/extension.dart' ;
6+ import 'package:gsy_github_app_flutter/common/repositories/data_result.dart' ;
47import 'package:gsy_github_app_flutter/model/file_model.dart' ;
58import 'package:gsy_github_app_flutter/common/style/gsy_style.dart' ;
69import 'package:gsy_github_app_flutter/common/utils/common_utils.dart' ;
710import 'package:gsy_github_app_flutter/common/utils/navigator_utils.dart' ;
811import 'package:gsy_github_app_flutter/page/repos/provider/repos_detail_provider.dart' ;
912import 'package:gsy_github_app_flutter/widget/gsy_card_item.dart' ;
10- import 'package:gsy_github_app_flutter/widget/state/gsy_list_state.dart' ;
11- import 'package:gsy_github_app_flutter/widget/pull/gsy_pull_load_widget.dart' ;
1213import 'package:provider/provider.dart' ;
14+ import 'package:signals/signals_flutter.dart' ;
1315
1416/// 仓库文件列表
1517/// Created by guoshuyu
@@ -27,18 +29,24 @@ class RepositoryDetailFileListPageState
2729 extends State <RepositoryDetailFileListPage >
2830 with
2931 AutomaticKeepAliveClientMixin <RepositoryDetailFileListPage >,
30- GSYListState <RepositoryDetailFileListPage > {
32+ SignalsMixin {
33+ ///使用 signal 例子,整个页面没用 setState
34+ late var dataList = createListSignal <FileModel >([]);
35+ late var headerList = createListSignal <String >(["." ]);
36+
37+ final EasyRefreshController controller = EasyRefreshController ();
38+
39+ bool _isLoading = false ;
40+
3141 String path = '' ;
3242
3343 String ? searchText;
3444 String ? issueState;
3545
36- List <String ?> headerList = ["." ];
37-
3846 ///渲染文件item
3947 _renderEventItem (index) {
40- FileItemViewModel fileItemViewModel =
41- FileItemViewModel .fromMap (pullLoadWidgetControl.dataList[index] );
48+ var item = dataList.value[index];
49+ FileItemViewModel fileItemViewModel = FileItemViewModel .fromMap (item );
4250 IconData iconData = (fileItemViewModel.type == "file" )
4351 ? GSYICons .REPOS_ITEM_FILE
4452 : GSYICons .REPOS_ITEM_DIR ;
@@ -76,7 +84,7 @@ class RepositoryDetailFileListPageState
7684 _resolveHeaderClick (index);
7785 },
7886 child:
79- Text ("${headerList [index ]! } > " , style: GSYConstant .smallText),
87+ Text ("${headerList [index ]} > " , style: GSYConstant .smallText),
8088 );
8189 },
8290 itemCount: headerList.length,
@@ -86,23 +94,19 @@ class RepositoryDetailFileListPageState
8694
8795 ///头部列表点击
8896 _resolveHeaderClick (index) {
89- if (isLoading ) {
97+ if (_isLoading ) {
9098 Fluttertoast .showToast (msg: context.l10n.loading_text);
9199 return ;
92100 }
93101 if (headerList.isNotEmpty && index != - 1 && headerList[index] != "." ) {
94- List <String ? > newHeaderList = headerList.sublist (0 , index + 1 );
102+ List <String > newHeaderList = headerList.sublist (0 , index + 1 );
95103 String path = newHeaderList.sublist (1 , newHeaderList.length).join ("/" );
96- setState (() {
97- this .path = path;
98- headerList = newHeaderList;
99- });
104+ this .path = path;
105+ headerList.value = newHeaderList;
100106 showRefreshLoading ();
101107 } else {
102- setState (() {
103- path = "" ;
104- headerList = ["." ];
105- });
108+ path = "" ;
109+ headerList.value = ["." ];
106110 showRefreshLoading ();
107111 }
108112 }
@@ -111,17 +115,14 @@ class RepositoryDetailFileListPageState
111115 _resolveItemClick (FileItemViewModel fileItemViewModel) {
112116 var provider = context.read <ReposDetailProvider >();
113117 if (fileItemViewModel.type == "dir" ) {
114- if (isLoading ) {
118+ if (_isLoading ) {
115119 Fluttertoast .showToast (msg: context.l10n.loading_text);
116120 return ;
117121 }
118- setState (() {
119- headerList.add (fileItemViewModel.name);
120- });
122+
123+ headerList.add (fileItemViewModel.name! );
121124 String path = headerList.sublist (1 , headerList.length).join ("/" );
122- setState (() {
123- this .path = path;
124- });
125+ this .path = path;
125126 showRefreshLoading ();
126127 } else {
127128 String path =
@@ -148,35 +149,52 @@ class RepositoryDetailFileListPageState
148149 }
149150 }
150151
151- _getDataLogic (String ? searchString) async {
152+ Future < DataResult > _getDataLogic (String ? searchString) async {
152153 return await context
153154 .read <ReposDetailProvider >()
154155 .getReposFileDirRequest (path: path);
155156 }
156157
157- @override
158- bool get wantKeepAlive => true ;
159-
160- @override
161- bool get needHeader => false ;
162-
163- @override
164- bool get isRefreshFirst => true ;
165-
166- @override
167- requestLoadMore () async {
168- return await _getDataLogic (searchText);
158+ /// 模拟IOS下拉显示刷新
159+ showRefreshLoading () {
160+ ///直接触发下拉
161+ Future .delayed (const Duration (seconds: 0 ), () {
162+ controller.callRefresh ();
163+ return true ;
164+ });
169165 }
170166
171167 @override
168+ bool get wantKeepAlive => true ;
169+
172170 requestRefresh () async {
173- return await _getDataLogic (searchText);
171+ _isLoading = true ;
172+ var res = await _getDataLogic (searchText);
173+ try {
174+ if (res.result) {
175+ var data = res.data;
176+ if (data != null ) {
177+ dataList.value = data as List <FileModel >;
178+ }
179+ }
180+ if (res.next != null ) {
181+ var data = await res.next? .call ();
182+ if (data != null ) {
183+ dataList.value = data as List <FileModel >;
184+ }
185+ }
186+ } catch (e) {
187+ if (kDebugMode) {
188+ print (e);
189+ }
190+ }
191+ _isLoading = false ;
174192 }
175193
176194 @override
177195 Widget build (BuildContext context) {
178196 super .build (context); // See AutomaticKeepAliveClientMixin.
179- var proivder = context.watch <ReposDetailProvider >();
197+ var provider = context.watch <ReposDetailProvider >();
180198 return Scaffold (
181199 backgroundColor: GSYColors .mainBackgroundColor,
182200 appBar: AppBar (
@@ -186,18 +204,21 @@ class RepositoryDetailFileListPageState
186204 elevation: 0.0 ,
187205 ),
188206 body: PopScope (
189- canPop: proivder .currentIndex != 3 || headerList.length == 1 ,
207+ canPop: provider .currentIndex != 3 || headerList.length == 1 ,
190208 onPopInvokedWithResult: (didPop, _) {
191209 if (didPop == false ) {
192210 _resolveHeaderClick (headerList.length - 2 );
193211 }
194212 },
195- child: GSYPullLoadWidget (
196- pullLoadWidgetControl,
197- (BuildContext context, int index) => _renderEventItem (index),
198- handleRefresh,
199- onLoadMore,
200- refreshKey: refreshIndicatorKey,
213+ child: EasyRefresh (
214+ controller: controller,
215+ header: const MaterialHeader (),
216+ refreshOnStart: true ,
217+ onRefresh: requestRefresh,
218+ child: ListView .builder (
219+ itemBuilder: (_, int index) => _renderEventItem (index),
220+ itemCount: dataList.length,
221+ ),
201222 ),
202223 ),
203224 );
0 commit comments