Skip to content

Commit

Permalink
Release 1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
tortamque committed Aug 25, 2023
2 parents 1cdabc5 + a2887ef commit c942941
Show file tree
Hide file tree
Showing 31 changed files with 953 additions and 92 deletions.
3 changes: 3 additions & 0 deletions lib/config/theme/app_themes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ import 'package:flutter/material.dart';
ThemeData theme(){
return ThemeData(
useMaterial3: true,
textSelectionTheme: TextSelectionThemeData(
selectionHandleColor: Colors.black
)
);
}
32 changes: 31 additions & 1 deletion lib/core/dependency_injection.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import 'package:get_it/get_it.dart';
// ignore: depend_on_referenced_packages
import 'package:dio/dio.dart';
import 'package:weathque/features/app/data/data_sources/local/storage.dart';
import 'package:weathque/features/app/data/data_sources/remote/api_service.dart';
import 'package:weathque/features/app/data/repository/storage_repository_implementation.dart';
import 'package:weathque/features/app/data/repository/weather_repository_implementation.dart';
import 'package:weathque/features/app/domain/entities/summary_builder.dart';
import 'package:weathque/features/app/domain/repository/weather_repository.dart';
import 'package:weathque/features/app/domain/usecases/delete_city.dart';
import 'package:weathque/features/app/domain/usecases/get_cities.dart';
import 'package:weathque/features/app/domain/usecases/get_colors.dart';
import 'package:weathque/features/app/domain/usecases/get_current_weather.dart';
import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart';
import 'package:weathque/features/app/domain/usecases/save_city.dart';
import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart';
import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart';
import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart';

Expand All @@ -24,13 +31,19 @@ Future<void> initializeDependencies() async {
ForecastWeatherApiService(locator())
);

// Storage
locator.registerSingleton<StorageImplementation>(StorageImplementation());

// Repo
locator.registerSingleton<WeatherRepository>(
WeatherRepositoryImplementation(locator())
);
locator.registerSingleton<ForecastWeatherRepository>(
ForecastWeatherRepositoryImplementation(locator())
);
locator.registerSingleton<StorageRepositoryImplementation>(
StorageRepositoryImplementation(locator<StorageImplementation>())
);

