From 0b246fe6d33dab8d6b96a277614a312aa8b0fda9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Tue, 7 May 2024 09:25:48 -0300 Subject: [PATCH] refactor: introduce datasource abstraction layer --- .../data/datasources/nasa_datasource.dart | 11 +++ .../datasources/remote_nasa_datasource.dart | 79 +++++++++++++++++++ .../repositories/remote_nasa_repository.dart | 68 ++-------------- lib/main.dart | 7 +- 4 files changed, 102 insertions(+), 63 deletions(-) create mode 100644 lib/features/picture_of_the_day/data/datasources/nasa_datasource.dart create mode 100644 lib/features/picture_of_the_day/data/datasources/remote_nasa_datasource.dart diff --git a/lib/features/picture_of_the_day/data/datasources/nasa_datasource.dart b/lib/features/picture_of_the_day/data/datasources/nasa_datasource.dart new file mode 100644 index 0000000..8818a86 --- /dev/null +++ b/lib/features/picture_of_the_day/data/datasources/nasa_datasource.dart @@ -0,0 +1,11 @@ +import 'package:nasa_potday/features/picture_of_the_day/domain/entities/pictures_page_entity.dart'; + +abstract interface class NasaDataSource { + Future loadPictureOfTheDay({ + required DateTime startDate, + }); + + Future loadNextPage({ + required DateTime currentStartDate, + }); +} diff --git a/lib/features/picture_of_the_day/data/datasources/remote_nasa_datasource.dart b/lib/features/picture_of_the_day/data/datasources/remote_nasa_datasource.dart new file mode 100644 index 0000000..9ffe016 --- /dev/null +++ b/lib/features/picture_of_the_day/data/datasources/remote_nasa_datasource.dart @@ -0,0 +1,79 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart'; +import 'package:nasa_potday/features/picture_of_the_day/data/datasources/nasa_datasource.dart'; +import 'package:nasa_potday/features/picture_of_the_day/data/models/load_picture_of_the_day_request_model.dart'; +import 'package:nasa_potday/features/picture_of_the_day/data/models/picture_model.dart'; +import 'package:nasa_potday/features/picture_of_the_day/domain/entities/pictures_page_entity.dart'; + +final class RemoteNasaDataSource implements NasaDataSource { + const RemoteNasaDataSource({ + required this.baseUrl, + required this.apiKey, + }); + + final String baseUrl; + final String apiKey; + + @override + Future loadPictureOfTheDay({ + required DateTime startDate, + }) async { + try { + final pictures = await _request( + LoadPictureOfTheDayRequestModel( + apiKey: apiKey, + startDate: startDate, + ), + ); + return PicturesPageEntity( + pictures: pictures, + startDate: startDate, + ); + } catch (error) { + debugPrint('Could not load picture of the day: $error'); + } + return PicturesPageEntity( + pictures: [], + startDate: startDate, + ); + } + + @override + Future loadNextPage({ + required DateTime currentStartDate, + }) async { + final newStartDate = currentStartDate.subtract(const Duration(days: 7)); + try { + final pictures = await _request( + LoadPictureOfTheDayRequestModel( + apiKey: apiKey, + startDate: newStartDate, + endDate: currentStartDate.subtract(const Duration(days: 1)), + ), + ); + return PicturesPageEntity(pictures: pictures, startDate: newStartDate); + } catch (error) { + debugPrint('Could not load picture of the day: $error'); + } + return PicturesPageEntity( + pictures: [], + startDate: newStartDate, + ); + } + + Future> _request( + LoadPictureOfTheDayRequestModel request) async { + final uri = Uri.parse(baseUrl).replace( + queryParameters: request.toJson(), + ); + final response = await get(uri); + return (jsonDecode(response.body) as List) + .cast>() + .map(PictureModel.fromJson) + .toList() + .reversed + .toList(); + } +} diff --git a/lib/features/picture_of_the_day/data/repositories/remote_nasa_repository.dart b/lib/features/picture_of_the_day/data/repositories/remote_nasa_repository.dart index fc337cb..2c90225 100644 --- a/lib/features/picture_of_the_day/data/repositories/remote_nasa_repository.dart +++ b/lib/features/picture_of_the_day/data/repositories/remote_nasa_repository.dart @@ -1,79 +1,25 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:http/http.dart'; -import 'package:nasa_potday/features/picture_of_the_day/data/models/load_picture_of_the_day_request_model.dart'; -import 'package:nasa_potday/features/picture_of_the_day/data/models/picture_model.dart'; +import 'package:nasa_potday/features/picture_of_the_day/data/datasources/remote_nasa_datasource.dart'; import 'package:nasa_potday/features/picture_of_the_day/domain/entities/pictures_page_entity.dart'; import 'package:nasa_potday/features/picture_of_the_day/domain/repositories/nasa_repository.dart'; class RemoteNasaRepository implements NasaRepository { RemoteNasaRepository({ - required this.baseUrl, - required this.apiKey, + required this.remoteDatasource, }); - final String baseUrl; - final String apiKey; + final RemoteNasaDataSource remoteDatasource; @override Future loadPictureOfTheDay({ required DateTime startDate, - }) async { - try { - final pictures = await _request( - LoadPictureOfTheDayRequestModel( - apiKey: apiKey, - startDate: startDate, - ), - ); - return PicturesPageEntity( - pictures: pictures, - startDate: startDate, - ); - } catch (error) { - debugPrint('Could not load picture of the day: $error'); - } - return PicturesPageEntity( - pictures: [], - startDate: startDate, - ); + }) { + return remoteDatasource.loadPictureOfTheDay(startDate: startDate); } @override Future loadNextPage({ required DateTime currentStartDate, - }) async { - final newStartDate = currentStartDate.subtract(const Duration(days: 7)); - try { - final pictures = await _request( - LoadPictureOfTheDayRequestModel( - apiKey: apiKey, - startDate: newStartDate, - endDate: currentStartDate.subtract(const Duration(days: 1)), - ), - ); - return PicturesPageEntity(pictures: pictures, startDate: newStartDate); - } catch (error) { - debugPrint('Could not load picture of the day: $error'); - } - return PicturesPageEntity( - pictures: [], - startDate: newStartDate, - ); - } - - Future> _request( - LoadPictureOfTheDayRequestModel request) async { - final uri = Uri.parse(baseUrl).replace( - queryParameters: request.toJson(), - ); - final response = await get(uri); - return (jsonDecode(response.body) as List) - .cast>() - .map(PictureModel.fromJson) - .toList() - .reversed - .toList(); + }) { + return remoteDatasource.loadNextPage(currentStartDate: currentStartDate); } } diff --git a/lib/main.dart b/lib/main.dart index 9ae4427..7aa2195 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nasa_potday/features/picture_of_the_day/data/datasources/remote_nasa_datasource.dart'; import 'package:nasa_potday/features/picture_of_the_day/data/repositories/remote_nasa_repository.dart'; import 'package:nasa_potday/features/picture_of_the_day/presentation/cubits/picture_of_the_day/picture_of_the_day_cubit.dart'; import 'package:nasa_potday/features/picture_of_the_day/presentation/pages/picture_of_the_day_page.dart'; @@ -22,8 +23,10 @@ class _MainAppState extends State { home: BlocProvider( create: (_) => PictureOfTheDayCubit( nasaRepository: RemoteNasaRepository( - baseUrl: const String.fromEnvironment('BASE_URL'), - apiKey: const String.fromEnvironment('API_KEY'), + remoteDatasource: const RemoteNasaDataSource( + baseUrl: String.fromEnvironment('BASE_URL'), + apiKey: String.fromEnvironment('API_KEY'), + ), ), ), child: const PictureOfTheDayPage(),