Skip to content

Commit

Permalink
feat(frontend/pagination): Add support to paginated starred repos
Browse files Browse the repository at this point in the history
  • Loading branch information
Grohden committed Aug 5, 2020
1 parent 6d0202f commit ea5c16b
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 10 deletions.
12 changes: 6 additions & 6 deletions frontend/lib/api/tagger/repository_tagger_cache_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class RepositoryTaggerCacheClient implements RepositoryTaggerClient {

final RepositoryTaggerClient delegate;

List<SimpleRepository> _cachedStarredRepos = [];
Map<int, List<SimpleRepository>> _cachedStarredRepos = {};

@override
Future<UserTag> addTag(CreateTagInput input) => delegate.addTag(input);
Expand All @@ -36,14 +36,14 @@ class RepositoryTaggerCacheClient implements RepositoryTaggerClient {
delegate.repositoriesByTag(id);

@override
Future<List<SimpleRepository>> starredRepos() async {
if (_cachedStarredRepos.isEmpty) {
final repos = await delegate.starredRepos();
Future<List<SimpleRepository>> starredRepos({int page}) async {
if (!_cachedStarredRepos.containsKey(page)) {
final repos = await delegate.starredRepos(page: page);

_cachedStarredRepos = repos;
_cachedStarredRepos[page] = repos;
}

return _cachedStarredRepos;
return _cachedStarredRepos[page];
}

@override
Expand Down
4 changes: 3 additions & 1 deletion frontend/lib/api/tagger/repository_tagger_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ abstract class RepositoryTaggerClient {

/// Lists a authorized user starred repositories
@GET('/repository/starred')
Future<List<SimpleRepository>> starredRepos();
Future<List<SimpleRepository>> starredRepos({
@Query('page') int page,
});

/// Lists all repositories associated with a tag
@GET('/tag/{tagId}/repositories')
Expand Down
20 changes: 20 additions & 0 deletions frontend/lib/ui/pages/starred/starred_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ class StarredController extends GetxController {
final formKey = GlobalKey<FormState>();
final tagger = Get.find<RepositoryTaggerClient>();

int _currentPage = 1;
final hasLoadError = false.obs;
final showLoading = false.obs;
final showLoadingMore = false.obs;
final repositories = RxList<SimpleRepository>([]);

void onInit() async {
super.onInit();
_currentPage = 1;
showLoading.value = true;
hasLoadError.value = false;

Expand All @@ -26,4 +29,21 @@ class StarredController extends GetxController {
void openRepo(SimpleRepository repo) {
Router.goToRepositoryDetails(repo.githubId);
}

void loadMore() async {
try {
showLoadingMore.value = true;
final more = await tagger.starredRepos(page: _currentPage + 1);
repositories.assignAll(more);
_currentPage += 1;
} on DioError catch (error) {
Get.dialog(
AdaptiveDialog.alert(
title: Text(error.message ?? 'Unknown error'),
),
);
} finally {
showLoadingMore.value = false;
}
}
}
4 changes: 4 additions & 0 deletions frontend/lib/ui/pages/starred/starred_page.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../../api/tagger/repository_tagger_client.dart';
import '../../../router.dart';
import '../../molecules/load_page_error.dart';
import '../../molecules/page_title.dart';
import '../../organisms/adaptive_dialog.dart';
import '../../templates/repository_list.dart';
import '../../utils/tagger_page.dart';

Expand Down Expand Up @@ -41,6 +43,8 @@ class StarredPage extends TaggerPage<StarredController> {
title: const PageTitle('Your starred repositories'),
onOpen: controller.openRepo,
items: controller.repositories.value,
onLoadMore: controller.loadMore,
isLoadingMore: controller.showLoadingMore.value,
);
}
}
25 changes: 22 additions & 3 deletions frontend/lib/ui/templates/repository_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@ import 'package:flutter/material.dart';

import '../../api/tagger/repository_tagger_client.dart';
import '../molecules/detail_chip.dart';
import '../molecules/primary_raised_button.dart';
import 'page_body.dart';

/// Default repository list template
class RepositoryList extends StatelessWidget {
const RepositoryList(
{@required this.title, @required this.items, @required this.onOpen});
const RepositoryList({
@required this.title,
@required this.items,
@required this.onOpen,
this.onLoadMore,
this.isLoadingMore,
});

final Widget title;
final List<SimpleRepository> items;
final Function(SimpleRepository repository) onOpen;

/// If specified, shows a load more button at the bottom of the page
final Function() onLoadMore;
final bool isLoadingMore;

@override
Widget build(BuildContext context) {
return SafeArea(
Expand All @@ -27,12 +37,21 @@ class RepositoryList extends StatelessWidget {

Widget _buildList(BuildContext context) {
final style = Theme.of(context).textTheme;
final offset = onLoadMore != null ? 1 : 0;

return ListView.separated(
itemCount: items.length,
itemCount: items.length + offset,
padding: const EdgeInsets.all(kStandardPadding),
separatorBuilder: (_, __) => const Divider(thickness: 1),
itemBuilder: (context, index) {
if (index >= items.length) {
return PrimaryRaisedButton(
child: const Text('Load more'),
onPressed: onLoadMore,
showLoader: isLoadingMore,
);
}

final item = items[index];

return ListTile(
Expand Down

0 comments on commit ea5c16b

Please sign in to comment.