// Use cases
locator.registerSingleton<GetCurrentWeatherUseCase>(
Expand All @@ -39,6 +52,18 @@ Future<void> initializeDependencies() async {
locator.registerSingleton<GetWeatherForecastUseCase>(
GetWeatherForecastUseCase(locator())
);
locator.registerSingleton<SaveCityUseCaseImplementation>(
SaveCityUseCaseImplementation(locator<StorageRepositoryImplementation>())
);
locator.registerSingleton<GetCitiesUseCaseImplementation>(
GetCitiesUseCaseImplementation(locator<StorageRepositoryImplementation>())
);
locator.registerSingleton<DeleteCityUseCaseImplementation>(
DeleteCityUseCaseImplementation(locator<StorageRepositoryImplementation>())
);
locator.registerSingleton<GetColorsUseCaseImplementation>(
GetColorsUseCaseImplementation(locator<StorageRepositoryImplementation>())
);

// Blocs
locator.registerFactory<GetCurrentWeatherBloc>(
Expand All @@ -48,6 +73,11 @@ Future<void> initializeDependencies() async {
() => GetWeatherForecastBloc(locator())
);

//Entities
// Cubit
locator.registerFactory<CitiesChangedCubit>(
() => CitiesChangedCubit()
);

// Entities
locator.registerSingleton(SummaryBuilder());
}
16 changes: 16 additions & 0 deletions lib/core/usecases/usecase.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
abstract class UseCase<Type, String>{
Future<Type> call({required String cityName});
}

abstract class SaveCityUseCase{
Future<bool> call({required String cityName, required String colorValue});
}

abstract class GetCitiesUseCase{
List<String> call();
}

abstract class GetColorsUseCase{
List<String> call();
}

abstract class DeleteCityUseCase{
Future<void> call(String cityName);
}
86 changes: 86 additions & 0 deletions lib/features/app/data/data_sources/local/storage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'package:shared_preferences/shared_preferences.dart';

abstract class Storage {
SharedPreferences? prefs;
Future<bool> saveCity(String cityName, String colorValue);
List<String> getCities();
List<String> getColors();
Future<void> deleteCity(String cityName);
}

class StorageImplementation implements Storage{
SharedPreferences? prefs;

StorageImplementation(){
_initPrefs();
}

Future<void> _initPrefs() async {
prefs = await SharedPreferences.getInstance();
await _fillEmptyStorage();
}

Future<void> ensurePrefsInitialized() async {
if (prefs == null) {
await _initPrefs();
}
}

Future<void> _fillEmptyStorage() async{
List<String> defaultCities = ["Paris", "New York", "Sydney"];
List<String> defaultColors = ["4294959426", "4282566399", "4294927572"];

List<String> cities = getCities();
List<String> colors = getColors();

if(cities.length == 0 || colors.length == 0){
await prefs!.setStringList('cities', defaultCities);
await prefs!.setStringList('colors', defaultColors);
}
}

@override
Future<bool> saveCity(String cityName, String colorValue) async {
final List<String> cities = getCities();
final List<String> colors = getColors();

if(!cities.contains(cityName)){
cities.add(cityName);
colors.add(colorValue);
await prefs!.setStringList('cities', cities);
await prefs!.setStringList('colors', colors);

return true;
}

return false;
}

@override
List<String> getCities() {
final List<String> cities = prefs!.getStringList('cities') ?? [];

return cities;
}

List<String> getColors(){
final List<String> colors = prefs!.getStringList('colors') ?? [];

return colors;
}

@override
Future<void> deleteCity(String cityName) async {
List<String> cities = getCities();
List<String> colors = getColors();
int colorIndex = cities.indexWhere((element) => element == cityName);

cities.remove(cityName);
colors.removeAt(colorIndex);

await prefs!.remove('cities');
await prefs!.remove('colors');
await prefs!.setStringList('cities', cities);
await prefs!.setStringList('colors', colors);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:weathque/features/app/data/data_sources/local/storage.dart';
import 'package:weathque/features/app/domain/repository/storage_repository.dart';

class StorageRepositoryImplementation implements StorageRepository{
final Storage _storage;

StorageRepositoryImplementation(this._storage);

@override
Future<bool> saveCity(String cityName, String colorValue) async{
return await _storage.saveCity(cityName, colorValue);
}

@override
List<String> getCities() {
return _storage.getCities();
}

@override
List<String> getColors() {
return _storage.getColors();
}

@override
Future<void> deleteCity(String cityName) async {
await _storage.deleteCity(cityName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,6 @@ class Coord {
Coord({required this.lat, required this.lon});

factory Coord.fromJson(Map<String, dynamic> json) {
return Coord(lat: json['lat'], lon: json['lon']);
return Coord(lat: json['lat'].toDouble(), lon: json['lon'].toDouble());
}
}
6 changes: 6 additions & 0 deletions lib/features/app/domain/repository/storage_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
abstract class StorageRepository{
Future<bool> saveCity(String cityName, String colorValue);
List<String> getCities();
List<String> getColors();
Future<void> deleteCity(String cityName);
}
13 changes: 13 additions & 0 deletions lib/features/app/domain/usecases/delete_city.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:weathque/core/usecases/usecase.dart';
import 'package:weathque/features/app/domain/repository/storage_repository.dart';

class DeleteCityUseCaseImplementation implements DeleteCityUseCase{
final StorageRepository _storage;

DeleteCityUseCaseImplementation(this._storage);

@override
Future<void> call(String cityName) {
return _storage.deleteCity(cityName);
}
}
13 changes: 13 additions & 0 deletions lib/features/app/domain/usecases/get_cities.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:weathque/core/usecases/usecase.dart';
import 'package:weathque/features/app/domain/repository/storage_repository.dart';

class GetCitiesUseCaseImplementation implements GetCitiesUseCase{
final StorageRepository _storage;

GetCitiesUseCaseImplementation(this._storage);

@override
List<String> call() {
return _storage.getCities();
}
}
13 changes: 13 additions & 0 deletions lib/features/app/domain/usecases/get_colors.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:weathque/core/usecases/usecase.dart';
import 'package:weathque/features/app/domain/repository/storage_repository.dart';

class GetColorsUseCaseImplementation implements GetColorsUseCase{
final StorageRepository _storage;

GetColorsUseCaseImplementation(this._storage);

@override
List<String> call() {
return _storage.getColors();
}
}
13 changes: 13 additions & 0 deletions lib/features/app/domain/usecases/save_city.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:weathque/core/usecases/usecase.dart';
import 'package:weathque/features/app/domain/repository/storage_repository.dart';

class SaveCityUseCaseImplementation implements SaveCityUseCase{
final StorageRepository _storage;

SaveCityUseCaseImplementation(this._storage);

@override
Future<bool> call({required String cityName, required String colorValue}) {
return _storage.saveCity(cityName, colorValue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:weathque/core/dependency_injection.dart';
import 'package:weathque/features/app/domain/usecases/get_cities.dart';

class CitiesChangedCubit extends Cubit<List<String>>{
CitiesChangedCubit() : super(locator<GetCitiesUseCaseImplementation>()());

void call(){
emit(locator<GetCitiesUseCaseImplementation>()());
}
}
31 changes: 31 additions & 0 deletions lib/features/app/presentation/bloc/blocs_provider_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:weathque/core/dependency_injection.dart';
import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart';
import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart';
import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart';
import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart';
import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart';

class BlocsProviderBuilder extends StatelessWidget {
final Widget child;
final BuildContext context;
final List<BlocProvider> providers = [
BlocProvider<GetCurrentWeatherBloc>(
create: (buildContext) => locator()..add(const GetCurrentWeather())
),
BlocProvider<GetWeatherForecastBloc>(
create: (buildContext) => locator()..add(const GetWeatherForecast()),
),
BlocProvider<CitiesChangedCubit>(
create: (buildContext) => locator<CitiesChangedCubit>(),
)
];

BlocsProviderBuilder({super.key, required this.child, required this.context});

@override
Widget build(BuildContext context) {
return MultiBlocProvider(providers: providers, child: child);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:weathque/features/app/domain/entities/cities_enum.dart';
import 'package:weathque/core/dependency_injection.dart';
import 'package:weathque/features/app/domain/entities/weather_entity.dart';
import 'package:weathque/features/app/domain/usecases/get_cities.dart';
import 'package:weathque/features/app/domain/usecases/get_current_weather.dart';
import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart';
import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_state.dart';
Expand All @@ -13,13 +14,16 @@ class GetCurrentWeatherBloc extends Bloc<GetCurrentWeatherEvent, GetCurrentWeath
}

void onGetCurrentWeather(GetCurrentWeather event, Emitter<GetCurrentWeatherState> emitter) async{
List<City> cities = City.values;
// ignore: invalid_use_of_visible_for_testing_member
emit(const GetCurrentWeatherLoading());

List<String> cities = locator<GetCitiesUseCaseImplementation>()();
Map<String, WeatherEntity> entities = {};

for (var city in cities) {
final dataState = await _getCurrentWeatherUseCase.call(cityName: city.string);
final dataState = await _getCurrentWeatherUseCase.call(cityName: city);

entities[city.string] = dataState;
entities[city] = dataState;
}

// ignore: invalid_use_of_visible_for_testing_member
Expand Down
Loading

0 comments on commit c942941

Please sign in to comment.