Skip to content

Commit

Permalink
feat: add pagination first page to work with static values
Browse files Browse the repository at this point in the history
  • Loading branch information
brunogabriel committed Oct 19, 2024
1 parent 0b839a5 commit 37b0350
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 3 deletions.
10 changes: 10 additions & 0 deletions pokedex/lib/app/di/injection.config.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion pokedex/lib/common/network/di/network_module.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:injectable/injectable.dart';

@module
Expand All @@ -13,5 +14,9 @@ abstract class NetworkModule {
) =>
Dio(
BaseOptions(baseUrl: baseUrl),
);
)..interceptors.add(
LogInterceptor(
logPrint: (element) => debugPrint(element.toString()),
),
);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';

import '../../../common/api/model/named_api_response.dart';
import '../domain/boundary/pokemon_list_repository.dart';
import '../domain/model/pokemon.dart';
import '../domain/model/pokemon_page_data.dart';

@Injectable(as: PokemonListRepository)
class PokemonListRepositoryImpl implements PokemonListRepository {
PokemonListRepositoryImpl({
required this.dio,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:pokedex/features/pokemon_list/presentation/bloc/pokemon_list_bloc.dart';
import 'package:pokedex/features/pokemon_list/presentation/widgets/pokemon_success.dart';

class PokemonListPage extends StatelessWidget {
const PokemonListPage({super.key});

@override
Widget build(BuildContext context) {
return const Scaffold(
body: Text('Pokemon List'),
return BlocProvider(
create: (_) => GetIt.instance.get<PokemonListBloc>()
..add(
const PokemonListEventRequest(),
),
child: Scaffold(
body: SafeArea(
child: BlocBuilder<PokemonListBloc, PokemonListState>(
builder: (context, state) {
final pageState = state.pageStatus;
if (state.firstPage) {
if (pageState == PageStatus.loading) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (pageState == PageStatus.failure) {
return const Text('Error');
} else if (pageState == PageStatus.initial) {
return const SizedBox.shrink();
}
}
return const PokemonSuccess();
},
),
),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pokedex/design/base/spacing.dart';
import 'package:pokedex/features/pokemon_list/presentation/bloc/pokemon_list_bloc.dart';
import 'package:pokedex/features/pokemon_list/presentation/widgets/pokemon_card.dart';

class PokemonSuccess extends StatefulWidget {
const PokemonSuccess({super.key});

@override
State<PokemonSuccess> createState() => _PokemonSuccessState();
}

class _PokemonSuccessState extends State<PokemonSuccess> {
final _scrollController = ScrollController();

@override
void initState() {
super.initState();
_scrollController.addListener(_onScrollListener);
}

@override
void dispose() {
_scrollController
..removeListener(_onScrollListener)
..dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
final state = context.watch<PokemonListBloc>().state;
final pageStatus = state.pageStatus;

return CustomScrollView(
controller: _scrollController,
slivers: [
const SliverAppBar(
snap: true,
floating: true,
pinned: true,
scrolledUnderElevation: 0,
expandedHeight: 120.0,
flexibleSpace: FlexibleSpaceBar(
centerTitle: false,
titlePadding: EdgeInsets.symmetric(horizontal: Spacing.kL),
title: Text('Hello World'),
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: Spacing.kL),
sliver: SliverList.separated(
separatorBuilder: (context, index) => const SizedBox(
height: Spacing.kM,
),
itemBuilder: (context, index) {
final pokemon = state.result[index];
return PokemonCard();
},
itemCount: state.result.length,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(_, __) {
final Widget tailWidget;
if (!state.firstPage && pageStatus == PageStatus.loading) {
tailWidget = const Padding(
padding: EdgeInsets.all(Spacing.kM),
child: Center(
child: CircularProgressIndicator(),
));
} else if (!state.firstPage && pageStatus == PageStatus.failure) {
tailWidget = Padding(
padding: const EdgeInsets.symmetric(
vertical: Spacing.kM, horizontal: Spacing.kL),
child: Column(
children: [
Text('Error title'),
],
),
);
} else {
tailWidget = const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.symmetric(vertical: Spacing.kXL),
child: tailWidget,
);
},
childCount: 1,
),
)
],
);
}

void _onScrollListener() {
if (_isBottomReached) {
// request other
}
}

bool get _isBottomReached {
if (!_scrollController.hasClients) {
return false;
}
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.offset;
return currentScroll >= (maxScroll * 0.9);
}
}

0 comments on commit 37b0350

Please sign in to comment.