From 5a37c04c3466f6fe4fc5fb6e79b0f6318820c14c Mon Sep 17 00:00:00 2001 From: Anes Belfodil Date: Sat, 12 Sep 2020 20:29:46 -0400 Subject: [PATCH 01/10] Add base Flutter dependencies --- mobile/pubspec.lock | 120 ++++++++++++++++++++++++++++++++++++++++++++ mobile/pubspec.yaml | 8 +++ 2 files changed, 128 insertions(+) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 65a95a92..03161685 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: "direct main" + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" async: dependency: transitive description: @@ -8,6 +22,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.5.0-nullsafety" + battery: + dependency: "direct main" + description: + name: battery + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + battery_platform_interface: + dependency: transitive + description: + name: battery_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + bloc: + dependency: "direct main" + description: + name: bloc + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.3" boolean_selector: dependency: transitive description: @@ -43,6 +78,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0-nullsafety.2" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" cupertino_icons: dependency: "direct main" description: @@ -69,11 +118,32 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.5" + flutter_blue: + dependency: "direct main" + description: + name: flutter_blue + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.2" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + hive: + dependency: "direct main" + description: + name: hive + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.4" matcher: dependency: transitive description: @@ -88,6 +158,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0-nullsafety.2" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.7" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4" path: dependency: transitive description: @@ -95,6 +179,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0-nullsafety" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" protobuf: dependency: "direct main" description: @@ -102,6 +193,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + provider: + dependency: transitive + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.2+2" + rxdart: + dependency: transitive + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.24.1" + share: + dependency: "direct main" + description: + name: share + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.5" sky_engine: dependency: transitive description: flutter @@ -156,6 +268,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0-nullsafety.2" + usb_serial: + dependency: "direct main" + description: + name: usb_serial + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.4" vector_math: dependency: transitive description: @@ -165,3 +284,4 @@ packages: version: "2.1.0-nullsafety.2" sdks: dart: ">=2.10.0-0.0.dev <2.10.0" + flutter: ">=1.16.0 <2.0.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 4c083390..5409c88d 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -28,6 +28,14 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.3 protobuf: ^1.0.1 + hive: ^1.4.4 + usb_serial: ^0.2.4 + flutter_blue: ^0.7.2 + bloc: ^6.0.3 + flutter_bloc: ^6.0.5 + battery: ^1.0.5 + share: ^0.6.5 + archive: ^2.0.13 dev_dependencies: flutter_test: From 65cf38dfe9c451307cceca67321d613183cb7a4a Mon Sep 17 00:00:00 2001 From: Anes Belfodil Date: Mon, 14 Sep 2020 16:11:13 -0400 Subject: [PATCH 02/10] Bump minimal android sdk version --- mobile/android/app/build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index fb5a1026..4e62f489 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -37,9 +37,8 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.Polydodo" - minSdkVersion 16 + applicationId "com.PolyCortex.Polydodo" + minSdkVersion 19 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName From 0c53addf6b0d5bade3ac520b90a9dc776e545229 Mon Sep 17 00:00:00 2001 From: William Harvey Date: Mon, 14 Sep 2020 23:04:18 -0400 Subject: [PATCH 03/10] Increment and decrement with counter cubit & create main/app/locator structure --- mobile/lib/main.dart | 116 +----------------- mobile/lib/src/app.dart | 25 ++++ .../application/counter/counter_cubit.dart | 8 ++ mobile/lib/src/locator.dart | 10 ++ .../counter_route/counter_route.dart | 39 ++++++ .../counter_route/counter_text.dart | 21 ++++ mobile/lib/src/theme.dart | 6 + mobile/pubspec.lock | 43 +++---- mobile/pubspec.yaml | 2 +- 9 files changed, 131 insertions(+), 139 deletions(-) create mode 100644 mobile/lib/src/app.dart create mode 100644 mobile/lib/src/application/counter/counter_cubit.dart create mode 100644 mobile/lib/src/locator.dart create mode 100644 mobile/lib/src/presentation/counter_route/counter_route.dart create mode 100644 mobile/lib/src/presentation/counter_route/counter_text.dart create mode 100644 mobile/lib/src/theme.dart diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 11655b66..ad72d679 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -1,117 +1,7 @@ import 'package:flutter/material.dart'; -void main() { - runApp(MyApp()); -} - -class MyApp extends StatelessWidget { - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, - // This makes the visual density adapt to the platform that you run - // the app on. For desktop platforms, the controls will be smaller and - // closer together (more dense) than on mobile platforms. - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ); - } -} - -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". +import 'src/app.dart'; - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Invoke "debug painting" (press "p" in the console, choose the - // "Toggle Debug Paint" action from the Flutter Inspector in Android - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) - // to see the wireframe for each widget. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } +void main() { + runApp(App()); } diff --git a/mobile/lib/src/app.dart b/mobile/lib/src/app.dart new file mode 100644 index 00000000..168bc419 --- /dev/null +++ b/mobile/lib/src/app.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'presentation/counter_route/counter_route.dart'; +import 'locator.dart'; +import 'theme.dart'; + +class App extends StatelessWidget { + @override + Widget build(BuildContext context) { + /// Cubits are provided globally down all of the context tree + return MultiBlocProvider( + providers: createBlocProviders(), + child: MaterialApp( + title: 'PolyDodo', + theme: theme, + home: CounterRoute(), + initialRoute: CounterRoute.name, + routes: { + CounterRoute.name: (context) => CounterRoute(), + }, + ), + ); + } +} diff --git a/mobile/lib/src/application/counter/counter_cubit.dart b/mobile/lib/src/application/counter/counter_cubit.dart new file mode 100644 index 00000000..70bd952a --- /dev/null +++ b/mobile/lib/src/application/counter/counter_cubit.dart @@ -0,0 +1,8 @@ +import 'package:bloc/bloc.dart'; + +class CounterCubit extends Cubit { + CounterCubit() : super(0); + + void increment() => emit(state + 1); + void decrement() => emit(state - 1); +} diff --git a/mobile/lib/src/locator.dart b/mobile/lib/src/locator.dart new file mode 100644 index 00000000..098b21c9 --- /dev/null +++ b/mobile/lib/src/locator.dart @@ -0,0 +1,10 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'application/counter/counter_cubit.dart'; + +/// This function creates all the BlocProviders used in this app +List createBlocProviders() => [ + BlocProvider( + create: (context) => CounterCubit(), + ), + ]; diff --git a/mobile/lib/src/presentation/counter_route/counter_route.dart b/mobile/lib/src/presentation/counter_route/counter_route.dart new file mode 100644 index 00000000..2c502ee4 --- /dev/null +++ b/mobile/lib/src/presentation/counter_route/counter_route.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:polydodo/src/application/counter/counter_cubit.dart'; + +import 'counter_text.dart'; + +class CounterRoute extends StatelessWidget { + static const name = 'counterRoute'; + + CounterRoute({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Polydodo')), + body: Center( + child: CounterText(), + ), + floatingActionButton: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + FloatingActionButton( + key: const Key('counterRoute_increment_fab'), + child: const Icon(Icons.add), + onPressed: () => BlocProvider.of(context).increment(), + ), + const SizedBox(height: 8), + FloatingActionButton( + key: const Key('counterRoute_decrement_fab'), + child: const Icon(Icons.remove), + onPressed: () => BlocProvider.of(context).decrement(), + ), + ], + ), + ); + } +} diff --git a/mobile/lib/src/presentation/counter_route/counter_text.dart b/mobile/lib/src/presentation/counter_route/counter_text.dart new file mode 100644 index 00000000..dc430777 --- /dev/null +++ b/mobile/lib/src/presentation/counter_route/counter_text.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:polydodo/src/application/counter/counter_cubit.dart'; + +class CounterText extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('You have pushed the button this many times:'), + Text('$state', style: Theme.of(context).textTheme.headline2), + ], + ); + }, + ); + } +} diff --git a/mobile/lib/src/theme.dart b/mobile/lib/src/theme.dart new file mode 100644 index 00000000..893c05cd --- /dev/null +++ b/mobile/lib/src/theme.dart @@ -0,0 +1,6 @@ +import 'package:flutter/material.dart'; + +final theme = ThemeData( + primarySwatch: Colors.blue, + visualDensity: VisualDensity.adaptivePlatformDensity, +); diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 03161685..67166363 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -21,7 +21,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety" + version: "2.4.1" battery: dependency: "direct main" description: @@ -49,35 +49,28 @@ packages: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0-nullsafety.2" + version: "2.0.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety" + version: "1.1.3" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety" + version: "1.0.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.2" + version: "1.14.12" convert: dependency: transitive description: @@ -105,7 +98,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety" + version: "1.1.0" fixnum: dependency: transitive description: @@ -150,14 +143,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety" + version: "0.12.6" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.2" + version: "1.1.8" mime: dependency: transitive description: @@ -178,7 +171,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety" + version: "1.7.0" plugin_platform_interface: dependency: transitive description: @@ -225,49 +218,49 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety" + version: "1.7.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety" + version: "1.9.3" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety" + version: "2.0.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety" + version: "1.0.5" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety" + version: "1.1.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety" + version: "0.2.16" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.2" + version: "1.1.6" usb_serial: dependency: "direct main" description: @@ -281,7 +274,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.2" + version: "2.0.8" sdks: - dart: ">=2.10.0-0.0.dev <2.10.0" + dart: ">=2.7.0 <3.0.0" flutter: ">=1.16.0 <2.0.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 5409c88d..8ae20b40 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -1,4 +1,4 @@ -name: Polydodo +name: polydodo description: A new Flutter project. # The following line prevents the package from being accidentally published to From 8697b3514ff137721d0ea32850e08dbd925ca8c6 Mon Sep 17 00:00:00 2001 From: William Harvey Date: Tue, 15 Sep 2020 00:02:41 -0400 Subject: [PATCH 04/10] create and implement domain layer --- mobile/lib/src/domain/unique_id.dart | 20 +++++++++ .../domain/wallet/i_wallet_repository.dart | 8 ++++ mobile/lib/src/domain/wallet/money.dart | 41 +++++++++++++++++++ mobile/lib/src/domain/wallet/owner.dart | 26 ++++++++++++ mobile/lib/src/domain/wallet/wallet.dart | 29 +++++++++++++ mobile/pubspec.lock | 14 +++++++ mobile/pubspec.yaml | 16 ++++---- 7 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 mobile/lib/src/domain/unique_id.dart create mode 100644 mobile/lib/src/domain/wallet/i_wallet_repository.dart create mode 100644 mobile/lib/src/domain/wallet/money.dart create mode 100644 mobile/lib/src/domain/wallet/owner.dart create mode 100644 mobile/lib/src/domain/wallet/wallet.dart diff --git a/mobile/lib/src/domain/unique_id.dart b/mobile/lib/src/domain/unique_id.dart new file mode 100644 index 00000000..9b301f89 --- /dev/null +++ b/mobile/lib/src/domain/unique_id.dart @@ -0,0 +1,20 @@ +import 'package:equatable/equatable.dart'; +import 'package:uuid/uuid.dart'; + +class UniqueId extends Equatable { + final String _id; + + UniqueId() : _id = Uuid().v4(); + + UniqueId.from(String unique) + : assert(unique != null), + _id = unique; + + String get() => _id; + + @override + List get props => [_id]; + + @override + bool get stringify => true; +} diff --git a/mobile/lib/src/domain/wallet/i_wallet_repository.dart b/mobile/lib/src/domain/wallet/i_wallet_repository.dart new file mode 100644 index 00000000..b03ae674 --- /dev/null +++ b/mobile/lib/src/domain/wallet/i_wallet_repository.dart @@ -0,0 +1,8 @@ +import 'package:polydodo/src/domain/unique_id.dart'; + +import 'wallet.dart'; + +abstract class IWalletRepository { + Future write(Wallet wallet); + Stream watch(UniqueId walletId); +} diff --git a/mobile/lib/src/domain/wallet/money.dart b/mobile/lib/src/domain/wallet/money.dart new file mode 100644 index 00000000..0408acf4 --- /dev/null +++ b/mobile/lib/src/domain/wallet/money.dart @@ -0,0 +1,41 @@ +import 'package:equatable/equatable.dart'; + +enum Currency { usd, cad } + +// Value object usually extends equatable +class Money extends Equatable { + static const _min = 0; + static const _usdToCadRate = 1.32; + + final double value; + final Currency currency; + + Money(this.value, this.currency) + : assert(value != null), + assert(currency != null) { + // Validation that money cannot be in an impossible state + if (value <= _min) { + Exception('Money amount cannot be inferior to $_min'); + } + } + + double get usd { + if (currency == Currency.cad) { + return value / _usdToCadRate; + } + return value; + } + + double get cad { + if (currency == Currency.usd) { + return value * _usdToCadRate; + } + return value; + } + + Money operator +(Money other) => Money(this.usd + other.usd, Currency.usd); + Money operator -(Money other) => Money(this.usd - other.usd, Currency.usd); + + @override + List get props => [usd]; +} diff --git a/mobile/lib/src/domain/wallet/owner.dart b/mobile/lib/src/domain/wallet/owner.dart new file mode 100644 index 00000000..c4c19c4a --- /dev/null +++ b/mobile/lib/src/domain/wallet/owner.dart @@ -0,0 +1,26 @@ +import 'package:polydodo/src/domain/unique_id.dart'; + +class Owner { + static const _legalAge = 16; + + final UniqueId id; + final String firstName; + final String lastName; + final int age; + + Owner(this.id, this.firstName, this.lastName, this.age) + : assert(id != null), + assert(firstName != null), + assert(lastName != null) { + if (firstName.length <= 0 || lastName.length <= 0) { + throw Exception('First and last name cannot be empty'); + } + if (!_hasLegalAge()) { + throw Exception('This owner does not have the legal age'); + } + } + + bool _hasLegalAge() => age >= _legalAge; + + // In a good model entity, we should have behavorial method... +} diff --git a/mobile/lib/src/domain/wallet/wallet.dart b/mobile/lib/src/domain/wallet/wallet.dart new file mode 100644 index 00000000..1866899a --- /dev/null +++ b/mobile/lib/src/domain/wallet/wallet.dart @@ -0,0 +1,29 @@ +import 'package:polydodo/src/domain/unique_id.dart'; + +import 'money.dart'; +import 'owner.dart'; + +// We call Wallet an aggregate root because it own other entities +class Wallet { + final UniqueId id; + final Owner owner; + Money money; + + Wallet(this.id, this.owner, this.money); + + // Wallet is an entity and therefore it must have a behavior. It is here that + // business logic appears. + void transfer(Money amount, Wallet receiver) { + if (money.usd - amount.usd < 0) { + throw Exception( + 'Not enough money in this wallet to perform this transaction', + ); + } + money -= amount; + receiver.receive(amount); + } + + void receive(Money amount) { + money += amount; + } +} diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 67166363..f3a4a78e 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -92,6 +92,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.3" + equatable: + dependency: "direct main" + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.5" fake_async: dependency: transitive description: @@ -268,6 +275,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.4" + uuid: + dependency: "direct main" + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.2" vector_math: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 8ae20b40..dd617208 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -26,16 +26,18 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.3 - protobuf: ^1.0.1 - hive: ^1.4.4 - usb_serial: ^0.2.4 - flutter_blue: ^0.7.2 + archive: ^2.0.13 + battery: ^1.0.5 bloc: ^6.0.3 + cupertino_icons: ^0.1.3 + equatable: ^1.2.5 flutter_bloc: ^6.0.5 - battery: ^1.0.5 + flutter_blue: ^0.7.2 + hive: ^1.4.4 + protobuf: ^1.0.1 share: ^0.6.5 - archive: ^2.0.13 + usb_serial: ^0.2.4 + uuid: ^2.2.2 dev_dependencies: flutter_test: From 15e4ab8fe7822d2e7ebf97ab8887dd3214120ac4 Mon Sep 17 00:00:00 2001 From: William Harvey Date: Sat, 19 Sep 2020 00:28:39 -0400 Subject: [PATCH 05/10] Create Flutter code structure example based on this [arch](https://github.com/PolyCortex/polydodo/wiki/Mobile-Architecture) --- mobile/lib/src/app.dart | 12 ++-- .../application/counter/counter_cubit.dart | 8 --- .../application/wallets/wallets_cubit.dart | 63 +++++++++++++++++++ .../application/wallets/wallets_state.dart | 25 ++++++++ mobile/lib/src/domain/wallet/constants.dart | 1 + .../domain/wallet/i_wallet_repository.dart | 6 +- mobile/lib/src/domain/wallet/money.dart | 26 ++++++-- mobile/lib/src/domain/wallet/owner.dart | 10 ++- mobile/lib/src/domain/wallet/wallet.dart | 10 ++- .../mock_wallet_repository.dart | 22 +++++++ mobile/lib/src/locator.dart | 21 ++++++- .../counter_route/counter_route.dart | 39 ------------ .../counter_route/counter_text.dart | 21 ------- .../presentation/wallets/wallet_widget.dart | 23 +++++++ .../presentation/wallets/wallets_route.dart | 62 ++++++++++++++++++ .../presentation/wallets/wallets_widget.dart | 32 ++++++++++ mobile/pubspec.lock | 9 ++- mobile/pubspec.yaml | 2 + 18 files changed, 303 insertions(+), 89 deletions(-) delete mode 100644 mobile/lib/src/application/counter/counter_cubit.dart create mode 100644 mobile/lib/src/application/wallets/wallets_cubit.dart create mode 100644 mobile/lib/src/application/wallets/wallets_state.dart create mode 100644 mobile/lib/src/domain/wallet/constants.dart create mode 100644 mobile/lib/src/infrastructure/mock_wallet_repository.dart delete mode 100644 mobile/lib/src/presentation/counter_route/counter_route.dart delete mode 100644 mobile/lib/src/presentation/counter_route/counter_text.dart create mode 100644 mobile/lib/src/presentation/wallets/wallet_widget.dart create mode 100644 mobile/lib/src/presentation/wallets/wallets_route.dart create mode 100644 mobile/lib/src/presentation/wallets/wallets_widget.dart diff --git a/mobile/lib/src/app.dart b/mobile/lib/src/app.dart index 168bc419..be3bfef4 100644 --- a/mobile/lib/src/app.dart +++ b/mobile/lib/src/app.dart @@ -1,11 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'presentation/counter_route/counter_route.dart'; +import 'presentation/wallets/wallets_route.dart'; import 'locator.dart'; import 'theme.dart'; class App extends StatelessWidget { + App() { + registerServices(); + } + @override Widget build(BuildContext context) { /// Cubits are provided globally down all of the context tree @@ -14,10 +18,10 @@ class App extends StatelessWidget { child: MaterialApp( title: 'PolyDodo', theme: theme, - home: CounterRoute(), - initialRoute: CounterRoute.name, + home: WalletsRoute(), + initialRoute: WalletsRoute.name, routes: { - CounterRoute.name: (context) => CounterRoute(), + WalletsRoute.name: (context) => WalletsRoute(), }, ), ); diff --git a/mobile/lib/src/application/counter/counter_cubit.dart b/mobile/lib/src/application/counter/counter_cubit.dart deleted file mode 100644 index 70bd952a..00000000 --- a/mobile/lib/src/application/counter/counter_cubit.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:bloc/bloc.dart'; - -class CounterCubit extends Cubit { - CounterCubit() : super(0); - - void increment() => emit(state + 1); - void decrement() => emit(state - 1); -} diff --git a/mobile/lib/src/application/wallets/wallets_cubit.dart b/mobile/lib/src/application/wallets/wallets_cubit.dart new file mode 100644 index 00000000..6ab7d3e3 --- /dev/null +++ b/mobile/lib/src/application/wallets/wallets_cubit.dart @@ -0,0 +1,63 @@ +import 'dart:math'; + +import 'package:bloc/bloc.dart'; + +import 'package:polydodo/src/application/wallets/wallets_state.dart'; +import 'package:polydodo/src/domain/unique_id.dart'; +import 'package:polydodo/src/domain/wallet/i_wallet_repository.dart'; +import 'package:polydodo/src/domain/wallet/money.dart'; +import 'package:polydodo/src/domain/wallet/owner.dart'; +import 'package:polydodo/src/domain/wallet/wallet.dart'; + +class WalletsCubit extends Cubit { + final IWalletRepository _walletRepository; + + WalletsCubit(this._walletRepository) : super(WalletsInitial()) { + createNewWallets(); + emit(WalletsLoadInProgress()); + _walletRepository + .watch() + .listen((wallets) => emit(WalletsLoadSuccess(wallets))) + .onError((e) => emit(WalletsLoadFailure(e))); + } + + // Does not yield another state + void transfer(Wallet sender, Wallet receiver, Money amount) async { + try { + sender.transfer(amount, receiver); + } catch (e) { + emit(WalletsTransferFailure(e)); + } + await Future.wait([ + _walletRepository.store(sender), + _walletRepository.store(receiver), + ]).catchError((e) => emit(WalletsTransferFailure(e))); + } + + Future> createNewWallets() => Future.wait([ + _walletRepository.store( + Wallet( + UniqueId(), + Owner( + id: UniqueId.from('1'), + firstName: 'Bob', + lastName: 'Skiridovsky', + age: 25, + ), + Money(Random().nextDouble() * 10, Currency.cad), + ), + ), + _walletRepository.store( + Wallet( + UniqueId(), + Owner( + id: UniqueId.from('2'), + firstName: 'Alice', + lastName: 'Pogo', + age: 35, + ), + Money(Random().nextDouble() * 1000, Currency.cad), + ), + ) + ]); +} diff --git a/mobile/lib/src/application/wallets/wallets_state.dart b/mobile/lib/src/application/wallets/wallets_state.dart new file mode 100644 index 00000000..01788a39 --- /dev/null +++ b/mobile/lib/src/application/wallets/wallets_state.dart @@ -0,0 +1,25 @@ +import 'package:polydodo/src/domain/wallet/wallet.dart'; + +abstract class WalletsState {} + +class WalletsInitial extends WalletsState {} + +class WalletsLoadInProgress extends WalletsState {} + +class WalletsLoadSuccess extends WalletsState { + final List wallets; + + WalletsLoadSuccess(this.wallets); +} + +class WalletsLoadFailure extends WalletsState { + final Exception cause; + + WalletsLoadFailure(this.cause); +} + +class WalletsTransferFailure extends WalletsState { + final Exception cause; + + WalletsTransferFailure(this.cause); +} diff --git a/mobile/lib/src/domain/wallet/constants.dart b/mobile/lib/src/domain/wallet/constants.dart new file mode 100644 index 00000000..595ccd29 --- /dev/null +++ b/mobile/lib/src/domain/wallet/constants.dart @@ -0,0 +1 @@ +const cadToUsdRate = 1.32; diff --git a/mobile/lib/src/domain/wallet/i_wallet_repository.dart b/mobile/lib/src/domain/wallet/i_wallet_repository.dart index b03ae674..d1f87cff 100644 --- a/mobile/lib/src/domain/wallet/i_wallet_repository.dart +++ b/mobile/lib/src/domain/wallet/i_wallet_repository.dart @@ -1,8 +1,6 @@ -import 'package:polydodo/src/domain/unique_id.dart'; - import 'wallet.dart'; abstract class IWalletRepository { - Future write(Wallet wallet); - Stream watch(UniqueId walletId); + Future store(Wallet wallet); + Stream> watch(); } diff --git a/mobile/lib/src/domain/wallet/money.dart b/mobile/lib/src/domain/wallet/money.dart index 0408acf4..1f760cea 100644 --- a/mobile/lib/src/domain/wallet/money.dart +++ b/mobile/lib/src/domain/wallet/money.dart @@ -1,11 +1,17 @@ import 'package:equatable/equatable.dart'; +import 'constants.dart'; + enum Currency { usd, cad } +Map currencyToString = { + Currency.usd: 'USD', + Currency.cad: 'CAD', +}; + // Value object usually extends equatable class Money extends Equatable { static const _min = 0; - static const _usdToCadRate = 1.32; final double value; final Currency currency; @@ -21,20 +27,30 @@ class Money extends Equatable { double get usd { if (currency == Currency.cad) { - return value / _usdToCadRate; + return value / cadToUsdRate; } return value; } double get cad { if (currency == Currency.usd) { - return value * _usdToCadRate; + return value * cadToUsdRate; } return value; } - Money operator +(Money other) => Money(this.usd + other.usd, Currency.usd); - Money operator -(Money other) => Money(this.usd - other.usd, Currency.usd); + Money convertTo(Currency currency) { + if (currency == Currency.usd) { + return Money(usd, currency); + } + return Money(cad, currency); + } + + /// Gives back result into left operand's currency + Money operator +(Money other) => + Money(this.usd + other.usd, Currency.usd).convertTo(this.currency); + Money operator -(Money other) => + Money(this.usd - other.usd, Currency.usd).convertTo(this.currency); @override List get props => [usd]; diff --git a/mobile/lib/src/domain/wallet/owner.dart b/mobile/lib/src/domain/wallet/owner.dart index c4c19c4a..a1360dbf 100644 --- a/mobile/lib/src/domain/wallet/owner.dart +++ b/mobile/lib/src/domain/wallet/owner.dart @@ -1,3 +1,5 @@ +import 'package:meta/meta.dart'; + import 'package:polydodo/src/domain/unique_id.dart'; class Owner { @@ -8,8 +10,12 @@ class Owner { final String lastName; final int age; - Owner(this.id, this.firstName, this.lastName, this.age) - : assert(id != null), + Owner({ + @required this.id, + @required this.firstName, + @required this.lastName, + @required this.age, + }) : assert(id != null), assert(firstName != null), assert(lastName != null) { if (firstName.length <= 0 || lastName.length <= 0) { diff --git a/mobile/lib/src/domain/wallet/wallet.dart b/mobile/lib/src/domain/wallet/wallet.dart index 1866899a..0c1dffcf 100644 --- a/mobile/lib/src/domain/wallet/wallet.dart +++ b/mobile/lib/src/domain/wallet/wallet.dart @@ -20,10 +20,16 @@ class Wallet { ); } money -= amount; - receiver.receive(amount); + receiver._receive(amount); } - void receive(Money amount) { + void _receive(Money amount) { money += amount; } + + @override + bool operator ==(other) => this.id == other.id; + + @override + int get hashCode => super.hashCode; } diff --git a/mobile/lib/src/infrastructure/mock_wallet_repository.dart b/mobile/lib/src/infrastructure/mock_wallet_repository.dart new file mode 100644 index 00000000..3e8cc516 --- /dev/null +++ b/mobile/lib/src/infrastructure/mock_wallet_repository.dart @@ -0,0 +1,22 @@ +import 'dart:async'; + +import 'package:polydodo/src/domain/wallet/i_wallet_repository.dart'; +import 'package:polydodo/src/domain/wallet/wallet.dart'; + +class MockWalletRepository implements IWalletRepository { + static List walletsMockPersistency = []; + final streamController = StreamController>(); + + @override + Future store(Wallet wallet) async { + await Future.delayed(Duration(milliseconds: 400)); + final idx = walletsMockPersistency.indexOf(wallet); + idx == -1 + ? walletsMockPersistency.add(wallet) + : walletsMockPersistency[idx] = wallet; + streamController.add(walletsMockPersistency); + } + + @override + Stream> watch() => streamController.stream; +} diff --git a/mobile/lib/src/locator.dart b/mobile/lib/src/locator.dart index 098b21c9..bac78b6f 100644 --- a/mobile/lib/src/locator.dart +++ b/mobile/lib/src/locator.dart @@ -1,10 +1,25 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get_it/get_it.dart'; -import 'application/counter/counter_cubit.dart'; +import 'package:polydodo/src/domain/wallet/i_wallet_repository.dart'; +import 'package:polydodo/src/infrastructure/mock_wallet_repository.dart'; + +import 'application/wallets/wallets_cubit.dart'; + +/// Private GetIt instance as we want all DI to be performed here in this file +final _serviceLocator = GetIt.asNewInstance(); + +void registerServices() { + _serviceLocator.registerSingleton( + MockWalletRepository(), + ); +} /// This function creates all the BlocProviders used in this app List createBlocProviders() => [ - BlocProvider( - create: (context) => CounterCubit(), + BlocProvider( + create: (context) => WalletsCubit( + _serviceLocator.get(), + ), ), ]; diff --git a/mobile/lib/src/presentation/counter_route/counter_route.dart b/mobile/lib/src/presentation/counter_route/counter_route.dart deleted file mode 100644 index 2c502ee4..00000000 --- a/mobile/lib/src/presentation/counter_route/counter_route.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'package:polydodo/src/application/counter/counter_cubit.dart'; - -import 'counter_text.dart'; - -class CounterRoute extends StatelessWidget { - static const name = 'counterRoute'; - - CounterRoute({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text('Polydodo')), - body: Center( - child: CounterText(), - ), - floatingActionButton: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - FloatingActionButton( - key: const Key('counterRoute_increment_fab'), - child: const Icon(Icons.add), - onPressed: () => BlocProvider.of(context).increment(), - ), - const SizedBox(height: 8), - FloatingActionButton( - key: const Key('counterRoute_decrement_fab'), - child: const Icon(Icons.remove), - onPressed: () => BlocProvider.of(context).decrement(), - ), - ], - ), - ); - } -} diff --git a/mobile/lib/src/presentation/counter_route/counter_text.dart b/mobile/lib/src/presentation/counter_route/counter_text.dart deleted file mode 100644 index dc430777..00000000 --- a/mobile/lib/src/presentation/counter_route/counter_text.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'package:polydodo/src/application/counter/counter_cubit.dart'; - -class CounterText extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('You have pushed the button this many times:'), - Text('$state', style: Theme.of(context).textTheme.headline2), - ], - ); - }, - ); - } -} diff --git a/mobile/lib/src/presentation/wallets/wallet_widget.dart b/mobile/lib/src/presentation/wallets/wallet_widget.dart new file mode 100644 index 00000000..426e3dc6 --- /dev/null +++ b/mobile/lib/src/presentation/wallets/wallet_widget.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:polydodo/src/domain/wallet/money.dart'; +import 'package:polydodo/src/domain/wallet/wallet.dart'; + +class WalletWidget extends StatelessWidget { + final Wallet wallet; + + const WalletWidget({Key key, @required this.wallet}) : super(key: key); + + @override + Widget build(BuildContext context) { + final currency = currencyToString[wallet.money.currency]; + return Container( + child: Column( + children: [ + Text('${wallet.owner.firstName} ${wallet.owner.lastName}'), + Text('ID: ${wallet.owner.id.get()}'), + Text('${wallet.money.value.toStringAsFixed(2)} $currency'), + ], + ), + ); + } +} diff --git a/mobile/lib/src/presentation/wallets/wallets_route.dart b/mobile/lib/src/presentation/wallets/wallets_route.dart new file mode 100644 index 00000000..842784d5 --- /dev/null +++ b/mobile/lib/src/presentation/wallets/wallets_route.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:polydodo/src/application/wallets/wallets_cubit.dart'; +import 'package:polydodo/src/application/wallets/wallets_state.dart'; +import 'package:polydodo/src/domain/wallet/constants.dart'; +import 'package:polydodo/src/domain/wallet/money.dart'; + +import 'wallets_widget.dart'; + +class WalletsRoute extends StatelessWidget { + static const name = 'walletsRoute'; + + WalletsRoute({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Polydodo')), + body: BlocConsumer( + listener: (context, state) { + print(state.runtimeType); + if (state is WalletsLoadFailure) { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text('Unable to load Wallets because ${state.cause}'), + )); + } else if (state is WalletsTransferFailure) { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text('Unable to transfer money because ${state.cause}'), + )); + } + }, + builder: (context, state) { + return Center( + child: Column( + children: [ + Text('CAD to USD Rate: $cadToUsdRate'), + WalletsWidget(state: state), + if (state is WalletsLoadSuccess) + _buildTransferButton(context, state), + ], + ), + ); + }, + ), + ); + } + + Widget _buildTransferButton(BuildContext context, WalletsLoadSuccess state) { + final sender = state.wallets[0]; + final receiver = state.wallets[1]; + return RaisedButton( + child: Text( + 'Send 1 USD from ${sender.owner.firstName} to ${receiver.owner.firstName}', + ), + onPressed: () => BlocProvider.of(context).transfer( + sender, + receiver, + Money(1, Currency.usd), + ), + ); + } +} diff --git a/mobile/lib/src/presentation/wallets/wallets_widget.dart b/mobile/lib/src/presentation/wallets/wallets_widget.dart new file mode 100644 index 00000000..3e8b643d --- /dev/null +++ b/mobile/lib/src/presentation/wallets/wallets_widget.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:polydodo/src/application/wallets/wallets_state.dart'; + +import 'wallet_widget.dart'; + +class WalletsWidget extends StatelessWidget { + final WalletsState state; + + const WalletsWidget({Key key, @required this.state}) : super(key: key); + + @override + Widget build(BuildContext context) { + if (state is WalletsLoadSuccess) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: (state as WalletsLoadSuccess) + .wallets + .map((wallet) => Container( + child: WalletWidget(wallet: wallet), + margin: EdgeInsets.all(24), + )) + .toList(), + ); + } + + return SizedBox( + child: CircularProgressIndicator(), + height: 50, + width: 50, + ); + } +} diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index f3a4a78e..6c957e89 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -137,6 +137,13 @@ packages: description: flutter source: sdk version: "0.0.0" + get_it: + dependency: "direct main" + description: + name: get_it + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.4" hive: dependency: "direct main" description: @@ -152,7 +159,7 @@ packages: source: hosted version: "0.12.6" meta: - dependency: transitive + dependency: "direct main" description: name: meta url: "https://pub.dartlang.org" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index dd617208..5cce6d6d 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -33,7 +33,9 @@ dependencies: equatable: ^1.2.5 flutter_bloc: ^6.0.5 flutter_blue: ^0.7.2 + get_it: ^4.0.4 hive: ^1.4.4 + meta: ^1.1.8 protobuf: ^1.0.1 share: ^0.6.5 usb_serial: ^0.2.4 From 428d554239c6ca88041b22f00768d9b0d6902be1 Mon Sep 17 00:00:00 2001 From: William Harvey Date: Sat, 19 Sep 2020 13:32:32 -0400 Subject: [PATCH 06/10] Remove widget test specific to counter app --- mobile/test/widget_test.dart | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 mobile/test/widget_test.dart diff --git a/mobile/test/widget_test.dart b/mobile/test/widget_test.dart deleted file mode 100644 index 53a930a0..00000000 --- a/mobile/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:Polydodo/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} From 118ed8586a1e44e3c5f59481178f4fcba31594e5 Mon Sep 17 00:00:00 2001 From: William Harvey Date: Sat, 19 Sep 2020 14:19:55 -0400 Subject: [PATCH 07/10] Create an empty test for pipeline to perform build --- mobile/.gitignore | 1 + mobile/lib/test/widget_test.dart | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 mobile/lib/test/widget_test.dart diff --git a/mobile/.gitignore b/mobile/.gitignore index 9d532b18..eca61f42 100644 --- a/mobile/.gitignore +++ b/mobile/.gitignore @@ -8,6 +8,7 @@ .buildlog/ .history .svn/ +.vscode/ # IntelliJ related *.iml diff --git a/mobile/lib/test/widget_test.dart b/mobile/lib/test/widget_test.dart new file mode 100644 index 00000000..25ac0578 --- /dev/null +++ b/mobile/lib/test/widget_test.dart @@ -0,0 +1,5 @@ +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async {}); +} From baebeabfbdb4864db765151c2c526cfc27930884 Mon Sep 17 00:00:00 2001 From: William Harvey Date: Sat, 19 Sep 2020 14:28:47 -0400 Subject: [PATCH 08/10] Create an empty test in order for build pipeline to pass --- mobile/lib/test/widget_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/lib/test/widget_test.dart b/mobile/lib/test/widget_test.dart index 25ac0578..295d8358 100644 --- a/mobile/lib/test/widget_test.dart +++ b/mobile/lib/test/widget_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async {}); + testWidgets('Test', (WidgetTester tester) async {}); } From 0c2397572395b9c19602a6431507951f00cdaaba Mon Sep 17 00:00:00 2001 From: William Harvey Date: Sat, 19 Sep 2020 16:55:26 -0400 Subject: [PATCH 09/10] fix mistake: move test/ under mobile/ --- mobile/pubspec.lock | 43 +++++++++++++++----------- mobile/pubspec.yaml | 4 +-- mobile/{lib => }/test/widget_test.dart | 0 3 files changed, 27 insertions(+), 20 deletions(-) rename mobile/{lib => }/test/widget_test.dart (100%) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 6c957e89..cf28699b 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -21,7 +21,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.0-nullsafety" battery: dependency: "direct main" description: @@ -49,28 +49,35 @@ packages: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0-nullsafety.2" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0-nullsafety.2" convert: dependency: transitive description: @@ -105,7 +112,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.0-nullsafety" fixnum: dependency: transitive description: @@ -157,14 +164,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety" meta: dependency: "direct main" description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.2" mime: dependency: transitive description: @@ -185,7 +192,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" plugin_platform_interface: dependency: transitive description: @@ -232,49 +239,49 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.1" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.16" + version: "0.2.19-nullsafety" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.2" usb_serial: dependency: "direct main" description: @@ -295,7 +302,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.2" sdks: - dart: ">=2.7.0 <3.0.0" + dart: ">=2.10.0-137.0 <2.10.0" flutter: ">=1.16.0 <2.0.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 5cce6d6d..c7f7dd29 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `pub publish`. This is preferred for private packages. -publish_to: "none" # Remove this line if you wish to publish to pub.dev +publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.7.0 <3.0.0' dependencies: flutter: diff --git a/mobile/lib/test/widget_test.dart b/mobile/test/widget_test.dart similarity index 100% rename from mobile/lib/test/widget_test.dart rename to mobile/test/widget_test.dart From 9bbde0aa8c3505c06eaa891be681f19399663aea Mon Sep 17 00:00:00 2001 From: William Harvey Date: Fri, 25 Sep 2020 00:07:41 -0400 Subject: [PATCH 10/10] add venv to gitignoe && remove useless print in wallets_route --- backend/.gitignore | 1 + mobile/lib/src/presentation/wallets/wallets_route.dart | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 backend/.gitignore diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 00000000..0cafc1cd --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1 @@ +.venv/ \ No newline at end of file diff --git a/mobile/lib/src/presentation/wallets/wallets_route.dart b/mobile/lib/src/presentation/wallets/wallets_route.dart index 842784d5..c5e9af1e 100644 --- a/mobile/lib/src/presentation/wallets/wallets_route.dart +++ b/mobile/lib/src/presentation/wallets/wallets_route.dart @@ -18,7 +18,6 @@ class WalletsRoute extends StatelessWidget { appBar: AppBar(title: Text('Polydodo')), body: BlocConsumer( listener: (context, state) { - print(state.runtimeType); if (state is WalletsLoadFailure) { Scaffold.of(context).showSnackBar(SnackBar( content: Text('Unable to load Wallets because ${state.cause}'),