Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juuaaann456/DMI-Practica06/llms.txt

Use this file to discover all available pages before exploring further.

Cinemapedia displays movies in five distinct categories, each backed by a dedicated Riverpod provider and a separate TheMovieDB API endpoint. All categories share the same MoviesNotifier class and support infinite scroll pagination.

Categories overview

En cines

Movies currently playing in theaters. Uses the /movie/now_playing endpoint. Provider: nowPlayingMoviesProvider.

Próximamente

Upcoming releases. Uses the /movie/upcoming endpoint. Provider: upcomingMoviesProvider.

Populares

Most popular movies right now. Uses the /movie/popular endpoint. Provider: popularMoviesProvider.

Mejor valoradas

Highest rated movies of all time. Uses the /movie/top_rated endpoint. Provider: topratedMoviesProvider.

Cine Mexicano

Mexican cinema, sorted by rating. Uses the /discover/movie endpoint with region=MX and with_origin_country=MX. Provider: mexicanMoviesProvider.

Category reference table

Display nameProviderTheMovieDB endpointNotes
En cinesnowPlayingMoviesProviderGET /movie/now_playingAlso drives the MovieSlideshow (first 6 results)
PróximamenteupcomingMoviesProviderGET /movie/upcoming
PopularespopularMoviesProviderGET /movie/popular
Mejor valoradastopratedMoviesProviderGET /movie/top_rated
Cine MexicanomexicanMoviesProviderGET /discover/movieFiltered by region=MX, with_origin_country=MX, sorted by vote_average.desc, minimum 10 votes

API datasource

All HTTP requests are made by MoviedbDataSource using the dio package. The base URL is https://api.themoviedb.org/3 with language=es-MX applied globally.

Standard categories

For Now Playing, Popular, Upcoming, and Top Rated, the pattern is identical — only the path differs:
@override
Future<List<Movie>> getNowPlaying({int page = 1}) async {
  final response = await dio.get(
    '/movie/now_playing',
    queryParameters: {'page': page},
  );

  final movieDBResponse = MovieDbResponse.fromJson(response.data);

  final List<Movie> movies = movieDBResponse.results
      .where((moviedb) => moviedb.posterPath != 'no-poster')
      .map((moviedb) => MovieMapper.movieDBToEntity(moviedb))
      .toList();

  return movies;
}
Movies without a poster image are filtered out before the list is returned. This prevents broken image widgets in the UI.

Mexican Cinema

The getMexicanMovies method uses the /discover/movie endpoint with additional query parameters:
@override
Future<List<Movie>> getMexicanMovies({int page = 1}) async {
  final response = await dio.get(
    '/discover/movie',
    queryParameters: {
      'page': page,
      'region': 'MX',
      'withOriginalLanguaje': 'es',
      'with_origin_country': 'MX',
      'sort_by': 'vote_average.desc',
      'vote_count.gte': 10,
    },
  );
  // ...
}

Providers

Each category has its own NotifierProvider<MoviesNotifier, List<Movie>>. All five providers are defined in movies_providers.dart and follow the same pattern:
final nowPlayingMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier(
    (ref) => ref.watch(movieRepositoryProvider).getNowPlaying,
  ),
);

final popularMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier(
    (ref) => ref.watch(movieRepositoryProvider).getPopular,
  ),
);

final upcomingMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier(
    (ref) => ref.watch(movieRepositoryProvider).getUpcoming,
  ),
);

final topratedMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier(
    (ref) => ref.watch(movieRepositoryProvider).getTopRated,
  ),
);

final mexicanMoviesProvider = NotifierProvider<MoviesNotifier, List<Movie>>(
  () => MoviesNotifier(
    (ref) => ref.watch(movieRepositoryProvider).getMexicanMovies,
  ),
);
Each provider receives a builder function that returns the appropriate repository method. This makes MoviesNotifier reusable across all five categories.

Infinite pagination

Pagination is handled entirely by MoviesNotifier. Calling loadNextPage() increments an internal page counter and appends the new results to the existing state list.
class MoviesNotifier extends Notifier<List<Movie>> {
  int currentPage = 0;
  bool isLoading = false;

  Future<void> loadNextPage() async {
    if (isLoading) return;
    isLoading = true;

    currentPage++;
    final movies = await fetchMoreMovies(page: currentPage);

    state = [...state, ...movies];

    isLoading = false;
  }
}
The isLoading guard prevents duplicate requests if loadNextPage() is called again before the previous one completes — for example, when the user rapidly scrolls to the end of a list.

Scroll-triggered loading

MovieHorizontalListview attaches a ScrollController listener that calls loadNextPage() when the scroll position is within 200 pixels of the end of the list:
scrollController.addListener(() {
  if (widget.loadNextPage == null) return;
  if (scrollController.position.pixels + 200 >=
      scrollController.position.maxScrollExtent) {
    widget.loadNextPage!();
  }
});
This callback is wired up in HomeScreen for each category:
MovieHorizontalListview(
  movies: nowPlayingMovies,
  title: 'En cines',
  subTitle: 'Lunes 27 de Octubre',
  loadNextPage: () =>
      ref.read(nowPlayingMoviesProvider.notifier).loadNextPage(),
),

Build docs developers (and LLMs) love