GiteaClient/lib/widget/repo_list.dart

103 lines
No EOL
2.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gitea_client/cubit/repo_event.dart';
import 'package:gitea_client/model/repository.dart';
import '../cubit/repo_cubit.dart';
class ReposList extends StatefulWidget {
@override
_ReposListState createState() => _ReposListState();
}
class _ReposListState extends State<ReposList> {
final _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<RepoBloc, RepoState>(
builder: (context, state) {
switch (state.status) {
case RepoStatus.failure:
String error_message = state.error_message!;
return Center(child: Text('failed to fetch $error_message'));
case RepoStatus.success:
if (state.repos.isEmpty) {
return const Center(child: Text('no posts'));
}
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return index >= state.repos.length
? BottomLoader()
: RepoListItem(post: state.repos[index]);
},
itemCount: state.hasReachedMax
? state.repos.length
: state.repos.length + 1,
controller: _scrollController,
);
default:
return const Center(child: CircularProgressIndicator());
}
},
);
}
@override
void dispose() {
_scrollController
..removeListener(_onScroll)
..dispose();
super.dispose();
}
void _onScroll() {
if (_isBottom) context.read<RepoBloc>().add(RepoFetched());
}
bool get _isBottom {
if (!_scrollController.hasClients) return false;
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.offset;
return currentScroll >= (maxScroll * 0.9);
}
}
class BottomLoader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Center(
child: SizedBox(
height: 24,
width: 24,
child: CircularProgressIndicator(strokeWidth: 1.5),
),
);
}
}
class RepoListItem extends StatelessWidget {
const RepoListItem({Key? key, required this.post}) : super(key: key);
final Repository post;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Material(
child: ListTile(
leading: Text('${post.id}', style: textTheme.caption),
title: Text(post.name),
isThreeLine: true,
subtitle: Text(post.owner.username!),
dense: true,
),
);
}
}