Please also see the contribution guide in the root folder.
- Install Flutter
- Open a terminal in VSCode in the
app
directory- Run
dart pub get
to fetch all dart dependencies - Run
flutter pub get
to fetch all flutter dependencies and setup all generated code - Run
dart run build_runner build --delete-conflicting-outputs
ordart run build_runner watch --delete-conflicting-outputs
to re-generate code upon file changes while developing
- Run
You should now be able to run the app by opening the debug panel on the left and pressing the green triangle at the top (or using the shortcut F5).
For (cleaning) generated code, you might want to add the following aliases to your shell configuration:
alias flutter-generate='dart run build_runner build --delete-conflicting-outputs'
alias flutter-clean='find . -maxdepth 20 -type f \( -name "*.inject.summary" -o -name "*.inject.dart" -o -name "*.g.dart" \) -delete'
... can be super painful, because Java, Gradle, and Kotlin versions may be wrong.
Often problems in packages arise that rely on older Gradle versions.
The places to check are:
- Your Flutter version
- Your
JAVA_HOME
version - The Gradle version in
gradle-wrapper.properties
; the recommended versions are "between 7.3 and 7.6.1." (see Android Java Gradle migration guide) - The Java version in
android/app/build/gradle
- The Java version used for Gradle (check in Android Studio)
- The Kotlin version in
settings.gradle
The app consists of multiple so-called modules. Our main modules (usually app
screens) correspond to the direct subfolders of lib/
.
Common functions used by modules such as models
, widgets
, and utilities
are living in common
. All such functions are exported from
common/module.dart
.
The structure of an example module lib/my_module
should look as follows:
my_module
module.dart
(see example below):- exports everything that is required by other modules, i.e., page(s) and possibly the cubit
- declares all routes as functions returning
AutoRoute
- may contain initialization code (
initMyModule()
)
widgets
:my_widget.dart
: containsMyWidget
and helpers
pages
:my_module.dart
: containsMyModulePage
and helpersmy_child_page.dart
: containsmy_complex_page
: create a folder for complex pages (e.g., tabbed ones); might want to create an own module if getting too complex
utils.dart
: contains utilities used throughout this modulecubit.dart
: containsMyModuleCubit
andMyModuleState
s (if needed)
Example for my_module/module.dart
; the page is used as a root page in the tab
router, which is why the empty router MyModuleRootPage
and adding
AutoRoute(path: '', page: MyModuleRoute.page)
to children is needed.
import '../common/module.dart';
// For generated routes
export 'cubit.dart';
export 'pages/my_module.dart';
export 'pages/my_child_page.dart';
export 'pages/my_complex_page/page.dart';
@RoutePage()
class MyModuleRootPage extends AutoRouter {}
AutoRoute myChildRoute() => AutoRoute(
path: 'my_child',
page: MyChildRoute.page,
);
AutoRoute myComplexRoute() => AutoRoute(
path: 'my_complex',
page: MyComplexRoute.page,
);
AutoRoute myModuleRoute({ required List<AutoRoute> children }) => AutoRoute(
path: 'my_module',
page: MyModuleRootRoute.page,
children: [
AutoRoute(path: '', page: MyModuleRoute.page),
...children, // includes myChildRoute()
],
);
Add the icon as assets/icon/icon.png
(configured in pubspec.yaml
) and run
flutter pub run flutter_launcher_icons:main
This will generate icons for both iOS as well as Android.
🙅 Not working yet due to login redirect, but keeping script for Sinai version (login without redirect) – can adopt once different login types are supported.
Scripts were created to click through the app using tests and record the screen.
A simulator with the app in its initial state (or not installed) needs to be running.
The generate_screendocs/generate_screencast.sh
script will create screencast.
It uses Xcode to record the screencast and ffmpeg
to cut the full.mov
to relevant subsets (needs to be installed).
To generate GIFs used in the Tutorial, ImageMagick is used (which also needs to be installed).
Run the script with bash generate_screendocs/generate_screencast.sh
.
To update the screenshots in ../docs/screenshots
(used in 📑 App screens,
📑 User instructions, and the
README), run the following command:
bash generate_screendocs/generate_screenshots.sh
.
If the error The following MissingPluginException was thrown running a test: MissingPluginException(No implementation found for method captureScreenshot on channel plugins.flutter.io/integration_test)
occurs, the registration in the
file
ios/.symlinks/plugins/integration_test/ios/Classes/IntegrationTestPlugin.m
needs to be adapted (see
issue):
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
[[IntegrationTestPlugin instance] setupChannels:registrar.messenger];
}
If you would like to test with specific test data but you don't have a user with
suitable data available, adapt the code in utilities/genome_data.dart
as
shown below.
// TODO(after-testing): remove test data adaption
UserData.instance.labData = UserData.instance.labData!.filter(
(labResult) => labResult.gene != 'UGT1A1'
).toList();
UserData.instance.labData!.add(LabResult(
gene: 'UGT1A1',
variant: '*28/*28',
phenotype: 'Poor Metabolizer',
allelesTested: '',
));
UserData.instance.labData = UserData.instance.labData!.filter(
(labResult) => labResult.gene != 'HLA-B' && labResult.variant != '*57:01 negative'
).toList();
UserData.instance.labData!.add(LabResult(
gene: 'HLA-B',
variant: '*57:01 positive',
phenotype: '*57:01 positive',
allelesTested: '',
));
You can use the CPIC API to get reasonable genotype-phenotype pairings, e.g.,
with
https://api.cpicpgx.org/v1/diplotype?genesymbol=eq.CYP2C9&select=genesymbol,diplotype,generesult
.
Some more examples are collected below (this is for testing what is shown for Warfarin):
UserData.instance.diplotypes!['CYP2C9'] = Diplotype(
gene: 'CYP2C9',
resultType: 'Diplotype',
genotype: '*11/*13',
phenotype: 'Poor Metabolizer',
allelesTested: '',
);
UserData.instance.diplotypes!['VKORC1'] = Diplotype(
gene: 'VKORC1',
resultType: 'Diplotype',
genotype: '-1639G>A variant carriers',
phenotype: '-1639G>A variant carriers',
allelesTested: '',
);
UserData.instance.diplotypes!['CYP4F2'] = Diplotype(
gene: 'CYP4F2',
resultType: 'Diplotype',
genotype: 'rs2108622 T carriers',
phenotype: 'rs2108622 T carriers',
allelesTested: '',
);
UserData.instance.diplotypes!['CYP2C'] = Diplotype(
gene: 'CYP2C',
resultType: 'Diplotype',
genotype: 'rs12777823 A carriers',
phenotype: 'rs12777823 A carriers',
allelesTested: '',
);