Skip to content

Commit

Permalink
Ussd Codes Datasources
Browse files Browse the repository at this point in the history
  • Loading branch information
Luis Ciber committed Aug 21, 2021
1 parent 344e1a2 commit 6ca1357
Show file tree
Hide file tree
Showing 36 changed files with 596 additions and 9 deletions.
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ icon:
rm -r android/app/src/development/res
rm -r android/app/src/staging/res
cp -r android/app/src/main/res android/app/src/development
cp -r android/app/src/main/res android/app/src/staging
cp -r android/app/src/main/res android/app/src/staging

.PHONY: tree
tree:
rm file_structure.txt
tree lib/ > file_structure.txt
2 changes: 2 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ include: package:very_good_analysis/analysis_options.2.3.0.yaml
linter:
rules:
public_member_api_docs: false
constant_identifier_names: false
unawaited_futures: false

analyzer:
strong-mode:
Expand Down
Binary file added assets/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions file_structure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
lib/
├── app
│   ├── app_bloc_observer.dart
│   ├── app.dart
│   ├── app_router.dart
│   ├── bloc
│   │   ├── bloc.dart
│   │   └── theme
│   │   ├── theme_bloc.dart
│   │   ├── theme_bloc.freezed.dart
│   │   ├── theme_event.dart
│   │   └── theme_state.dart
│   ├── data
│   │   ├── core
│   │   │   ├── core.dart
│   │   │   └── exceptions
│   │   │   └── exceptions.dart
│   │   ├── data.dart
│   │   ├── datasources
│   │   │   └── datasources.dart
│   │   ├── models
│   │   │   ├── models.dart
│   │   │   └── ussd
│   │   │   ├── category
│   │   │   │   ├── ussd_category.dart
│   │   │   │   └── ussd_category.g.dart
│   │   │   ├── code
│   │   │   │   ├── ussd_code.dart
│   │   │   │   └── ussd_code.g.dart
│   │   │   ├── code_field
│   │   │   │   ├── ussd_code_field.dart
│   │   │   │   └── ussd_code_field.g.dart
│   │   │   ├── ussd.dart
│   │   │   └── ussd_item.dart
│   │   └── repositories
│   │   └── repositories.dart
│   ├── dependencies
│   │   ├── dependencies.config.dart
│   │   └── dependencies.dart
│   ├── theme
│   │   ├── app_bar_theme.dart
│   │   ├── dark.dart
│   │   ├── light.dart
│   │   └── theme.dart
│   └── widgets
│   ├── loading.dart
│   └── widgets.dart
├── gen
│   └── assets.gen.dart
├── generated_plugin_registrant.dart
├── home
│   ├── home.dart
│   ├── router
│   │   ├── home_location.dart
│   │   ├── home_page.dart
│   │   └── router.dart
│   ├── view
│   │   ├── home_view.dart
│   │   └── view.dart
│   └── widgets
│   └── widgets.dart
├── l10n
│   ├── arb
│   │   ├── app_en.arb
│   │   └── app_es.arb
│   └── l10n.dart
├── main_development.dart
├── main_production.dart
└── main_staging.dart

23 directories, 45 files
1 change: 1 addition & 0 deletions lib/app/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:todo/app/dependencies/dependencies.dart';
import 'package:todo/app/theme/theme.dart';
import 'package:todo/app/widgets/widgets.dart';

export 'app_environment.dart';
export 'bloc/bloc.dart';
export 'data/data.dart';
export 'dependencies/dependencies.dart';
Expand Down
33 changes: 33 additions & 0 deletions lib/app/app_environment.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:injectable/injectable.dart';

abstract class AppEnvironment {
const AppEnvironment({
required this.ussdCodesRemote,
required this.ussdCodesHashRemote,
});

final String ussdCodesRemote;
final String ussdCodesHashRemote;
}

@prod
@Injectable(as: AppEnvironment)
class AppEnvironmentProd extends AppEnvironment {
AppEnvironmentProd()
: super(
ussdCodesHashRemote:
'https://todo-devs.github.io/todo-json/config.json',
ussdCodesRemote: 'https://todo-devs.github.io/todo-json/hash.json',
);
}

@dev
@Injectable(as: AppEnvironment)
class AppEnvironmentDev extends AppEnvironment {
AppEnvironmentDev()
: super(
ussdCodesHashRemote:
'https://todo-devs.github.io/todo-json/config.json',
ussdCodesRemote: 'https://todo-devs.github.io/todo-json/hash.json',
);
}
3 changes: 3 additions & 0 deletions lib/app/data/core/core.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'exceptions/exceptions.dart';
export 'platform/platform.dart';
export 'utils/utils.dart';
17 changes: 17 additions & 0 deletions lib/app/data/core/exceptions/exceptions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class ParseUssdCodeException implements Exception {
const ParseUssdCodeException({
required this.message,
this.map,
});

final String message;
final Map<String, dynamic>? map;
}

class UssdCodesCacheException implements Exception {}

