Sequence
Music Recognition app using Audd's Music recognition API
Content
π§ Getting Started π§
ποΈ Construction is underway, there may be a lot of elements missing in this README
App Demo:
Running the app
Couple steps are required to run this app on your local machine.
First, get an API Token from Audd by following this link.
Step 1
An API Token is required to run the app. This API Token is retrieved from environment variables read throught dart define. You'll need to provide is as well as the api base url:
$ flutter run --dart-define apiBaseUrl=https://api.audd.io --dart-define AUDD_API_TOKEN=<YOUR_API_TOKEN>
Step 2
Install dependencies:
$ flutter pub get
Step 3
Run code generation:
$ flutter pub run build_runner build --delete-conflicting-outputs
Architecture and Folder Structure
This project uses the BLoC Architecture. Learn more on https://bloclibrary.dev
Data layer
This layer is responsible of manipulating data from one or more sources
Api Controllers
Are responsible for API calls. They all extend the BaseApiController
class. Are not responsible for data processing.
class UserApiController extends BaseApiController {
UserApiController({required super.dio});
Future<Response<Json>> recognize({
required Request request,
CancelToken? cancelToken,
}) async {
try {
final Response<Json> response = await dio.post('/endpoint', data: await request.toJson());
return response;
} on DioError catch (_) {
rethrow;
}
}
}
Repositories
They can aggregate multiple data sources (eg. Multiple API Controllers). They all extend be BaseRepository
class which contains the runApiCall
method that has necessary logi cfor errors handling.
class TestRepository extends BaseRepository {
final MyApiController _myApiController;
final MySecondApiController _mySecondApiController;
TestRepository({
MyApiController? myApiController,
MySecondApiController? mySecondApiController,
}) : _myApiController = myApiController ?? locator<MyApiController>(),
_mySecondApiController = mySecondApiController ?? locator<MySecondApiController>();
Future<NetworkResponse<TestResponse, CustomHttpException>> test(MyRequest request) async {
return runApiCall<TestResponse>(
call: () async {
final response = await _myApiController.test(request: request);
return NetworkResponse.success(TestResponse.fromJson(response.data!));
},
);
}
}
Business logic layer
The business logic layer's responsibility is to respond to input from the presentation layer with new states. This layer can depend on one or more repositories to retrieve data needed to build up the application state.
This layer hosts our blocks, cubits and services.
Services
They are used to store any logic that's not related to a UI State
Cubits/BLoCs
They are used to store any logic that can result to a UI State change
Presentation layer
This layer is the one the user interacts with. It renders itself base on one or more BLoC/Cubit's state
Folder structure
Here's how our folder structure look like:
lib/
βββ generated/
βββ src/
βββ core/
β βββ i18n/
β βββ routing/
β βββ theme/
β βββ app_initialiser.dart
β βββ application.dart
β βββ environment.dart
βββ datasource/
β βββ http/
β βββ models/
β βββ repositories/
β βββ base_repository.dart
βββ features/
β βββ music_recognition/
β β βββ enums/
β β βββ exceptions/
β β βββ logic/
β β βββ repositories/
β β βββ services/
β β βββ ui/
β βββ music_details/
βββ main.dart
Testing
This repo uses couple of testing libs :
- bloc_test: A Dart package that makes testing blocs and cubits easy
- mocktail: A Dart mock library which simplifies mocking with null safety support and no manual mocks or code generation.
- http_mock_adapter: A simple to use mocking package for Dio intended to be used in tests. It provides various types and methods to declaratively mock request-response communication.
Usage examples are available in the test
dir.
Tools
- fvm: used for flutter version management
- flutter_gen: Used to generated assets