Build `crane` demo as deferred component (#461)
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 2a761ab..f87c9b1 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -63,4 +63,5 @@
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
+ implementation "com.google.android.play:core:1.8.0"
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 7a5f72a..e333832 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,6 +8,7 @@
FlutterApplication and put your custom class here. -->
<application
android:label="Flutter Gallery"
+ android:name="io.flutter.app.FlutterPlayStoreSplitApplication"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
@@ -42,5 +43,6 @@
android:name="flutterEmbedding"
android:value="2"/>
</activity>
+ <meta-data android:name="io.flutter.embedding.engine.deferredcomponents.DeferredComponentManager.loadingUnitMapping" android:value="2:crane,3:,4:,5:,6:,7:,8:,9:,10:,11:"/>
</application>
</manifest>
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b0907ab
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="craneName">crane</string>
+</resources>
diff --git a/android/build.gradle b/android/build.gradle
index b7faad8..c505a86 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,12 +1,12 @@
buildscript {
- ext.kotlin_version = '1.2.71'
+ ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
diff --git a/android/crane/build.gradle b/android/crane/build.gradle
new file mode 100644
index 0000000..4eb7e49
--- /dev/null
+++ b/android/crane/build.gradle
@@ -0,0 +1,46 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: "com.android.dynamic-feature"
+
+android {
+ compileSdkVersion 30
+
+ sourceSets {
+ applicationVariants.all { variant ->
+ main.assets.srcDirs += "${project.buildDir}/intermediates/flutter/${variant.name}/deferred_assets"
+ main.jniLibs.srcDirs += "${project.buildDir}/intermediates/flutter/${variant.name}/deferred_libs"
+ }
+ }
+
+ defaultConfig {
+ minSdkVersion 16
+ targetSdkVersion 30
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ compileOptions {
+ sourceCompatibility 1.8
+ targetCompatibility 1.8
+ }
+}
+
+dependencies {
+ implementation project(":app")
+}
diff --git a/android/crane/src/main/AndroidManifest.xml b/android/crane/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..eb7cb07
--- /dev/null
+++ b/android/crane/src/main/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:dist="http://schemas.android.com/apk/distribution"
+ package="com.example.gallery.crane">
+
+ <dist:module
+ dist:instant="false"
+ dist:title="@string/craneName">
+ <dist:delivery>
+ <dist:on-demand />
+ </dist:delivery>
+ <dist:fusing dist:include="true" />
+ </dist:module>
+</manifest>
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 2819f02..bc6a58a 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
index f6e4cd3..7cb0e47 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,4 +1,4 @@
-include ':app'
+include ':app', ':crane'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
diff --git a/deferred_components_loading_units.yaml b/deferred_components_loading_units.yaml
new file mode 100644
index 0000000..0949ae1
--- /dev/null
+++ b/deferred_components_loading_units.yaml
@@ -0,0 +1,149 @@
+# ==============================================================================
+# The contents of this file are automatically generated and it is not
+# recommended to modify this file manually.
+# ==============================================================================
+#
+# In order to prevent unexpected splitting of deferred apps, this file records
+# the last generated set of loading units. It only possible to obtain the final
+# configuration of loading units after compilation is complete. This means
+# improperly setup deferred imports can only be detected after compilation.
+#
+# This file allows the build tool to detect any changes in the generated
+# loading units. During the next build attempt, loading units in this file are
+# compared against the newly generated loading units to check for any new or
+# removed loading units. In the case where loading units do not match, the build
+# will fail and ask the developer to verify that the `deferred-components`
+# configuration in `pubspec.yaml` is correct. Developers should make any
+# necessary changes to integrate new and changed loading units or remove no
+# longer existing loading units from the configuration. The build command should
+# then be re-run to continue the build process.
+#
+# Sometimes, changes to the generated loading units may be unintentional. If
+# the list of loading units in this file is not what is expected, the app's
+# deferred imports should be reviewed. Third party plugins and packages may
+# also introduce deferred imports that result in unexpected loading units.
+loading-units:
+ - id: 2
+ libraries:
+ - package:flutter_staggered_grid_view/src/rendering/sliver_staggered_grid.dart
+ - package:flutter_staggered_grid_view/src/rendering/sliver_variable_size_box_adaptor.dart
+ - package:flutter_staggered_grid_view/src/rendering/tile_container_render_object_mixin.dart
+ - package:flutter_staggered_grid_view/src/widgets/sliver.dart
+ - package:flutter_staggered_grid_view/src/widgets/staggered_grid_view.dart
+ - package:flutter_staggered_grid_view/src/widgets/staggered_tile.dart
+ - package:gallery/layout/highlight_focus.dart
+ - package:gallery/studies/crane/app.dart
+ - package:gallery/studies/crane/backdrop.dart
+ - package:gallery/studies/crane/eat_form.dart
+ - package:gallery/studies/crane/fly_form.dart
+ - package:gallery/studies/crane/sleep_form.dart
+ - package:gallery/studies/crane/theme.dart
+ - package:gallery/studies/crane/backlayer.dart
+ - package:gallery/studies/crane/border_tab_indicator.dart
+ - package:gallery/studies/crane/header_form.dart
+ - package:gallery/studies/crane/item_cards.dart
+ - package:gallery/studies/crane/model/data.dart
+ - package:gallery/studies/crane/model/destination.dart
+ - package:gallery/studies/crane/model/formatters.dart
+ - id: 3
+ libraries:
+ - package:gallery/studies/fortnightly/app.dart
+ - package:gallery/studies/fortnightly/shared.dart
+ - id: 4
+ libraries:
+ - package:gallery/studies/rally/app.dart
+ - package:gallery/studies/rally/home.dart
+ - package:gallery/studies/rally/login.dart
+ - package:gallery/studies/rally/charts/line_chart.dart
+ - package:gallery/studies/rally/data.dart
+ - package:gallery/studies/rally/formatters.dart
+ - package:gallery/studies/rally/charts/pie_chart.dart
+ - package:gallery/studies/rally/charts/vertical_fraction_bar.dart
+ - package:gallery/studies/rally/finance.dart
+ - package:gallery/studies/rally/tabs/accounts.dart
+ - package:gallery/studies/rally/tabs/bills.dart
+ - package:gallery/studies/rally/tabs/budgets.dart
+ - package:gallery/studies/rally/tabs/overview.dart
+ - package:gallery/studies/rally/tabs/settings.dart
+ - package:gallery/studies/rally/tabs/sidebar.dart
+ - id: 5
+ libraries:
+ - package:gallery/studies/shrine/app.dart
+ - package:gallery/studies/shrine/backdrop.dart
+ - package:gallery/studies/shrine/category_menu_page.dart
+ - package:gallery/studies/shrine/expanding_bottom_sheet.dart
+ - package:gallery/studies/shrine/home.dart
+ - package:gallery/studies/shrine/login.dart
+ - package:gallery/studies/shrine/model/app_state_model.dart
+ - package:gallery/studies/shrine/model/product.dart
+ - package:gallery/studies/shrine/page_status.dart
+ - package:gallery/studies/shrine/scrim.dart
+ - package:gallery/studies/shrine/supplemental/layout_cache.dart
+ - package:gallery/studies/shrine/theme.dart
+ - package:scoped_model/scoped_model.dart
+ - package:gallery/studies/shrine/triangle_category_indicator.dart
+ - package:gallery/studies/shrine/shopping_cart.dart
+ - package:gallery/studies/shrine/supplemental/asymmetric_view.dart
+ - package:gallery/studies/shrine/model/products_repository.dart
+ - package:gallery/studies/shrine/supplemental/balanced_layout.dart
+ - package:gallery/studies/shrine/supplemental/desktop_product_columns.dart
+ - package:gallery/studies/shrine/supplemental/product_columns.dart
+ - package:gallery/studies/shrine/supplemental/product_card.dart
+ - package:gallery/studies/shrine/supplemental/cut_corners_border.dart
+ - id: 6
+ libraries:
+ - package:gallery/demos/cupertino/cupertino_demos.dart
+ - package:gallery/demos/cupertino/cupertino_activity_indicator_demo.dart
+ - package:gallery/demos/cupertino/cupertino_alert_demo.dart
+ - package:gallery/demos/cupertino/cupertino_button_demo.dart
+ - package:gallery/demos/cupertino/cupertino_context_menu_demo.dart
+ - package:gallery/demos/cupertino/cupertino_navigation_bar_demo.dart
+ - package:gallery/demos/cupertino/cupertino_picker_demo.dart
+ - package:gallery/demos/cupertino/cupertino_refresh_demo.dart
+ - package:gallery/demos/cupertino/cupertino_segmented_control_demo.dart
+ - package:gallery/demos/cupertino/cupertino_slider_demo.dart
+ - package:gallery/demos/cupertino/cupertino_switch_demo.dart
+ - package:gallery/demos/cupertino/cupertino_tab_bar_demo.dart
+ - package:gallery/demos/cupertino/cupertino_text_field_demo.dart
+ - id: 7
+ libraries:
+ - package:gallery/demos/material/material_demos.dart
+ - package:gallery/demos/material/app_bar_demo.dart
+ - package:gallery/demos/material/banner_demo.dart
+ - package:gallery/demos/material/bottom_app_bar_demo.dart
+ - package:gallery/demos/material/bottom_navigation_demo.dart
+ - package:gallery/demos/material/bottom_sheet_demo.dart
+ - package:gallery/demos/material/button_demo.dart
+ - package:gallery/demos/material/cards_demo.dart
+ - package:gallery/demos/material/chip_demo.dart
+ - package:gallery/demos/material/data_table_demo.dart
+ - package:gallery/demos/material/dialog_demo.dart
+ - package:gallery/demos/material/divider_demo.dart
+ - package:gallery/demos/material/grid_list_demo.dart
+ - package:gallery/demos/material/list_demo.dart
+ - package:gallery/demos/material/menu_demo.dart
+ - package:gallery/demos/material/navigation_drawer.dart
+ - package:gallery/demos/material/navigation_rail_demo.dart
+ - package:gallery/demos/material/picker_demo.dart
+ - package:gallery/demos/material/progress_indicator_demo.dart
+ - package:gallery/demos/material/selection_controls_demo.dart
+ - package:gallery/demos/material/sliders_demo.dart
+ - package:gallery/demos/material/snackbar_demo.dart
+ - package:gallery/demos/material/tabs_demo.dart
+ - package:gallery/demos/material/text_field_demo.dart
+ - package:gallery/demos/material/tooltip_demo.dart
+ - id: 8
+ libraries:
+ - package:gallery/demos/reference/motion_demo_container_transition.dart
+ - id: 9
+ libraries:
+ - package:gallery/demos/reference/colors_demo.dart
+ - id: 10
+ libraries:
+ - package:gallery/demos/reference/transformations_demo.dart
+ - package:gallery/demos/reference/transformations_demo_board.dart
+ - package:gallery/demos/reference/transformations_demo_edit_board_point.dart
+ - package:gallery/demos/reference/transformations_demo_color_picker.dart
+ - id: 11
+ libraries:
+ - package:gallery/demos/reference/typography_demo.dart
diff --git a/lib/deferred_widget.dart b/lib/deferred_widget.dart
index 63fe89b..a1b7fc2 100644
--- a/lib/deferred_widget.dart
+++ b/lib/deferred_widget.dart
@@ -14,11 +14,14 @@
/// state as long as closure to create widget stays the same.
///
class DeferredWidget extends StatefulWidget {
- DeferredWidget(this.libraryLoader, this.createWidget, {Key key})
- : super(key: key);
+ DeferredWidget(this.libraryLoader, this.createWidget,
+ {Key key, Widget placeholder})
+ : placeholder = placeholder ?? Container(),
+ super(key: key);
final LibraryLoader libraryLoader;
final DeferredWidgetBuilder createWidget;
+ final Widget placeholder;
static final Map<LibraryLoader, Future<void>> _moduleLoaders = {};
static final Set<LibraryLoader> _loadedModules = {};
@@ -68,6 +71,43 @@
_loadedCreator = widget.createWidget;
_loadedChild = _loadedCreator();
}
- return _loadedChild ?? Container();
+ return _loadedChild ?? widget.placeholder;
+ }
+}
+
+/// Displays a progress indicator and text description explaining that
+/// the widget is a deferred component and is currently being installed.
+class DeferredLoadingPlaceholder extends StatelessWidget {
+ DeferredLoadingPlaceholder({String name = 'This widget'}) : name = name;
+
+ final String name;
+
+ @override
+ Widget build(BuildContext context) {
+ return Center(
+ child: Container(
+ child: Column(
+ children: <Widget>[
+ Text('$name is installing.',
+ style: Theme.of(context).textTheme.headline4),
+ Container(height: 10),
+ Text(
+ '$name is a deferred component which are downloaded and installed at runtime.',
+ style: Theme.of(context).textTheme.bodyText1),
+ Container(height: 20),
+ const Center(child: CircularProgressIndicator()),
+ ],
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ ),
+ decoration: BoxDecoration(
+ color: Colors.grey[700],
+ border: Border.all(
+ width: 20,
+ color: Colors.grey[700],
+ ),
+ borderRadius: const BorderRadius.all(Radius.circular(10))),
+ width: 250,
+ ));
}
}
diff --git a/lib/routes.dart b/lib/routes.dart
index 1d4eb78..38bd754 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -67,7 +67,8 @@
r'^' + crane_routes.defaultRoute,
(context, match) => StudyWrapper(
study: DeferredWidget(crane.loadLibrary,
- () => crane.CraneApp()), // ignore: prefer_const_constructors
+ () => crane.CraneApp(), // ignore: prefer_const_constructors
+ placeholder: DeferredLoadingPlaceholder(name: 'Crane')),
),
),
Path(
diff --git a/pubspec.yaml b/pubspec.yaml
index b3237f8..ff8dd3e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -43,6 +43,54 @@
web_benchmarks: ^0.0.5
flutter:
+ deferred-components:
+ - name: crane
+ libraries:
+ # Only one library from the loading unit is necessary.
+ - package:gallery/studies/crane/app.dart
+ assets:
+ - packages/flutter_gallery_assets/crane/destinations/eat_1.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_2.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_3.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_4.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_5.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_6.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_7.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_8.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_9.jpg
+ - packages/flutter_gallery_assets/crane/destinations/eat_10.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_0.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_1.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_2.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_3.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_4.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_5.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_6.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_7.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_8.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_9.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_10.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_11.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_12.jpg
+ - packages/flutter_gallery_assets/crane/destinations/fly_13.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_0.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_1.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_2.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_3.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_4.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_5.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_6.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_7.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_8.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_9.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_10.jpg
+ - packages/flutter_gallery_assets/crane/destinations/sleep_11.jpg
+ - packages/flutter_gallery_assets/crane/logo/logo.png
+ - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Medium.ttf
+ - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-SemiBold.ttf
+ - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Regular.ttf
+ - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Light.ttf
+
assets:
- packages/flutter_gallery_assets/assets/studies/shrine_card_dark.png
- packages/flutter_gallery_assets/assets/studies/starter_card.png
@@ -69,8 +117,6 @@
- packages/flutter_gallery_assets/fonts/google_fonts/Rubik-Bold.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/Merriweather-Light.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/RobotoCondensed-Bold.ttf
- - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Medium.ttf
- - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-SemiBold.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-Regular.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/RobotoMono-Regular.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-ExtraBold.ttf
@@ -78,10 +124,8 @@
- packages/flutter_gallery_assets/fonts/google_fonts/Oswald-SemiBold.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/Oswald-Medium.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-SemiBold.ttf
- - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Regular.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/Montserrat-Bold.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/Merriweather-BoldItalic.ttf
- - packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Light.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/Rubik-Medium.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/Montserrat-SemiBold.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/RobotoCondensed-Regular.ttf
@@ -94,43 +138,6 @@
- packages/flutter_gallery_assets/fonts/google_fonts/WorkSans-Bold.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/WorkSans-Thin.ttf
- packages/flutter_gallery_assets/fonts/google_fonts/WorkSans-SemiBold.ttf
- - packages/flutter_gallery_assets/crane/destinations/eat_1.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_2.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_3.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_4.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_5.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_6.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_7.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_8.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_9.jpg
- - packages/flutter_gallery_assets/crane/destinations/eat_10.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_0.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_1.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_2.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_3.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_4.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_5.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_6.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_7.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_8.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_9.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_10.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_11.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_12.jpg
- - packages/flutter_gallery_assets/crane/destinations/fly_13.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_0.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_1.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_2.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_3.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_4.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_5.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_6.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_7.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_8.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_9.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_10.jpg
- - packages/flutter_gallery_assets/crane/destinations/sleep_11.jpg
- - packages/flutter_gallery_assets/crane/logo/logo.png
- packages/flutter_gallery_assets/fortnightly/fortnightly_army.png
- packages/flutter_gallery_assets/fortnightly/fortnightly_bees.jpg
- packages/flutter_gallery_assets/fortnightly/fortnightly_chart.png