class UssdCodesServerException implements Exception {
const UssdCodesServerException(this.message);

final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import 'package:dio/adapter_browser.dart';

BrowserHttpClientAdapter httpAdapter() => BrowserHttpClientAdapter();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import 'package:dio/adapter.dart';

DefaultHttpClientAdapter httpAdapter() => DefaultHttpClientAdapter();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import 'package:dio/dio.dart';

HttpClientAdapter httpAdapter() => throw UnsupportedError('');
21 changes: 21 additions & 0 deletions lib/app/data/core/platform/http_client/http_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';

// ignore: always_use_package_imports
import 'adapters/http_stub_adapter.dart'
if (dart.library.html) 'adapters/http_browser_adapter.dart'
if (dart.library.io) 'adapters/http_native_adapter.dart';

@injectable
class HttpClient with DioMixin implements Dio {
HttpClient() {
options = BaseOptions(
headers: {
'Accept-Encoding': 'gzip, deflate, br',
'Content-Type': 'application/json',
},
);

httpClientAdapter = httpAdapter();
}
}
1 change: 1 addition & 0 deletions lib/app/data/core/platform/platform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'http_client/http_client.dart';
13 changes: 13 additions & 0 deletions lib/app/data/core/utils/parse_json.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'dart:convert';

import 'package:flutter/foundation.dart';

Future<Map<String, dynamic>> parseJson(String text) {
return compute(_parseAndDecode, text);
}

Map<String, dynamic> _parseAndDecode(String response) {
return json.decode(
response,
) as Map<String, dynamic>;
}
1 change: 1 addition & 0 deletions lib/app/data/core/utils/utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'parse_json.dart';
5 changes: 4 additions & 1 deletion lib/app/data/data.dart
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@

export 'core/core.dart';
export 'datasources/datasources.dart';
export 'models/models.dart';
export 'repositories/repositories.dart';
1 change: 1 addition & 0 deletions lib/app/data/datasources/datasources.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'ussd/ussd.dart';
3 changes: 3 additions & 0 deletions lib/app/data/datasources/ussd/ussd.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'ussd_assets_datasource.dart';
export 'ussd_local_datasource.dart';
export 'ussd_remote_datasource.dart';
27 changes: 27 additions & 0 deletions lib/app/data/datasources/ussd/ussd_assets_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'dart:developer';

import 'package:flutter/services.dart';
import 'package:injectable/injectable.dart';
import 'package:todo/app/app.dart';
import 'package:todo/gen/assets.gen.dart';

@injectable
class UssdAssetsDatasource {
Future<List<UssdItem>> getUssdCodes() async {
try {
final data = await rootBundle.loadString(Assets.config.ussdCodes);

final parsedJson = await parseJson(data);

parsedJson['name'] = '';
parsedJson['description'] = '';
parsedJson['icon'] = '';
parsedJson['type'] = 'category';

return UssdCategory.fromJson(parsedJson).items;
} on Exception catch (e) {
log(e.toString());
rethrow;
}
}
}
50 changes: 50 additions & 0 deletions lib/app/data/datasources/ussd/ussd_local_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'dart:convert';

import 'package:injectable/injectable.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:todo/app/app.dart';

const USSD_CODES_KEY = 'config';
const USSD_CODES_HASH = 'hash';

@injectable
class UssdLocalDatasource {
const UssdLocalDatasource(this._storage);

final SharedPreferences _storage;

Future<List<UssdItem>> getUssdCodes() async {
final jsonString = _storage.getString(USSD_CODES_KEY);

if (jsonString != null) {
final parsedJson = await parseJson(jsonString);

parsedJson['name'] = '';
parsedJson['description'] = '';
parsedJson['icon'] = '';
parsedJson['type'] = 'category';

return UssdCategory.fromJson(parsedJson).items;
} else {
throw UssdCodesCacheException();
}
}

Future<String?> getHash() async {
return _storage.getString(USSD_CODES_HASH);
}

Future<void> saveUssdCodes(List<UssdItem> items, String hash) async {
final data = json.encode({
'items': items.map((e) {
if (e.type == 'code') {
return (e as UssdCode).toJson();
} else if (e.type == 'category') {
return (e as UssdCategory).toJson();
}
}).toList()
});

_storage..setString(USSD_CODES_KEY, data)..setString(USSD_CODES_HASH, hash);
}
}
50 changes: 50 additions & 0 deletions lib/app/data/datasources/ussd/ussd_remote_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'dart:convert';

import 'package:injectable/injectable.dart';
import 'package:todo/app/app.dart';

@injectable
class UssdRemoteDatasource {
const UssdRemoteDatasource(
this._environment,
this._http,
);

final AppEnvironment _environment;
final HttpClient _http;

Future<String> getHash() async {
return _getData(_environment.ussdCodesHashRemote);
}

Future<List<UssdItem>> getUssdCodes() async {
final jsonString = await _getData(_environment.ussdCodesRemote);
final parsedJson = json.decode(jsonString) as Map<String, dynamic>;

parsedJson['name'] = '';
parsedJson['description'] = '';
parsedJson['icon'] = '';
parsedJson['type'] = 'category';

return UssdCategory.fromJson(parsedJson).items;
}

Future<String> _getData(String url) {
return _http.get<Map<String, dynamic>>(url).then(
(response) {
if (response.statusCode == 200) {
return json.encode(response.data);
} else {
throw UssdCodesServerException(
'Request failed: ${response.realUri}\n'
'StatusCode: ${response.statusCode}\n'
'Body: ${response.data}',
);
}
},
).timeout(
const Duration(seconds: 5),
onTimeout: () => throw const UssdCodesServerException('Request timeout'),
);
}
}
1 change: 1 addition & 0 deletions lib/app/data/models/models.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'ussd/ussd.dart';
Loading

0 comments on commit 6ca1357

Please sign in to comment.