Skip to content

feat/documentation #59

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 2 commits into from
Apr 15, 2024
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
5 changes: 5 additions & 0 deletions assets/documentation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## v0.0.1 - 1

* ProjectSetup: Initialized new project with base architecture
28 changes: 28 additions & 0 deletions assets/documentation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# {app_name}

Readme file contains a technical description of the {app_name} project, provides instructions on how to install the applications and contains description of complex technical solutions and flows used.

## Contents:

* [Installation instructions](docs/INSTALL_INSTRUCTION.md)
* [Architecture overview](docs/ARCH_OVERVIEW.md)
* [Technical description](docs/TECH_DESCRIPTION.md)
* [Development solutions](docs/dev_solutions/DEV_SOLUTIONS.md)
* [Changelog](CHANGELOG.md)

## Project environment

* Supported Dart SDK `>=3.2.0 <4.0.0`
* Flutter SDK `Channel stable, 3.19.1`
* Min Android SDK version `22`
* Compile Android API version `34`
* Target Android API version `34`
* Minimum deployment iOS version: `12`

## Application packages

Here described package names and bundle ids used in the {app_name} application project:

{platform_package_names}


75 changes: 75 additions & 0 deletions assets/documentation/docs/ARCH_OVERVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Architecture overview

{app_name} project code built on Clean based hybrid Architecture (I'll just call it Clean architecture for simplicity's sake).

The main concept of regular [Clean Architecture](http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) is codes splitted to layers, where every low-level layer knows nothing about up layers, separation of business logic from UI, not depending on frameworks or libraries, etc.

The architecture we used in {app_name} project is very similar to the regular Clean architecture, but it has its own values, which is why we call it Clean based quasi-architecture.

The main features of the architecture:

* a clear separation of code into layers: data, domain, presentation is preserved;
* each layer operates with data within its responsibility;
* interaction between layers occurs through interfaces;
* data models are separated from general use models;
* DI is used to provide access to code components;
* the chain of access to components and method calls is strictly defined and cannot be broken;
* there is an additional app layer to meet the needs of the application;

## Layers, components, and their interaction

### App level
Contains classes that meet the needs of the entire application. These are usually global components that affect the operation of the entire application. For example: navigation components, localization, utilities, etc.
This layer also contains application-level services. Usually, these are services that process and store data on which the application globally depends. For example: authorization status, current user profile, etc.
These services are created and transferred using DI.

### Data layer
The data layer operates with the lowest-level data and deals with receiving data from various sources, transferring data to storage locations, transforming it, organizing it, and then transferring it to the next layer.
To be more specific, the main operations that take place in the data layer are as follows:

* work with APIs;
* work with data storage;
* work with other data providers;
* data transformation for further use in other layers;

The data layer has 2 main components: **source** and **repository implementation**.

**Source** receives data directly from the provider: API, Storage, or others data providers and transmits it in the data format or class of a specific error.

The **repository** interacts with different sources, receives data from them, transforms, combines and performs other necessary operations and passes it on in the format of data or error.

Both components are created through DI, and have a dependency between them, so that **source can be called from repository but not vice versa**. The dependency is ensured by passing source to the repository constructor (in the DI configuration).

### Domain layer
The Domain layer is the link layer between data and presentation. In this layer, data is retrieved from the data layer and data calls are organized into specific scenarios.

The main components are: **usecase** and **repository interface**.

**Usecase** executes specific scenarios in the application by calling repositories, services, and other auxiliary components and returns a result that is ready to be used in the presentation in the format of data or error.

The **repository interface** is a simple interface that describes the functions of a specific repository and from which a specific repository in the data layer is inherited.

Both components are created through DI and have a dependency between them, so that **usecase can call functions of repository (or service) but not vice versa**. The dependency is ensured by passing source to the repository constructor (in the DI configuration).

### Presentation layer
The presentation layer contains classes that are responsible for the visual display of the application, UI and screens, as well as **state controllers and presentation logic holders**(BLoC).

Usually, a separate state controller is used for each screen. But there are cases when it can be used in several places.

The **state controller** is the highest component in the call chain by calling **usecase** and it initiates calls to other components sequentially. In turn, the state controller depends on the events that occur in the UI.

### Call chain

To be more specific, the call chain works from the highest level (UI and state controller) to the lowest and usually looks like this:

* usecase called from state controller (BLoC);
* one or more repositories(interface) (or services) called from usecase;
* one or more sources called from repository(implementation);
* source called data provider (API request or else);
* result is providing back to caller by returning result in each component;






132 changes: 132 additions & 0 deletions assets/documentation/docs/INSTALL_INSTRUCTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# {app_name} Installation guide

This section describes different installation options. It consists of the following parts:

