Skip to content

Commit b111a27

Browse files
committed
updated
1 parent cfa19cd commit b111a27

File tree

8 files changed

+325
-42
lines changed

8 files changed

+325
-42
lines changed

lib/data/remote/search_remote_source_impl.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import 'dart:io';
22

33
import 'package:flutter_github_search_rx_redux/data/remote/search_result.dart';
4+
import 'package:http/http.dart' as http;
45

56
import 'search_remote_source.dart';
6-
import 'package:http/http.dart' as http;
77

88
class SearchRemoteSourceImpl implements SearchRemoteSource {
99
final http.Client _client;
@@ -18,6 +18,7 @@ class SearchRemoteSourceImpl implements SearchRemoteSource {
1818
'search/repositories',
1919
{'q': term, 'page': page.toString()},
2020
);
21+
print('SearchRemoteSourceImpl: ${url.queryParameters}');
2122
final response = await _client.get(url);
2223

2324
if (response.statusCode != HttpStatus.ok) {

lib/ui/home/home_action.dart

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,26 @@ class RetryAction implements HomeAction {
4444
// Side effect actions
4545
//
4646

47+
abstract class TextChangedAction
48+
implements Built<TextChangedAction, TextChangedActionBuilder>, HomeAction {
49+
String get term;
50+
51+
TextChangedAction._();
52+
53+
factory TextChangedAction([void Function(TextChangedActionBuilder) updates]) =
54+
_$TextChangedAction;
55+
56+
@override
57+
HomeState reduce(HomeState state) => state;
58+
}
59+
4760
abstract class SearchLoadingAction
4861
implements
4962
Built<SearchLoadingAction, SearchLoadingActionBuilder>,
5063
HomeAction {
5164
String get term;
5265

53-
int get page;
66+
int get nextPage;
5467

5568
SearchLoadingAction._();
5669

@@ -60,7 +73,7 @@ abstract class SearchLoadingAction
6073

6174
@override
6275
HomeState reduce(HomeState state) {
63-
if (page == 1) {
76+
if (nextPage == 1) {
6477
return state.rebuild((b) => b
6578
..term = term
6679
..page = 0
@@ -97,8 +110,16 @@ abstract class SearchSuccessAction
97110
..page = state.page + (items.isEmpty ? 0 : 1)
98111
..term = term
99112
..items = (b.items
100-
..update(
101-
(ib) => state.isFirstPage ? ib.replace(items) : ib.addAll(items)))
113+
..update((ib) {
114+
if (state.isFirstPage) {
115+
ib.replace(items);
116+
} else {
117+
final urls = Set.of(state.items.map((item) => item.htmlUrl));
118+
final distinctItems =
119+
items.where((item) => urls.add(item.htmlUrl));
120+
ib.addAll(distinctItems);
121+
}
122+
}))
102123
..error = null
103124
..isLoading = false,
104125
);
@@ -124,7 +145,6 @@ abstract class SearchFailureAction
124145
HomeState reduce(HomeState state) {
125146
return state.rebuild(
126147
(b) => b
127-
..items = ListBuilder<RepoItem>()
128148
..term = term
129149
..error = error
130150
..isLoading = false,

lib/ui/home/home_action.g.dart

Lines changed: 92 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/ui/home/home_page.dart

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ class _MyHomePageState extends State<MyHomePage> with DisposeBagMixin {
3333
}
3434

3535
void subscribe(RxReduxStore<HomeAction, HomeState> store) {
36+
store.stateStream
37+
.listen((state) => print('Page: ${state.page}'))
38+
.disposedBy(bag);
39+
3640
store.actionStream.listen((action) {
3741
if (action is SearchFailureAction) {
38-
key.snackBar('Error: ${action.error}');
42+
key.snackBar('Error occurred');
3943
}
4044
}).disposedBy(bag);
4145
}
@@ -104,7 +108,8 @@ class _MyHomePageState extends State<MyHomePage> with DisposeBagMixin {
104108
width: 128,
105109
height: 48,
106110
child: RaisedButton(
107-
onPressed: () => store.dispatch(RetryAction()),
111+
onPressed: () =>
112+
store.dispatch(const RetryAction()),
108113
child: Text('Retry'),
109114
elevation: 12,
110115
shape: RoundedRectangleBorder(
@@ -162,9 +167,29 @@ class RepoItemsListWidget extends StatelessWidget {
162167
}
163168

164169
if (state.error != null) {
165-
return ListTile(
166-
title: Text(
167-
"Search for '${state.term}', page: ${state.page + 1} error: ${state.error}"),
170+
return Padding(
171+
padding: const EdgeInsets.all(8.0),
172+
child: Column(
173+
children: [
174+
Text(
175+
"Search for '${state.term}', page: ${state.page + 1} error: ${state.error}",
176+
style: Theme.of(context).textTheme.subtitle2,
177+
textAlign: TextAlign.center,
178+
),
179+
const SizedBox(height: 16),
180+
SizedBox(
181+
width: 128,
182+
height: 48,
183+
child: RaisedButton(
184+
onPressed: () => dispatch(const RetryAction()),
185+
child: Text('Retry'),
186+
elevation: 12,
187+
shape: RoundedRectangleBorder(
188+
borderRadius: BorderRadius.circular(24)),
189+
),
190+
),
191+
],
192+
),
168193
);
169194
}
170195

@@ -184,10 +209,16 @@ class RepoItemsListWidget extends StatelessWidget {
184209
return Padding(
185210
padding: const EdgeInsets.only(bottom: 12),
186211
child: Center(
187-
child: RaisedButton(
188-
onPressed: () => dispatch(const LoadNextPageAction()),
189-
padding: const EdgeInsets.all(12),
190-
child: Text('Load next page'),
212+
child: SizedBox(
213+
width: 128,
214+
height: 48,
215+
child: RaisedButton(
216+
onPressed: () => dispatch(const LoadNextPageAction()),
217+
child: Text('Load next page'),
218+
elevation: 12,
219+
shape: RoundedRectangleBorder(
220+
borderRadius: BorderRadius.circular(24)),
221+
),
191222
),
192223
),
193224
);

lib/ui/home/home_state.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,13 @@ abstract class HomeState implements Built<HomeState, HomeStateBuilder> {
2828
);
2929

3030
bool get isFirstPage => page == 0;
31+
32+
bool get canLoadNextPage =>
33+
!isLoading &&
34+
error == null &&
35+
items.isNotEmpty &&
36+
term.isNotEmpty &&
37+
page > 0;
38+
39+
bool get canRetry => !isLoading && error != null;
3140
}

0 commit comments

Comments
 (0)