Skip to content

Feature Searching News #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion lib/feature/data/datasource/news/news_remote_data_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import 'package:flutter_news_app/feature/data/model/topheadlinesnews/top_headlin
import 'package:meta/meta.dart';

abstract class NewsRemoteDataSource {
/// Calls the baseUrl:/v2/top-headlines?category=:category&country=:country&apiKey=:apiKey endpoint
/// Calls the [baseUrl]/v2/top-headlines?category=:category&country=:country&apiKey=:apiKey endpoint
///
/// Throws a [DioError] for all error codes.
Future<TopHeadlinesNewsResponseModel> getTopHeadlinesNews(String category);

/// Calls the [baseUrl]/v2/top-headlines?country=:country&apiKey=:apiKey&q=:q
///
/// Throws a [DioError] for all error codes.
Future<TopHeadlinesNewsResponseModel> searchTopHeadlinesNews(String keyword);
}

class NewsRemoteDataSourceImpl implements NewsRemoteDataSource {
Expand Down Expand Up @@ -46,4 +51,21 @@ class NewsRemoteDataSourceImpl implements NewsRemoteDataSource {
throw DioError();
}
}

@override
Future<TopHeadlinesNewsResponseModel> searchTopHeadlinesNews(String keyword) async {
var response = await dio.get(
'/v2/top-headlines',
queryParameters: {
'country': 'id',
'apiKey': constantConfig.apiKeyNewsApi,
'q': keyword,
},
);
if (response.statusCode == 200) {
return TopHeadlinesNewsResponseModel.fromJson(response.data);
} else {
throw DioError();
}
}
}
15 changes: 15 additions & 0 deletions lib/feature/data/repository/news/news_repository_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,19 @@ class NewsRepositoryImpl implements NewsRepository {
return Left(ConnectionFailure());
}
}

@override
Future<Either<Failure, TopHeadlinesNewsResponseModel>> searchTopHeadlinesNews(String keyword) async {
var isConnected = await networkInfo.isConnected;
if (isConnected) {
try {
var response = await newsRemoteDataSource.searchTopHeadlinesNews(keyword);
return Right(response);
} on DioError catch (error) {
return Left(ServerFailure(error.message));
}
} else {
return Left(ConnectionFailure());
}
}
}
1 change: 1 addition & 0 deletions lib/feature/domain/repository/news/news_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ abstract class NewsRepository {

Future<Either<Failure, TopHeadlinesNewsResponseModel>> getTopHeadlinesNews(String category);

Future<Either<Failure, TopHeadlinesNewsResponseModel>> searchTopHeadlinesNews(String keyword);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_news_app/core/error/failure.dart';
import 'package:flutter_news_app/feature/domain/repository/news/news_repository.dart';
import 'package:meta/meta.dart';
import 'package:flutter_news_app/core/usecase/usecase.dart';
import 'package:flutter_news_app/feature/data/model/topheadlinesnews/top_headlines_news_response_model.dart';

class SearchTopHeadlinesNews implements UseCase<TopHeadlinesNewsResponseModel, ParamsSearchTopHeadlinesNews> {
final NewsRepository newsRepository;

SearchTopHeadlinesNews({@required this.newsRepository});

@override
Future<Either<Failure, TopHeadlinesNewsResponseModel>> call(ParamsSearchTopHeadlinesNews params) async {
return await newsRepository.searchTopHeadlinesNews(params.keyword);
}
}

class ParamsSearchTopHeadlinesNews extends Equatable {
final String keyword;

ParamsSearchTopHeadlinesNews({@required this.keyword});

@override
List<Object> get props => [keyword];

@override
String toString() {
return 'ParamsSearchTopHeadlinesNews{keyword: $keyword}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter_news_app/core/error/failure.dart';
import 'package:flutter_news_app/feature/domain/usecase/gettopheadlinesnews/get_top_headlines_news.dart';
import 'package:flutter_news_app/feature/domain/usecase/searchtopheadlinesnews/search_top_headlines_news.dart';
import 'package:meta/meta.dart';

import './bloc.dart';

class TopHeadlinesNewsBloc extends Bloc<TopHeadlinesNewsEvent, TopHeadlinesNewsState> {
final GetTopHeadlinesNews getTopHeadlinesNews;
final SearchTopHeadlinesNews searchTopHeadlinesNews;

TopHeadlinesNewsBloc({@required this.getTopHeadlinesNews}) : assert(getTopHeadlinesNews != null);
TopHeadlinesNewsBloc({
@required this.getTopHeadlinesNews,
@required this.searchTopHeadlinesNews,
}) : assert(getTopHeadlinesNews != null),
assert(searchTopHeadlinesNews != null);

@override
TopHeadlinesNewsState get initialState => InitialTopHeadlinesNewsState();
Expand All @@ -23,6 +29,8 @@ class TopHeadlinesNewsBloc extends Bloc<TopHeadlinesNewsEvent, TopHeadlinesNewsS
yield* _mapLoadTopHeadlinesNewsEventToState(event);
} else if (event is ChangeCategoryTopHeadlinesNewsEvent) {
yield* _mapChangeCategoryTopHeadlinesNewsEventToState(event);
} else if (event is SearchTopHeadlinesNewsEvent) {
yield* _mapSearchTopHeadlinesNewsEventToState(event);
}
}

Expand All @@ -47,4 +55,20 @@ class TopHeadlinesNewsBloc extends Bloc<TopHeadlinesNewsEvent, TopHeadlinesNewsS
) async* {
yield ChangedCategoryTopHeadlinesNewsState(indexCategorySelected: event.indexCategorySelected);
}

Stream<TopHeadlinesNewsState> _mapSearchTopHeadlinesNewsEventToState(SearchTopHeadlinesNewsEvent event) async* {
yield LoadingTopHeadlinesNewsState();
var result = await searchTopHeadlinesNews(ParamsSearchTopHeadlinesNews(keyword: event.keyword));
yield result.fold(
// ignore: missing_return
(failure) {
if (failure is ServerFailure) {
return FailureTopHeadlinesNewsState(errorMessage: failure.errorMessage);
} else if (failure is ConnectionFailure) {
return FailureTopHeadlinesNewsState(errorMessage: failure.errorMessage);
}
},
(response) => SearchSuccessTopHeadlinesNewsState(listArticles: response.articles),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,18 @@ class ChangeCategoryTopHeadlinesNewsEvent extends TopHeadlinesNewsEvent {
String toString() {
return 'ChangeCategoryTopHeadlinesNewsEvent{indexCategorySelected: $indexCategorySelected}';
}
}

class SearchTopHeadlinesNewsEvent extends TopHeadlinesNewsEvent {
final String keyword;

SearchTopHeadlinesNewsEvent({@required this.keyword});

@override
List<Object> get props => [keyword];

@override
String toString() {
return 'SearchTopHeadlinesNewsEvent{keyword: $keyword}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,18 @@ class ChangedCategoryTopHeadlinesNewsState extends TopHeadlinesNewsState {
String toString() {
return 'ChangedCategoryTopHeadlinesNewsState{indexCategorySelected: $indexCategorySelected}';
}
}

class SearchSuccessTopHeadlinesNewsState extends TopHeadlinesNewsState {
final List<ItemArticleTopHeadlinesNewsResponseModel> listArticles;

SearchSuccessTopHeadlinesNewsState({this.listArticles});

@override
List<Object> get props => [listArticles];

@override
String toString() {
return 'SearchSuccessTopHeadlinesNewsState{listArticles: $listArticles}';
}
}
Loading