* Terminology
* Platforms supported
* Environment variables and setup
* Important installation instructions
* How to run {app_name} application locally
* How to run {app_name} automatic tests
* How to build {app_name} application



## Terminology

* **Output Type** - platform keyword used in run or build commands to specify for what platform app will be built. Available platforms are:

```
{output_types}
```
Apk and AppBundle refers to Android and specifies a type of output file (`*.apk` or `*.aab`).


* **Flavor** - type of application configuration. {app_name} supports following flavors:

```
{app_flavors}
```

* **Build type** - type of build process: `release` or `debug`.
* **main.dart** file - main file and entry point of your application. {main_count_description}:

```
{app_main_files}
```

When you specifying a flavor in run or build command you also need to specify corresponding `main.dart` file for that flavor.

## Platforms supported

{app_name} application supported on following platforms:

{app_platforms}

## Important installation instructions

Before opening {app_name} project make sure that you have installed followed software on your Mac or PC:

* IDE (Android Studio or VSCode)
* Dart SDK
* Flutter SDK and Flutter plugin for IDE

When you sure you installed followed software follow steps to prepare {app_name} project to build.

* Open project folder in your IDE and wait for project indexing finished
* Open IDE terminal and run `dart pub get` command and wait to complete and import errors disappeared

## Environment variables and setup

To add project environment keys need to create `.env` file in root folder for each of flavors:

```
{app_env_files}
```

{app_env_explanation}
Environment file scheme:

```
STRIPE_KEY=enter_stripe_key
OPENAI_PUBLIC_KEY=enter_openAi_key
```
## How to run {app_name} application locally

To run {app_name} application locally on device follow steps:

* Connect device or open an device emulator and make sure it appeared in devices list in IDE;
* Select build configuration in Flutter plugin toolbar
* Press Run button

You can use commands to run applications also. To run app:

* Open IDE terminal
* Run command `flutter run --flavor {flavor} --{build_type} -t {path_to_main.dart}`

## How to run {app_name} automatic tests

{app_name} application is covered with **unit** and **widgets** tests.
The goal of a unit test is to verify the correctness of a unit of logic under a variety of conditions.
The goal of a widget test is to verify that the widget’s UI looks and interacts as expected.

To lauch all tests run following command in IDE terminal:

`flutter test`

To launch specific test run following command in IDE terminal:

`flutter test {path_to test_file.dart}`

## How to build {app_name} application

To build application open IDE terminal use following command:

`flutter build {output_type} --flavor {flavor} -t {{path_to_main.dart}}`

Add obfuscation params if you build application for mobile platforms:
`--obfuscate --split-debug-info=debug_info`

Next step is depending on platform:

* For iOS and MacOS open ios/macos folder of project in XCode and follow instructions How to upload app to AppStore
* For Android you'll see the location of the output file in the terminal after build finished. Follow the instruction to upload build to Play Store
* For Web - after build completed - deploy content of `/web` folder to your server

## Possible build errors

### Some files are underlined red in project file tree:

Try to run `dart pub get` command in IDE terminal

### When you build an iOS or MacOS application you might get Pod's issue.

To fix that run following command in IDE terminal:

`cd ios && pod cache clean --all && pod repo update && pod update && cd .. && flutter clean && flutter pub get`






86 changes: 86 additions & 0 deletions assets/documentation/docs/TECH_DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# {app_name} Technical description

This file contains a description of technologies, packages and libraries used in {app_name} project.

## Main Technologies

### Core packages
* [GetIt](https://pub.dev/packages/get_it) - service locator, used for fast and effective acces to objects
* [Screen Util](https://pub.dev/packages/flutter_screenutil) - adaptive UI tools providing autoscaling UI features
* [Go Router](https://pub.dev/packages/go_router) - navigation library that complies with Flutter Navigation 2.0
* [Freezed](https://pub.dev/packages/freezed_annotation) - code generarion of data classes withh boilerplate functions

### Local storage and database

* [Hive](https://pub.dev/packages/hive) - effective noSQL database
* [Shared Preferences](https://pub.dev/packages/shared_preferences) - key-value storage

### Networking

* [Dio](https://pub.dev/packages/dio) - Http client
* [Json Annotation](https://pub.dev/packages/json_annotation) - code generation based JSON parsing utility

### State management

* [Bloc](https://pub.dev/packages/flutter_bloc) - state management

### UI

* [Native Splash](https://pub.dev/packages/flutter_native_splash) - utitity to generate splash screen from yaml configuration(in `pubspec.yaml`)

## Build runner

{app_name} project uses Build Runner to generate additional code. This features mostly used in **freezed** and **jsonAnnotation** utilities. So when you chaning build runner related classes you need to regenerate additional generated classes (mostly it's `*.g.dart`, `*.freezed.dart` classes).

To generate classes:

`flutter packages pub run build_runner build`

Use the [watch] flag to watch the files' system for edits and rebuild as necessary.

`flutter packages pub run build_runner watch`

If you have conflicts use command:

`flutter pub run build_runner build --delete-conflicting-outputs`

## Launcher Icons

{app_name} uses [flutter_launcher_icons](https://pub.dev/packages/flutter_launcher_icons) plugin fro quick generation on icons for mobile applications. Flutter Launcher Icons configuration placed in pubspec.yaml (`flutter_launcher_icons` section) or in config file called `flutter_launcher_icons.yaml`.
After you changing configuration or icon images need to rerun icons generation to apply changes using command:

`flutter pub run flutter_launcher_icons:main`

If project contains flavors and need to regenerate icons for ech flavor run:

`flutter pub run flutter_launcher_icons:main -f flutter_launcher_icons*`

## Deep links

{app_name} has a deep link features, and here describe all deeplinks options are available in the application.

Deep links schemes are:

* Android: `https://dev-backend.myapp.com/{action}`
* iOS: `myappappscheme://myapp.com/{action}`
* iOS Unilink: `https://dev-backend.myapp.com/{action}`

Deeplink actions:

* Move money (deeplink to open transfer money to some user): `move_money`

### Testing Deep links
**Android:**
```
adb shell am start -a android.intent.action.VIEW \
-c android.intent.category.BROWSABLE \
-d https://dev-backend.myapp.com/move_money
```

**iOS Scheme links:**

`xcrun simctl openurl booted myappappscheme://myapp.com/move_money`

**IOS Uni Links:**

`xcrun simctl openurl booted https://dev-backend.myapp.com/move_money`
9 changes: 9 additions & 0 deletions assets/documentation/docs/dev_solutions/DEV_SOLUTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Development solutions

This section describes complex flows, custom complex solutions and describes package modifications used in {app_name} application.

Contents:
* [Example Flow](EXAMPLE.md)



18 changes: 18 additions & 0 deletions assets/documentation/docs/dev_solutions/EXAMPLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Example Flow


This section describing how Example flow works in {app_name} application.
For verifying user identity [Onfido](https://onfido.com/) library used. Onfido incapsulates all business logic about capturing user documents and send it to verify and jus return a status KYC of validation.

```mermaid
flowchart TD
A[User Logged In] --> B[Check KYC status];
B ----> C{KYC Approved}
C -- Yes --> D[User allowed to order physical card];
C -- No --> E[Show Verify identity button on Home screen];
D ----> F[Verify button pressed]
E ----> G{Launch Onfido verifying}
G -- Verified --> D;
G -- Verification failed --> J[Show Verification failure message];
J ----> E
```
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AppService {
final _secureFromJailbreak = true;

Future<bool> initialize() async {
if (_secureFromJailbreak && !kIsWeb) {
if (_secureFromJailbreak && !kIsWeb && !kDebugMode) {
final isJailBroken = await FlutterJailbreakDetection.jailbroken;
if (isJailBroken) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import 'package:{{project_name}}/core/arch/data/remote/clients/dio/dio_request_p
{{#graphql}}import 'package:{{project_name}}/core/arch/data/remote/clients/graph_ql/graph_ql_client.dart';
import 'package:{{project_name}}/core/arch/data/remote/clients/graph_ql/request_processor/graph_ql_request_processor.dart';
import 'package:{{project_name}}/core/arch/data/remote/clients/graph_ql/request_processor/graph_ql_request_processor_impl.dart';{{/graphql}}

{{#firebase_auth}}import 'package:firebase_auth/firebase_auth.dart';{{/firebase_auth}}
void registerRemote(GetIt getIt) {
final dioClientModule = _DioClientModule();

getIt.registerLazySingleton<DioRequestProcessor>(
dioClientModule.makeDioErrorHandler,
);{{#graphql}}
getIt.registerLazySingleton<GraphQlRequestProcessor>(
);{{#firebase_auth}}
getIt.registerLazySingleton<FirebaseAuth>(
() => FirebaseAuth.instance,
);{{/firebase_auth}}

{{#graphql}}getIt.registerLazySingleton<GraphQlRequestProcessor>(
GraphQlRequestProcessorImpl.new,
);
getIt.registerLazySingleton<GraphQlClient>(
Expand All @@ -23,6 +27,5 @@ void registerRemote(GetIt getIt) {
//{remote end}
}

{{#graphql}}GraphQlClient graphQlApiClient() => GetIt.I.get<GraphQlClient>();
{{/graphql}}
{{#graphql}}GraphQlClient graphQlApiClient() => GetIt.I.get<GraphQlClient>();{{/graphql}}
class _DioClientModule extends DioClientModule {}
Loading