[adaptive_scaffold] Clean up `adaptive_scaffold` package (#2558)
diff --git a/packages/adaptive_scaffold/README.md b/packages/adaptive_scaffold/README.md
index 1983704..5be72ea 100644
--- a/packages/adaptive_scaffold/README.md
+++ b/packages/adaptive_scaffold/README.md
@@ -1,18 +1,37 @@
<?code-excerpt path-base="excerpts/packages/adaptive_scaffold_example"?>
-# Helper Widgets for Making Adaptive Layouts in Flutter (AdaptiveScaffold)
+# Adaptive Scaffold
-This package contains some helper widgets that make the process of developing adaptive layouts easier, especially with navigational elements.
+`AdaptiveScaffold` reacts to input from users, devices and screen elements and
+renders your Flutter application according to the
+[Material 3](https://m3.material.io/foundations/adaptive-design/overview)
+guidelines.
-To see examples of using these helper widgets to make a simple but common adaptive layout:
+To see examples of using these widgets to make a simple but common adaptive
+layout:
```bash
cd example/
flutter run --release
```
-## AdaptiveScaffold:
-AdaptiveScaffold implements the basic visual layout structure for Material Design 3 that adapts to a variety of screens. It provides a preset of layout, including positions and animations, by handling macro changes in navigational elements and bodies based on the current features of the screen, namely screen width and platform. For example, the navigational elements would be a BottomNavigationBar on a small mobile device and a NavigationRail on larger devices. The body is the primary screen that takes up the space left by the navigational elements. The secondaryBody acts as an option to split the space between two panes for purposes such as having a detail view. There is some automatic functionality with foldables to handle the split between panels properly. AdaptiveScaffold is much simpler to use but is not the best if you would like high customizability. Apps that would like more refined layout and/or animation should use AdaptiveLayout.
-### Example Usage:
+
+## AdaptiveScaffold
+
+AdaptiveScaffold implements the basic visual layout structure for Material
+Design 3 that adapts to a variety of screens. It provides a preset of layout,
+including positions and animations, by handling macro changes in navigational
+elements and bodies based on the current features of the screen, namely screen
+width and platform. For example, the navigational elements would be a
+BottomNavigationBar on a small mobile device and a NavigationRail on larger
+devices. The body is the primary screen that takes up the space left by the
+navigational elements. The secondaryBody acts as an option to split the space
+between two panes for purposes such as having a detail view. There is some
+automatic functionality with foldables to handle the split between panels
+properly. AdaptiveScaffold is much simpler to use but is not the best if you
+would like high customizability. Apps that would like more refined layout and/or
+animation should use AdaptiveLayout.
+
+### Example Usage
<?code-excerpt "adaptive_scaffold_demo.dart (Example)"?>
```dart
@@ -22,16 +41,20 @@
final List<Widget> children = <Widget>[
for (int i = 0; i < 10; i++)
Padding(
- padding: const EdgeInsets.all(8.0),
- child: Container(
- color: const Color.fromARGB(255, 255, 201, 197), height: 400))
+ padding: const EdgeInsets.all(8.0),
+ child: Container(
+ color: const Color.fromARGB(255, 255, 201, 197),
+ height: 400,
+ ),
+ )
];
return BottomNavigationBarTheme(
data: const BottomNavigationBarThemeData(
- unselectedItemColor: Colors.black,
- selectedItemColor: Colors.black,
- backgroundColor: Colors.white),
+ unselectedItemColor: Colors.black,
+ selectedItemColor: Colors.black,
+ backgroundColor: Colors.white,
+ ),
child: AdaptiveScaffold(
// An option to override the default breakpoints used for small, medium,
// and large.
@@ -50,29 +73,47 @@
],
body: (_) => GridView.count(crossAxisCount: 2, children: children),
smallBody: (_) => ListView.builder(
- itemCount: children.length,
- itemBuilder: (_, int idx) => children[idx]),
+ itemCount: children.length,
+ itemBuilder: (_, int idx) => children[idx],
+ ),
// Define a default secondaryBody.
secondaryBody: (_) =>
Container(color: const Color.fromARGB(255, 234, 158, 192)),
// Override the default secondaryBody during the smallBreakpoint to be
// empty. Must use AdaptiveScaffold.emptyBuilder to ensure it is properly
- // overriden.
+ // overridden.
smallSecondaryBody: AdaptiveScaffold.emptyBuilder));
}
}
```
## The Background Widget Suite
-These are the set of widgets that are used on a lower level and offer more customizability at a cost of more lines of code.
-#### AdaptiveLayout:
+
+These are the set of widgets that are used on a lower level and offer more
+customizability at a cost of more lines of code.
+
+### AdaptiveLayout
+
!["AdaptiveLayout's Assigned Slots Displayed on Screen"](example/demo_files/screenSlots.png)
-AdaptiveLayout is the top-level widget class that arranges the layout of the slots and their animation, similar to Scaffold. It takes in several LayoutSlots and returns an appropriate layout based on the diagram above. AdaptiveScaffold is built upon AdaptiveLayout internally but abstracts some of the complexity with presets based on the Material 3 Design specification.
-#### SlotLayout:
-SlotLayout handles the adaptivity or the changes between widgets at certain Breakpoints. It also holds the logic for animating between breakpoints. It takes SlotLayoutConfigs mapped to Breakpoints in a config and displays a widget based on that information.
-#### SlotLayout.from:
-SlotLayout.from creates a SlotLayoutConfig holds the actual widget to be displayed and the entrance animation and exit animation.
-### Example Usage:
+AdaptiveLayout is the top-level widget class that arranges the layout of the
+slots and their animation, similar to Scaffold. It takes in several LayoutSlots
+and returns an appropriate layout based on the diagram above. AdaptiveScaffold
+is built upon AdaptiveLayout internally but abstracts some of the complexity
+with presets based on the Material 3 Design specification.
+
+### SlotLayout
+
+SlotLayout handles the adaptivity or the changes between widgets at certain
+Breakpoints. It also holds the logic for animating between breakpoints. It takes
+SlotLayoutConfigs mapped to Breakpoints in a config and displays a widget based
+on that information.
+
+### SlotLayout.from
+
+SlotLayout.from creates a SlotLayoutConfig holds the actual widget to be
+displayed and the entrance animation and exit animation.
+
+### Example Usage
<?code-excerpt "adaptive_layout_demo.dart (Example)"?>
```dart
@@ -86,24 +127,26 @@
config: <Breakpoint, SlotLayoutConfig>{
Breakpoints.medium: SlotLayout.from(
inAnimation: AdaptiveScaffold.leftOutIn,
- key: const Key('pnav1'),
+ key: const Key('Primary Navigation Medium'),
builder: (_) => AdaptiveScaffold.standardNavigationRail(
- leading: const Icon(Icons.menu),
- destinations: destinations
- .map((_) => AdaptiveScaffold.toRailDestination(_))
- .toList()),
+ leading: const Icon(Icons.menu),
+ destinations: destinations
+ .map((_) => AdaptiveScaffold.toRailDestination(_))
+ .toList(),
+ ),
),
Breakpoints.large: SlotLayout.from(
- key: const Key('pn1'),
+ key: const Key('Primary Navigation Large'),
inAnimation: AdaptiveScaffold.leftOutIn,
builder: (_) => AdaptiveScaffold.standardNavigationRail(
extended: true,
leading: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const <Widget>[
- Text('REPLY',
- style:
- TextStyle(color: Color.fromARGB(255, 255, 201, 197))),
+ Text(
+ 'REPLY',
+ style: TextStyle(color: Color.fromARGB(255, 255, 201, 197)),
+ ),
Icon(Icons.menu_open)
],
),
@@ -120,14 +163,14 @@
body: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
Breakpoints.small: SlotLayout.from(
- key: const Key('body'),
+ key: const Key('Body Small'),
builder: (_) => ListView.builder(
itemCount: children.length,
itemBuilder: (BuildContext context, int index) => children[index],
),
),
Breakpoints.mediumAndUp: SlotLayout.from(
- key: const Key('body1'),
+ key: const Key('Body Medium'),
builder: (_) =>
GridView.count(crossAxisCount: 2, children: children),
)
@@ -138,14 +181,15 @@
bottomNavigation: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
Breakpoints.small: SlotLayout.from(
- key: const Key('bn'),
+ key: const Key('Bottom Navigation Small'),
inAnimation: AdaptiveScaffold.bottomToTop,
outAnimation: AdaptiveScaffold.topToBottom,
builder: (_) => BottomNavigationBarTheme(
- data: const BottomNavigationBarThemeData(
- selectedItemColor: Colors.black),
- child: AdaptiveScaffold.standardBottomNavigationBar(
- destinations: destinations)),
+ data: const BottomNavigationBarThemeData(
+ selectedItemColor: Colors.black),
+ child: AdaptiveScaffold.standardBottomNavigationBar(
+ destinations: destinations),
+ ),
)
},
),
@@ -153,9 +197,11 @@
}
}
```
-##
+
Both of the examples shown here produce the same output:
!["Example of a display made with AdaptiveScaffold"](example/demo_files/adaptiveScaffold.gif)
## Additional information
-You can find more information on this package and its usage in the public [design doc](https://docs.google.com/document/d/1qhrpTWYs5f67X8v32NCCNTRMIjSrVHuaMEFAul-Q_Ms/edit?usp=sharing).
+
+You can find more information on this package and its usage in the public
+[design doc](https://docs.google.com/document/d/1qhrpTWYs5f67X8v32NCCNTRMIjSrVHuaMEFAul-Q_Ms/edit?usp=sharing).
diff --git a/packages/adaptive_scaffold/example/.metadata b/packages/adaptive_scaffold/example/.metadata
index 7586be5..d2eb7d5 100644
--- a/packages/adaptive_scaffold/example/.metadata
+++ b/packages/adaptive_scaffold/example/.metadata
@@ -4,8 +4,8 @@
# This file should be version controlled.
version:
- revision: 57f2ff0d286c95e6c2385abc29efc9e2d298797c
- channel: sliverQuickDocumentationFix
+ revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
+ channel: stable
project_type: app
@@ -13,11 +13,11 @@
migration:
platforms:
- platform: root
- create_revision: 57f2ff0d286c95e6c2385abc29efc9e2d298797c
- base_revision: 57f2ff0d286c95e6c2385abc29efc9e2d298797c
+ create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
+ base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
- platform: windows
- create_revision: 57f2ff0d286c95e6c2385abc29efc9e2d298797c
- base_revision: 57f2ff0d286c95e6c2385abc29efc9e2d298797c
+ create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
+ base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c
# User provided section
diff --git a/packages/adaptive_scaffold/example/android/.gitignore b/packages/adaptive_scaffold/example/android/.gitignore
index bc2100d..6f56801 100644
--- a/packages/adaptive_scaffold/example/android/.gitignore
+++ b/packages/adaptive_scaffold/example/android/.gitignore
@@ -5,3 +5,9 @@
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/packages/adaptive_scaffold/example/android/app/build.gradle b/packages/adaptive_scaffold/example/android/app/build.gradle
index 52a9e4f..b80bb84 100644
--- a/packages/adaptive_scaffold/example/android/app/build.gradle
+++ b/packages/adaptive_scaffold/example/android/app/build.gradle
@@ -26,23 +26,31 @@
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion 31
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
- lintOptions {
- disable 'InvalidPackage'
- }
-
defaultConfig {
- applicationId "dev.flutter.packages.adaptive_scaffold.example"
- minSdkVersion 16
- targetSdkVersion 28
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "dev.flutter.example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -60,7 +68,4 @@
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test:runner:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
diff --git a/packages/adaptive_scaffold/example/android/app/src/debug/AndroidManifest.xml b/packages/adaptive_scaffold/example/android/app/src/debug/AndroidManifest.xml
index 9b5b60e..30b46fd 100644
--- a/packages/adaptive_scaffold/example/android/app/src/debug/AndroidManifest.xml
+++ b/packages/adaptive_scaffold/example/android/app/src/debug/AndroidManifest.xml
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="dev.flutter.packages.adaptive_scaffold.example">
- <!-- Flutter needs it to communicate with the running application
+ package="dev.flutter.example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
diff --git a/packages/adaptive_scaffold/example/android/app/src/main/AndroidManifest.xml b/packages/adaptive_scaffold/example/android/app/src/main/AndroidManifest.xml
index b7881a3..b4b2722 100644
--- a/packages/adaptive_scaffold/example/android/app/src/main/AndroidManifest.xml
+++ b/packages/adaptive_scaffold/example/android/app/src/main/AndroidManifest.xml
@@ -1,15 +1,25 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="dev.flutter.packages.adaptive_scaffold.example">
- <application
+ package="dev.flutter.example">
+ <application
android:label="example"
+ android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
+ android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
diff --git a/packages/adaptive_scaffold/example/android/app/src/main/kotlin/dev/flutter/packages/animations/example/MainActivity.kt b/packages/adaptive_scaffold/example/android/app/src/main/kotlin/dev/flutter/example/MainActivity.kt
similarity index 82%
rename from packages/adaptive_scaffold/example/android/app/src/main/kotlin/dev/flutter/packages/animations/example/MainActivity.kt
rename to packages/adaptive_scaffold/example/android/app/src/main/kotlin/dev/flutter/example/MainActivity.kt
index 725c17a..a17091e 100644
--- a/packages/adaptive_scaffold/example/android/app/src/main/kotlin/dev/flutter/packages/animations/example/MainActivity.kt
+++ b/packages/adaptive_scaffold/example/android/app/src/main/kotlin/dev/flutter/example/MainActivity.kt
@@ -1,10 +1,10 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package dev.flutter.packages.adaptive_scaffold.example
+
+package dev.flutter.example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
-
}
diff --git a/packages/adaptive_scaffold/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/adaptive_scaffold/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/packages/adaptive_scaffold/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/packages/adaptive_scaffold/example/android/app/src/main/res/values-night/styles.xml b/packages/adaptive_scaffold/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/packages/adaptive_scaffold/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/packages/adaptive_scaffold/example/android/app/src/main/res/values/styles.xml b/packages/adaptive_scaffold/example/android/app/src/main/res/values/styles.xml
index 00fa441..cb1ef88 100644
--- a/packages/adaptive_scaffold/example/android/app/src/main/res/values/styles.xml
+++ b/packages/adaptive_scaffold/example/android/app/src/main/res/values/styles.xml
@@ -1,8 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
- Flutter draws its first frame -->
+ the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
</resources>
diff --git a/packages/adaptive_scaffold/example/android/app/src/profile/AndroidManifest.xml b/packages/adaptive_scaffold/example/android/app/src/profile/AndroidManifest.xml
index 9b5b60e..30b46fd 100644
--- a/packages/adaptive_scaffold/example/android/app/src/profile/AndroidManifest.xml
+++ b/packages/adaptive_scaffold/example/android/app/src/profile/AndroidManifest.xml
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="dev.flutter.packages.adaptive_scaffold.example">
- <!-- Flutter needs it to communicate with the running application
+ package="dev.flutter.example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
diff --git a/packages/adaptive_scaffold/example/android/build.gradle b/packages/adaptive_scaffold/example/android/build.gradle
index 2092f9d..58a8c74 100644
--- a/packages/adaptive_scaffold/example/android/build.gradle
+++ b/packages/adaptive_scaffold/example/android/build.gradle
@@ -1,12 +1,12 @@
buildscript {
- ext.kotlin_version = '1.6.0'
+ ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
diff --git a/packages/adaptive_scaffold/example/android/gradle.properties b/packages/adaptive_scaffold/example/android/gradle.properties
index 38c8d45..94adc3a 100644
--- a/packages/adaptive_scaffold/example/android/gradle.properties
+++ b/packages/adaptive_scaffold/example/android/gradle.properties
@@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
-android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
diff --git a/packages/adaptive_scaffold/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/adaptive_scaffold/example/android/gradle/wrapper/gradle-wrapper.properties
index bc6a58a..3c472b9 100644
--- a/packages/adaptive_scaffold/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/adaptive_scaffold/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
diff --git a/packages/adaptive_scaffold/example/android/settings.gradle b/packages/adaptive_scaffold/example/android/settings.gradle
index 5a2f14f..44e62bc 100644
--- a/packages/adaptive_scaffold/example/android/settings.gradle
+++ b/packages/adaptive_scaffold/example/android/settings.gradle
@@ -1,15 +1,11 @@
include ':app'
-def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
-def plugins = new Properties()
-def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
-if (pluginsFile.exists()) {
- pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
-}
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
-plugins.each { name, path ->
- def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
- include ":$name"
- project(":$name").projectDir = pluginDirectory
-}
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/packages/adaptive_scaffold/example/ios/.gitignore b/packages/adaptive_scaffold/example/ios/.gitignore
index e96ef60..7a7f987 100644
--- a/packages/adaptive_scaffold/example/ios/.gitignore
+++ b/packages/adaptive_scaffold/example/ios/.gitignore
@@ -1,3 +1,4 @@
+**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
@@ -18,6 +19,7 @@
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
+Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
diff --git a/packages/adaptive_scaffold/example/ios/Flutter/AppFrameworkInfo.plist b/packages/adaptive_scaffold/example/ios/Flutter/AppFrameworkInfo.plist
index 6b4c0f7..9625e10 100644
--- a/packages/adaptive_scaffold/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/packages/adaptive_scaffold/example/ios/Flutter/AppFrameworkInfo.plist
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
- <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
@@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
- <string>8.0</string>
+ <string>11.0</string>
</dict>
</plist>
diff --git a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.pbxproj b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.pbxproj
index 457892f..fe6e10d 100644
--- a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -90,7 +90,6 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
- 97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
@@ -99,13 +98,6 @@
path = Runner;
sourceTree = "<group>";
};
- 97C146F11CF9000F007C117D /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- );
- name = "Supporting Files";
- sourceTree = "<group>";
- };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -135,8 +127,8 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
- ORGANIZATIONNAME = "The Flutter Authors";
+ LastUpgradeCheck = 1300;
+ ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
@@ -145,7 +137,7 @@
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
- compatibilityVersion = "Xcode 3.2";
+ compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@@ -179,6 +171,7 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -193,6 +186,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -280,7 +274,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -296,19 +290,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
- FRAMEWORK_SEARCH_PATHS = (
- "$(inherited)",
- "$(PROJECT_DIR)/Flutter",
- );
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- LIBRARY_SEARCH_PATHS = (
+ LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/Flutter",
+ "@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.adaptive_scaffold.example;
+ PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -363,7 +351,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -412,11 +400,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -429,19 +418,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
- FRAMEWORK_SEARCH_PATHS = (
- "$(inherited)",
- "$(PROJECT_DIR)/Flutter",
- );
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- LIBRARY_SEARCH_PATHS = (
+ LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/Flutter",
+ "@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.adaptive_scaffold.example;
+ PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -457,19 +440,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
- FRAMEWORK_SEARCH_PATHS = (
- "$(inherited)",
- "$(PROJECT_DIR)/Flutter",
- );
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- LIBRARY_SEARCH_PATHS = (
+ LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/Flutter",
+ "@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.adaptive_scaffold.example;
+ PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
diff --git a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 1d526a1..919434a 100644
--- a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
- location = "group:Runner.xcodeproj">
+ location = "self:">
</FileRef>
</Workspace>
diff --git a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>PreviewsEnabled</key>
+ <false/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140c..c87d15a 100644
--- a/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/packages/adaptive_scaffold/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1020"
+ LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <Testables>
- </Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
- <AdditionalOptions>
- </AdditionalOptions>
+ <Testables>
+ </Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
- <AdditionalOptions>
- </AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
diff --git a/packages/adaptive_scaffold/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/adaptive_scaffold/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/packages/adaptive_scaffold/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>PreviewsEnabled</key>
+ <false/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
index 28c6bf0..7353c41 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
index 2ccbfd9..797d452 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
index f091b6b..6ed2d93 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
index 4cde121..4cd7b00 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
index d0ef06e..fe73094 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
index dcdc230..321773c 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
index 2ccbfd9..797d452 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
index c8f9ed8..502f463 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
index a6d6b86..0ec3034 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
index a6d6b86..0ec3034 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
index 75b2d16..e9f5fea 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
index c4df70d..84ac32a 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
index 6a84f41..8953cba 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
index d0e1f58..0467bf1 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
+++ b/packages/adaptive_scaffold/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/ios/Runner/Info.plist b/packages/adaptive_scaffold/example/ios/Runner/Info.plist
index a060db6..7f55346 100644
--- a/packages/adaptive_scaffold/example/ios/Runner/Info.plist
+++ b/packages/adaptive_scaffold/example/ios/Runner/Info.plist
@@ -4,6 +4,8 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleDisplayName</key>
+ <string>Example</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@@ -41,5 +43,9 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
+ <key>CADisableMinimumFrameDurationOnPhone</key>
+ <true/>
+ <key>UIApplicationSupportsIndirectInputEvents</key>
+ <true/>
</dict>
</plist>
diff --git a/packages/adaptive_scaffold/example/lib/adaptive_layout_demo.dart b/packages/adaptive_scaffold/example/lib/adaptive_layout_demo.dart
index 6c122bb..1c9a4ad 100644
--- a/packages/adaptive_scaffold/example/lib/adaptive_layout_demo.dart
+++ b/packages/adaptive_scaffold/example/lib/adaptive_layout_demo.dart
@@ -6,11 +6,13 @@
import 'package:flutter/material.dart';
void main() {
- runApp(const _MyApp());
+ runApp(const MyApp());
}
-class _MyApp extends StatelessWidget {
- const _MyApp({Key? key}) : super(key: key);
+/// The main application widget for this example.
+class MyApp extends StatelessWidget {
+ /// Creates a const main application widget.
+ const MyApp({super.key});
@override
Widget build(BuildContext context) {
@@ -24,7 +26,7 @@
/// [AdaptiveLayout].
class MyHomePage extends StatelessWidget {
/// Creates a const [MyHomePage].
- const MyHomePage({Key? key}) : super(key: key);
+ const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
@@ -72,7 +74,7 @@
icon: const Icon(Icons.folder_copy_outlined),
iconSize: 21),
const SizedBox(width: 21),
- const Text('Mortage'),
+ const Text('Mortgage'),
],
),
const SizedBox(height: 12),
@@ -107,16 +109,21 @@
// Define the list of destinations to be used within the app.
const List<NavigationDestination> destinations = <NavigationDestination>[
NavigationDestination(
- label: 'Inbox', icon: Icon(Icons.inbox, color: Colors.black)),
+ label: 'Inbox',
+ icon: Icon(Icons.inbox, color: Colors.black),
+ ),
NavigationDestination(
- label: 'Articles',
- icon: Icon(Icons.article_outlined, color: Colors.black)),
+ label: 'Articles',
+ icon: Icon(Icons.article_outlined, color: Colors.black),
+ ),
NavigationDestination(
- label: 'Chat',
- icon: Icon(Icons.chat_bubble_outline, color: Colors.black)),
+ label: 'Chat',
+ icon: Icon(Icons.chat_bubble_outline, color: Colors.black),
+ ),
NavigationDestination(
- label: 'Video',
- icon: Icon(Icons.video_call_outlined, color: Colors.black)),
+ label: 'Video',
+ icon: Icon(Icons.video_call_outlined, color: Colors.black),
+ ),
];
// #docregion Example
@@ -130,24 +137,26 @@
config: <Breakpoint, SlotLayoutConfig>{
Breakpoints.medium: SlotLayout.from(
inAnimation: AdaptiveScaffold.leftOutIn,
- key: const Key('pnav1'),
+ key: const Key('Primary Navigation Medium'),
builder: (_) => AdaptiveScaffold.standardNavigationRail(
- leading: const Icon(Icons.menu),
- destinations: destinations
- .map((_) => AdaptiveScaffold.toRailDestination(_))
- .toList()),
+ leading: const Icon(Icons.menu),
+ destinations: destinations
+ .map((_) => AdaptiveScaffold.toRailDestination(_))
+ .toList(),
+ ),
),
Breakpoints.large: SlotLayout.from(
- key: const Key('pn1'),
+ key: const Key('Primary Navigation Large'),
inAnimation: AdaptiveScaffold.leftOutIn,
builder: (_) => AdaptiveScaffold.standardNavigationRail(
extended: true,
leading: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const <Widget>[
- Text('REPLY',
- style:
- TextStyle(color: Color.fromARGB(255, 255, 201, 197))),
+ Text(
+ 'REPLY',
+ style: TextStyle(color: Color.fromARGB(255, 255, 201, 197)),
+ ),
Icon(Icons.menu_open)
],
),
@@ -164,14 +173,14 @@
body: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
Breakpoints.small: SlotLayout.from(
- key: const Key('body'),
+ key: const Key('Body Small'),
builder: (_) => ListView.builder(
itemCount: children.length,
itemBuilder: (BuildContext context, int index) => children[index],
),
),
Breakpoints.mediumAndUp: SlotLayout.from(
- key: const Key('body1'),
+ key: const Key('Body Medium'),
builder: (_) =>
GridView.count(crossAxisCount: 2, children: children),
)
@@ -182,14 +191,15 @@
bottomNavigation: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
Breakpoints.small: SlotLayout.from(
- key: const Key('bn'),
+ key: const Key('Bottom Navigation Small'),
inAnimation: AdaptiveScaffold.bottomToTop,
outAnimation: AdaptiveScaffold.topToBottom,
builder: (_) => BottomNavigationBarTheme(
- data: const BottomNavigationBarThemeData(
- selectedItemColor: Colors.black),
- child: AdaptiveScaffold.standardBottomNavigationBar(
- destinations: destinations)),
+ data: const BottomNavigationBarThemeData(
+ selectedItemColor: Colors.black),
+ child: AdaptiveScaffold.standardBottomNavigationBar(
+ destinations: destinations),
+ ),
)
},
),
diff --git a/packages/adaptive_scaffold/example/lib/adaptive_scaffold_demo.dart b/packages/adaptive_scaffold/example/lib/adaptive_scaffold_demo.dart
index b7f53b4..6609550 100644
--- a/packages/adaptive_scaffold/example/lib/adaptive_scaffold_demo.dart
+++ b/packages/adaptive_scaffold/example/lib/adaptive_scaffold_demo.dart
@@ -6,11 +6,13 @@
import 'package:flutter/material.dart';
void main() {
- runApp(const _MyApp());
+ runApp(const MyApp());
}
-class _MyApp extends StatelessWidget {
- const _MyApp({Key? key}) : super(key: key);
+/// The main application widget for this example.
+class MyApp extends StatelessWidget {
+ /// Creates a const main application widget.
+ const MyApp({super.key});
@override
Widget build(BuildContext context) {
@@ -22,7 +24,7 @@
/// [AdaptiveScaffold].
class MyHomePage extends StatelessWidget {
/// Creates a const [MyHomePage].
- const MyHomePage({Key? key}) : super(key: key);
+ const MyHomePage({super.key});
// #docregion Example
@override
@@ -31,16 +33,20 @@
final List<Widget> children = <Widget>[
for (int i = 0; i < 10; i++)
Padding(
- padding: const EdgeInsets.all(8.0),
- child: Container(
- color: const Color.fromARGB(255, 255, 201, 197), height: 400))
+ padding: const EdgeInsets.all(8.0),
+ child: Container(
+ color: const Color.fromARGB(255, 255, 201, 197),
+ height: 400,
+ ),
+ )
];
return BottomNavigationBarTheme(
data: const BottomNavigationBarThemeData(
- unselectedItemColor: Colors.black,
- selectedItemColor: Colors.black,
- backgroundColor: Colors.white),
+ unselectedItemColor: Colors.black,
+ selectedItemColor: Colors.black,
+ backgroundColor: Colors.white,
+ ),
child: AdaptiveScaffold(
// An option to override the default breakpoints used for small, medium,
// and large.
@@ -59,14 +65,15 @@
],
body: (_) => GridView.count(crossAxisCount: 2, children: children),
smallBody: (_) => ListView.builder(
- itemCount: children.length,
- itemBuilder: (_, int idx) => children[idx]),
+ itemCount: children.length,
+ itemBuilder: (_, int idx) => children[idx],
+ ),
// Define a default secondaryBody.
secondaryBody: (_) =>
Container(color: const Color.fromARGB(255, 234, 158, 192)),
// Override the default secondaryBody during the smallBreakpoint to be
// empty. Must use AdaptiveScaffold.emptyBuilder to ensure it is properly
- // overriden.
+ // overridden.
smallSecondaryBody: AdaptiveScaffold.emptyBuilder));
}
// #enddocregion
diff --git a/packages/adaptive_scaffold/example/lib/main.dart b/packages/adaptive_scaffold/example/lib/main.dart
index 3e15cb3..c5293d4 100644
--- a/packages/adaptive_scaffold/example/lib/main.dart
+++ b/packages/adaptive_scaffold/example/lib/main.dart
@@ -14,11 +14,13 @@
/// or adaptive_scaffold_demo.dart
void main() {
- runApp(const _MyApp());
+ runApp(const MyApp());
}
-class _MyApp extends StatelessWidget {
- const _MyApp({Key? key}) : super(key: key);
+/// The main application widget for this example.
+class MyApp extends StatelessWidget {
+ /// Creates a const main application widget.
+ const MyApp({super.key});
@override
Widget build(BuildContext context) {
@@ -38,7 +40,7 @@
/// Creates an example mail page using [AdaptiveLayout].
class MyHomePage extends StatefulWidget {
/// Creates a const [MyHomePage].
- const MyHomePage({Key? key}) : super(key: key);
+ const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
@@ -62,42 +64,42 @@
int _navigationIndex = 0;
// The controllers used for the staggered animation of the navigation elements.
- late AnimationController _controller;
- late AnimationController _controller1;
- late AnimationController _controller2;
- late AnimationController _controller3;
+ late AnimationController _inboxIconSlideController;
+ late AnimationController _articleIconSlideController;
+ late AnimationController _chatIconSlideController;
+ late AnimationController _videoIconSlideController;
@override
void initState() {
showGridView.addListener(() {
Navigator.popUntil(
context, (Route<dynamic> route) => route.settings.name == '/');
- _controller
+ _inboxIconSlideController
..reset()
..forward();
- _controller1
+ _articleIconSlideController
..reset()
..forward();
- _controller2
+ _chatIconSlideController
..reset()
..forward();
- _controller3
+ _videoIconSlideController
..reset()
..forward();
});
- _controller = AnimationController(
- duration: const Duration(milliseconds: 1000),
+ _inboxIconSlideController = AnimationController(
+ duration: const Duration(milliseconds: 100),
vsync: this,
)..forward();
- _controller1 = AnimationController(
- duration: const Duration(milliseconds: 1200),
+ _articleIconSlideController = AnimationController(
+ duration: const Duration(milliseconds: 120),
vsync: this,
)..forward();
- _controller2 = AnimationController(
- duration: const Duration(milliseconds: 1400),
+ _chatIconSlideController = AnimationController(
+ duration: const Duration(milliseconds: 140),
vsync: this,
)..forward();
- _controller3 = AnimationController(
- duration: const Duration(milliseconds: 1600),
+ _videoIconSlideController = AnimationController(
+ duration: const Duration(milliseconds: 160),
vsync: this,
)..forward();
super.initState();
@@ -105,10 +107,10 @@
@override
void dispose() {
- _controller.dispose();
- _controller1.dispose();
- _controller2.dispose();
- _controller3.dispose();
+ _inboxIconSlideController.dispose();
+ _articleIconSlideController.dispose();
+ _chatIconSlideController.dispose();
+ _videoIconSlideController.dispose();
super.dispose();
}
@@ -129,9 +131,10 @@
children: <Widget>[
const SizedBox(width: 16),
IconButton(
- onPressed: () {},
- icon: const Icon(Icons.folder_copy_outlined),
- iconSize: 21),
+ onPressed: () {},
+ icon: const Icon(Icons.folder_copy_outlined),
+ iconSize: 21,
+ ),
const SizedBox(width: 21),
const Text('Freelance', overflow: TextOverflow.ellipsis),
],
@@ -141,11 +144,12 @@
children: <Widget>[
const SizedBox(width: 16),
IconButton(
- onPressed: () {},
- icon: const Icon(Icons.folder_copy_outlined),
- iconSize: 21),
+ onPressed: () {},
+ icon: const Icon(Icons.folder_copy_outlined),
+ iconSize: 21,
+ ),
const SizedBox(width: 21),
- const Text('Mortage', overflow: TextOverflow.ellipsis),
+ const Text('Mortgage', overflow: TextOverflow.ellipsis),
],
),
const SizedBox(height: 16),
@@ -153,9 +157,10 @@
children: <Widget>[
const SizedBox(width: 16),
IconButton(
- onPressed: () {},
- icon: const Icon(Icons.folder_copy_outlined),
- iconSize: 21),
+ onPressed: () {},
+ icon: const Icon(Icons.folder_copy_outlined),
+ iconSize: 21,
+ ),
const SizedBox(width: 21),
const Flexible(
child: Text('Taxes', overflow: TextOverflow.ellipsis))
@@ -166,9 +171,10 @@
children: <Widget>[
const SizedBox(width: 16),
IconButton(
- onPressed: () {},
- icon: const Icon(Icons.folder_copy_outlined),
- iconSize: 21),
+ onPressed: () {},
+ icon: const Icon(Icons.folder_copy_outlined),
+ iconSize: 21,
+ ),
const SizedBox(width: 21),
const Flexible(
child: Text('Receipts', overflow: TextOverflow.ellipsis))
@@ -214,7 +220,7 @@
builder: (_) {
return AdaptiveScaffold.standardNavigationRail(
// Usually it would be easier to use a builder from
- // AdaptiveScaffold for these types of navigations but this
+ // AdaptiveScaffold for these types of navigation but this
// navigation has custom staggered item animations.
onDestinationSelected: (int index) {
setState(() {
@@ -223,30 +229,32 @@
},
selectedIndex: _navigationIndex,
leading: ScaleTransition(
- scale: _controller1, child: const _MediumComposeIcon()),
+ scale: _articleIconSlideController,
+ child: const _MediumComposeIcon(),
+ ),
backgroundColor: const Color.fromARGB(0, 255, 255, 255),
destinations: <NavigationRailDestination>[
slideInNavigationItem(
begin: -1,
- controller: _controller,
+ controller: _inboxIconSlideController,
icon: Icons.inbox,
label: 'Inbox',
),
slideInNavigationItem(
begin: -2,
- controller: _controller1,
+ controller: _articleIconSlideController,
icon: Icons.article_outlined,
label: 'Articles',
),
slideInNavigationItem(
begin: -3,
- controller: _controller2,
+ controller: _chatIconSlideController,
icon: Icons.chat_bubble_outline,
label: 'Chat',
),
slideInNavigationItem(
begin: -4,
- controller: _controller3,
+ controller: _videoIconSlideController,
icon: Icons.video_call_outlined,
label: 'Video',
)
@@ -255,7 +263,7 @@
},
),
Breakpoints.large: SlotLayout.from(
- key: const Key('primaryNavigation1'),
+ key: const Key('Large primaryNavigation'),
// The AdaptiveScaffold builder here greatly simplifies
// navigational elements.
builder: (_) => AdaptiveScaffold.standardNavigationRail(
@@ -268,9 +276,9 @@
selectedIndex: _navigationIndex,
trailing: trailingNavRail,
extended: true,
- destinations: destinations
- .map((_) => AdaptiveScaffold.toRailDestination(_))
- .toList(),
+ destinations: destinations.map((_) {
+ return AdaptiveScaffold.toRailDestination(_);
+ }).toList(),
),
),
},
@@ -280,15 +288,16 @@
Breakpoints.standard: SlotLayout.from(
key: const Key('body'),
// The conditional here is for navigation screens. The first
- // screen shows the main screen and every other screeen shows
+ // screen shows the main screen and every other screen shows
// ExamplePage.
builder: (_) => (_navigationIndex == 0)
? Padding(
padding: const EdgeInsets.fromLTRB(0, 32, 0, 0),
child: _ItemList(
- selected: selected,
- items: _allItems,
- selectCard: selectCard),
+ selected: selected,
+ items: _allItems,
+ selectCard: selectCard,
+ ),
)
: const _ExamplePage(),
),
@@ -301,7 +310,7 @@
// This overrides the default behavior of the secondaryBody
// disappearing as it is animating out.
outAnimation: AdaptiveScaffold.stayOnScreen,
- key: const Key('sBody'),
+ key: const Key('Secondary Body'),
builder: (_) => SafeArea(
child: _DetailTile(item: _allItems[selected ?? 0]),
),
@@ -351,9 +360,7 @@
}
class _SmallComposeIcon extends StatelessWidget {
- const _SmallComposeIcon({
- Key? key,
- }) : super(key: key);
+ const _SmallComposeIcon();
@override
Widget build(BuildContext context) {
@@ -378,9 +385,7 @@
}
class _MediumComposeIcon extends StatelessWidget {
- const _MediumComposeIcon({
- Key? key,
- }) : super(key: key);
+ const _MediumComposeIcon();
@override
Widget build(BuildContext context) {
@@ -395,9 +400,7 @@
}
class _LargeComposeIcon extends StatelessWidget {
- const _LargeComposeIcon({
- Key? key,
- }) : super(key: key);
+ const _LargeComposeIcon();
@override
Widget build(BuildContext context) {
@@ -409,8 +412,10 @@
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const <Widget>[
- Text('REPLY',
- style: TextStyle(color: Colors.deepPurple, fontSize: 15)),
+ Text(
+ 'REPLY',
+ style: TextStyle(color: Colors.deepPurple, fontSize: 15),
+ ),
Icon(Icons.menu_open, size: 22)
],
),
@@ -455,11 +460,10 @@
// ItemList creates the list of cards and the search bar.
class _ItemList extends StatelessWidget {
const _ItemList({
- Key? key,
required this.items,
required this.selectCard,
required this.selected,
- }) : super(key: key);
+ });
final List<_Item> items;
final int? selected;
@@ -526,12 +530,11 @@
class _ItemListTile extends StatelessWidget {
const _ItemListTile({
- Key? key,
required this.item,
required this.email,
required this.selectCard,
required this.selected,
- }) : super(key: key);
+ });
final _Item item;
final _Email email;
@@ -568,38 +571,43 @@
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
- Row(
- children: <Widget>[
- CircleAvatar(
- radius: 18,
- child: Image.asset(
- email.image,
- width: 100,
- height: 100,
- fit: BoxFit.cover,
+ ListTile(
+ contentPadding: EdgeInsets.zero,
+ leading: CircleAvatar(
+ radius: 18,
+ child: Image.asset(
+ email.image,
+ width: 100,
+ height: 100,
+ fit: BoxFit.cover,
+ ),
+ ),
+ title: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: <Widget>[
+ Text(
+ email.sender,
+ style: Theme.of(context).textTheme.bodyLarge,
+ softWrap: false,
+ overflow: TextOverflow.clip,
),
- ),
- const SizedBox(width: 8),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text(email.sender,
- style: Theme.of(context).textTheme.bodyLarge),
- const SizedBox(height: 3),
- Text('${email.time} ago',
- style: Theme.of(context).textTheme.bodySmall),
- ],
- ),
- const Spacer(),
- Container(
- padding: const EdgeInsets.all(8.0),
- decoration: const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.all(Radius.circular(50)),
+ const SizedBox(height: 3),
+ Text(
+ '${email.time} ago',
+ style: Theme.of(context).textTheme.bodySmall,
+ softWrap: false,
+ overflow: TextOverflow.clip,
),
- child: Icon(Icons.star_outline, color: Colors.grey[500]),
+ ],
+ ),
+ trailing: Container(
+ padding: const EdgeInsets.all(8.0),
+ decoration: const BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.all(Radius.circular(50)),
),
- ],
+ child: Icon(Icons.star_outline, color: Colors.grey[500]),
+ ),
),
const SizedBox(height: 13),
Text(item.title,
@@ -624,10 +632,8 @@
}
class _DetailTile extends StatelessWidget {
- const _DetailTile({
- required this.item,
- Key? key,
- }) : super(key: key);
+ const _DetailTile({required this.item});
+
final _Item item;
@override
@@ -638,79 +644,87 @@
height: MediaQuery.of(context).size.height,
child: Container(
decoration: const BoxDecoration(
- color: Color.fromARGB(255, 245, 241, 248),
- borderRadius: BorderRadius.all(Radius.circular(10))),
+ color: Color.fromARGB(255, 245, 241, 248),
+ borderRadius: BorderRadius.all(Radius.circular(10)),
+ ),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
- padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
- child: Column(
- children: <Widget>[
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Expanded(
- child: Container(
- padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text(item.title,
- style: Theme.of(context)
- .textTheme
- .titleLarge),
- const SizedBox(height: 7),
- Text('${item.emails!.length} Messages',
- style: Theme.of(context)
- .textTheme
- .labelSmall)
- ],
+ padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
+ child: Column(
+ children: <Widget>[
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: <Widget>[
+ Expanded(
+ child: Container(
+ padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: <Widget>[
+ Text(
+ item.title,
+ style: Theme.of(context).textTheme.titleLarge,
+ ),
+ const SizedBox(height: 7),
+ Text(
+ '${item.emails!.length} Messages',
+ style: Theme.of(context).textTheme.labelSmall,
+ )
+ ],
+ ),
+ ),
+ ),
+ Container(
+ padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
+ child: Row(
+ children: <Widget>[
+ Container(
+ padding: const EdgeInsets.all(8.0),
+ decoration: const BoxDecoration(
+ color: Colors.white,
+ borderRadius:
+ BorderRadius.all(Radius.circular(15)),
+ ),
+ child: Icon(
+ Icons.restore_from_trash,
+ color: Colors.grey[600],
),
),
- ),
- Container(
- padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
- child: Row(
- children: <Widget>[
- Container(
- padding: const EdgeInsets.all(8.0),
- decoration: const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.all(
- Radius.circular(15)),
- ),
- child: Icon(Icons.restore_from_trash,
- color: Colors.grey[600]),
- ),
- const SizedBox(width: 15),
- Container(
- padding: const EdgeInsets.all(8.0),
- decoration: const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.all(
- Radius.circular(15))),
- child: Icon(Icons.more_vert,
- color: Colors.grey[600]),
- )
- ],
- )),
- ]),
- const SizedBox(height: 20),
- ],
- )),
+ const SizedBox(width: 15),
+ Container(
+ padding: const EdgeInsets.all(8.0),
+ decoration: const BoxDecoration(
+ color: Colors.white,
+ borderRadius:
+ BorderRadius.all(Radius.circular(15)),
+ ),
+ child: Icon(Icons.more_vert,
+ color: Colors.grey[600]),
+ )
+ ],
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 20),
+ ],
+ ),
+ ),
Expanded(
child: ListView.builder(
itemCount: item.emails!.length,
itemBuilder: (BuildContext context, int index) {
final _Email thisEmail = item.emails![index];
return _EmailTile(
- sender: thisEmail.sender,
- time: thisEmail.time,
- senderIcon: thisEmail.image,
- recepients: thisEmail.recepients,
- body: thisEmail.body,
- bodyImage: thisEmail.bodyImage);
+ sender: thisEmail.sender,
+ time: thisEmail.time,
+ senderIcon: thisEmail.image,
+ recipients: thisEmail.recipients,
+ body: thisEmail.body,
+ bodyImage: thisEmail.bodyImage,
+ );
},
),
),
@@ -727,16 +741,15 @@
required this.sender,
required this.time,
required this.senderIcon,
- required this.recepients,
+ required this.recipients,
required this.body,
required this.bodyImage,
- Key? key,
- }) : super(key: key);
+ });
final String sender;
final String time;
final String senderIcon;
- final String recepients;
+ final String recipients;
final String body;
final String bodyImage;
@@ -746,8 +759,9 @@
padding: const EdgeInsets.fromLTRB(0, 4, 0, 4),
child: Container(
decoration: const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.all(Radius.circular(10))),
+ color: Colors.white,
+ borderRadius: BorderRadius.all(Radius.circular(10)),
+ ),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
@@ -780,16 +794,17 @@
Container(
padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
- color: Color.fromARGB(255, 245, 241, 248),
- borderRadius: BorderRadius.all(Radius.circular(50))),
+ color: Color.fromARGB(255, 245, 241, 248),
+ borderRadius: BorderRadius.all(Radius.circular(50)),
+ ),
child: Icon(Icons.star_outline, color: Colors.grey[500]),
),
],
),
- if (recepients != '')
+ if (recipients != '')
Column(children: <Widget>[
const SizedBox(height: 15),
- Text('To $recepients',
+ Text('To $recipients',
style: TextStyle(color: Colors.grey[500], fontSize: 12)),
])
else
@@ -817,9 +832,12 @@
borderRadius: BorderRadius.circular(30.0)),
),
backgroundColor: MaterialStateProperty.all<Color>(
- const Color.fromARGB(255, 245, 241, 248)),
- side: MaterialStateProperty.all(const BorderSide(
- width: 0.0, color: Colors.transparent)),
+ const Color.fromARGB(255, 245, 241, 248),
+ ),
+ side: MaterialStateProperty.all(
+ const BorderSide(
+ width: 0.0, color: Colors.transparent),
+ ),
),
child: Text('Reply',
style:
@@ -836,9 +854,12 @@
borderRadius: BorderRadius.circular(30.0)),
),
backgroundColor: MaterialStateProperty.all<Color>(
- const Color.fromARGB(255, 245, 241, 248)),
- side: MaterialStateProperty.all(const BorderSide(
- width: 0.0, color: Colors.transparent)),
+ const Color.fromARGB(255, 245, 241, 248),
+ ),
+ side: MaterialStateProperty.all(
+ const BorderSide(
+ width: 0.0, color: Colors.transparent),
+ ),
),
child: Text(
'Reply all',
@@ -868,7 +889,7 @@
}
class _ExtractRouteArguments extends StatelessWidget {
- const _ExtractRouteArguments({Key? key}) : super(key: key);
+ const _ExtractRouteArguments();
static const String routeName = '/detailView';
@@ -885,8 +906,7 @@
const _RouteDetailView({
required this.item,
required this.selectCard,
- Key? key,
- }) : super(key: key);
+ });
final _Item item;
final _CardSelectedCallback selectCard;
@@ -915,7 +935,7 @@
}
class _ExamplePage extends StatelessWidget {
- const _ExamplePage({Key? key}) : super(key: key);
+ const _ExamplePage();
@override
Widget build(BuildContext context) {
@@ -936,7 +956,7 @@
class _Email {
const _Email({
required this.sender,
- required this.recepients,
+ required this.recipients,
required this.image,
required this.time,
required this.body,
@@ -944,7 +964,7 @@
});
final String sender;
- final String recepients;
+ final String recipients;
final String image;
final String time;
final String body;
@@ -959,7 +979,7 @@
emails: <_Email>[
_Email(
sender: 'So Duri',
- recepients: 'me, Ziad and Lily',
+ recipients: 'me, Ziad and Lily',
image: 'images/strawberry.png',
time: '20 min',
body:
@@ -968,7 +988,7 @@
),
_Email(
sender: 'Me',
- recepients: 'me, Ziad, and Lily',
+ recipients: 'me, Ziad, and Lily',
image: 'images/plum.png',
time: '4 min',
body:
@@ -976,7 +996,7 @@
bodyImage: ''),
_Email(
sender: 'Ziad Aouad',
- recepients: 'me, Ziad and Lily',
+ recipients: 'me, Ziad and Lily',
image: 'images/mushroom.png',
time: '2 min',
body:
@@ -994,7 +1014,7 @@
'Curabitur tincidunt purus at vulputate mattis. Nam lectus urna, varius eget quam in, ultricies ultrices libero. Curabitur rutrum ultricies varius. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec vulputate auctor est, non semper velit eleifend sit amet.',
image: 'images/potato.png',
bodyImage: 'images/avocado.png',
- recepients: '',
+ recipients: '',
),
],
),
@@ -1008,7 +1028,7 @@
'Cras egestas ultricies elit, vitae interdum lorem aliquam et. Donec quis arcu a quam tempor rutrum vitae in lectus. Nullam elit nunc, lacinia sed luctus non, mollis id nulla. Morbi luctus turpis sapien, id molestie ante maximus vel. Vivamus sagittis consequat nisl nec placerat.',
image: 'images/habanero.png',
bodyImage: '',
- recepients: '',
+ recipients: '',
),
],
),
diff --git a/packages/adaptive_scaffold/example/linux/.gitignore b/packages/adaptive_scaffold/example/linux/.gitignore
new file mode 100644
index 0000000..d3896c9
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/.gitignore
@@ -0,0 +1 @@
+flutter/ephemeral
diff --git a/packages/adaptive_scaffold/example/linux/CMakeLists.txt b/packages/adaptive_scaffold/example/linux/CMakeLists.txt
new file mode 100644
index 0000000..79ccc9d
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/CMakeLists.txt
@@ -0,0 +1,138 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.10)
+project(runner LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "example")
+# The unique GTK application identifier for this application. See:
+# https://wiki.gnome.org/HowDoI/ChooseApplicationID
+set(APPLICATION_ID "dev.flutter.example")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Load bundled libraries from the lib/ directory relative to the binary.
+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+ set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+ set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+endif()
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_14)
+ target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+ target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
+ target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+
+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
+
+# Define the application target. To change its name, change BINARY_NAME above,
+# not the value here, or `flutter run` will no longer work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME}
+ "main.cc"
+ "my_application.cc"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Add dependency libraries. Add any application-specific dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
+
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+ PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+)
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+ file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+ " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
+ install(FILES "${bundled_library}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endforeach(bundled_library)
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
diff --git a/packages/adaptive_scaffold/example/linux/flutter/CMakeLists.txt b/packages/adaptive_scaffold/example/linux/flutter/CMakeLists.txt
new file mode 100644
index 0000000..d5bd016
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/flutter/CMakeLists.txt
@@ -0,0 +1,88 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.10)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+
+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
+# which isn't available in 3.10.
+function(list_prepend LIST_NAME PREFIX)
+ set(NEW_LIST "")
+ foreach(element ${${LIST_NAME}})
+ list(APPEND NEW_LIST "${PREFIX}${element}")
+ endforeach(element)
+ set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
+endfunction()
+
+# === Flutter Library ===
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
+
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "fl_basic_message_channel.h"
+ "fl_binary_codec.h"
+ "fl_binary_messenger.h"
+ "fl_dart_project.h"
+ "fl_engine.h"
+ "fl_json_message_codec.h"
+ "fl_json_method_codec.h"
+ "fl_message_codec.h"
+ "fl_method_call.h"
+ "fl_method_channel.h"
+ "fl_method_codec.h"
+ "fl_method_response.h"
+ "fl_plugin_registrar.h"
+ "fl_plugin_registry.h"
+ "fl_standard_message_codec.h"
+ "fl_standard_method_codec.h"
+ "fl_string_codec.h"
+ "fl_value.h"
+ "fl_view.h"
+ "flutter_linux.h"
+)
+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
+target_link_libraries(flutter INTERFACE
+ PkgConfig::GTK
+ PkgConfig::GLIB
+ PkgConfig::GIO
+)
+add_dependencies(flutter flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
+ ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+)
diff --git a/packages/adaptive_scaffold/example/linux/flutter/generated_plugins.cmake b/packages/adaptive_scaffold/example/linux/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..2e1de87
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,23 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/packages/adaptive_scaffold/example/linux/main.cc b/packages/adaptive_scaffold/example/linux/main.cc
new file mode 100644
index 0000000..1507d02
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/main.cc
@@ -0,0 +1,10 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+ g_autoptr(MyApplication) app = my_application_new();
+ return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/packages/adaptive_scaffold/example/linux/my_application.cc b/packages/adaptive_scaffold/example/linux/my_application.cc
new file mode 100644
index 0000000..3a67810
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/my_application.cc
@@ -0,0 +1,111 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "my_application.h"
+
+#include <flutter_linux/flutter_linux.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+ GtkApplication parent_instance;
+ char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+ MyApplication* self = MY_APPLICATION(application);
+ GtkWindow* window =
+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+ // Use a header bar when running in GNOME as this is the common style used
+ // by applications and is the setup most users will be using (e.g. Ubuntu
+ // desktop).
+ // If running on X and not using GNOME then just use a traditional title bar
+ // in case the window manager does more exotic layout, e.g. tiling.
+ // If running on Wayland assume the header bar will work (may need changing
+ // if future cases occur).
+ gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+ GdkScreen* screen = gtk_window_get_screen(window);
+ if (GDK_IS_X11_SCREEN(screen)) {
+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+ use_header_bar = FALSE;
+ }
+ }
+#endif
+ if (use_header_bar) {
+ GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+ gtk_widget_show(GTK_WIDGET(header_bar));
+ gtk_header_bar_set_title(header_bar, "example");
+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+ } else {
+ gtk_window_set_title(window, "example");
+ }
+
+ gtk_window_set_default_size(window, 1280, 720);
+ gtk_widget_show(GTK_WIDGET(window));
+
+ g_autoptr(FlDartProject) project = fl_dart_project_new();
+ fl_dart_project_set_dart_entrypoint_arguments(
+ project, self->dart_entrypoint_arguments);
+
+ FlView* view = fl_view_new(project);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+ gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application,
+ gchar*** arguments,
+ int* exit_status) {
+ MyApplication* self = MY_APPLICATION(application);
+ // Strip out the first argument as it is the binary name.
+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+ g_autoptr(GError) error = nullptr;
+ if (!g_application_register(application, nullptr, &error)) {
+ g_warning("Failed to register: %s", error->message);
+ *exit_status = 1;
+ return TRUE;
+ }
+
+ g_application_activate(application);
+ *exit_status = 0;
+
+ return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject* object) {
+ MyApplication* self = MY_APPLICATION(object);
+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+ G_APPLICATION_CLASS(klass)->local_command_line =
+ my_application_local_command_line;
+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+ return MY_APPLICATION(g_object_new(my_application_get_type(),
+ "application-id", APPLICATION_ID, "flags",
+ G_APPLICATION_NON_UNIQUE, nullptr));
+}
diff --git a/packages/adaptive_scaffold/example/linux/my_application.h b/packages/adaptive_scaffold/example/linux/my_application.h
new file mode 100644
index 0000000..6e9f0c3
--- /dev/null
+++ b/packages/adaptive_scaffold/example/linux/my_application.h
@@ -0,0 +1,22 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include <gtk/gtk.h>
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+ GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif // FLUTTER_MY_APPLICATION_H_
diff --git a/packages/adaptive_scaffold/example/macos/.gitignore b/packages/adaptive_scaffold/example/macos/.gitignore
new file mode 100644
index 0000000..746adbb
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/.gitignore
@@ -0,0 +1,7 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/dgph
+**/xcuserdata/
diff --git a/packages/adaptive_scaffold/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/adaptive_scaffold/example/macos/Flutter/Flutter-Debug.xcconfig
new file mode 100644
index 0000000..c2efd0b
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Flutter/Flutter-Debug.xcconfig
@@ -0,0 +1 @@
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/packages/adaptive_scaffold/example/macos/Flutter/Flutter-Release.xcconfig b/packages/adaptive_scaffold/example/macos/Flutter/Flutter-Release.xcconfig
new file mode 100644
index 0000000..c2efd0b
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Flutter/Flutter-Release.xcconfig
@@ -0,0 +1 @@
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/project.pbxproj b/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..736ab66
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,573 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 33CC110E2044A8840003C045 /* Bundle Framework */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Bundle Framework";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
+ 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "<group>";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* example.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "<group>";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ );
+ path = Flutter;
+ sourceTree = "<group>";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "<group>";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 33CC110E2044A8840003C045 /* Bundle Framework */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 1300;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..fb7259e
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1300"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Profile"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/packages/adaptive_scaffold/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/adaptive_scaffold/example/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "group:Runner.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/packages/adaptive_scaffold/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/adaptive_scaffold/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/macos/Runner/AppDelegate.swift b/packages/adaptive_scaffold/example/macos/Runner/AppDelegate.swift
new file mode 100644
index 0000000..5cec4c4
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..a2ec33f
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_64.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_1024.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
new file mode 100644
index 0000000..82b6f9d
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
new file mode 100644
index 0000000..13b35eb
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
new file mode 100644
index 0000000..0a3f5fa
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
new file mode 100644
index 0000000..bdb5722
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
new file mode 100644
index 0000000..f083318
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
new file mode 100644
index 0000000..326c0e7
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
new file mode 100644
index 0000000..2f1632c
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Base.lproj/MainMenu.xib b/packages/adaptive_scaffold/example/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 0000000..80e867a
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+ <connections>
+ <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+ <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Runner" customModuleProvider="target">
+ <connections>
+ <outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
+ <outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
+ </connections>
+ </customObject>
+ <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
+ <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+ <items>
+ <menuItem title="APP_NAME" id="1Xt-HY-uBw">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
+ <items>
+ <menuItem title="About APP_NAME" id="5kV-Vb-QxS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+ <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
+ <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
+ <menuItem title="Services" id="NMo-om-nkz">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
+ <menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
+ <connections>
+ <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="Kd2-mp-pUS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+ <menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
+ <connections>
+ <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Edit" id="5QF-Oa-p0T">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Edit" id="W48-6f-4Dl">
+ <items>
+ <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
+ <connections>
+ <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
+ <connections>
+ <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
+ <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
+ <connections>
+ <action selector="cut:" target="-1" id="YJe-68-I9s"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
+ <connections>
+ <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
+ <connections>
+ <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Delete" id="pa3-QI-u2k">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
+ <connections>
+ <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
+ <menuItem title="Find" id="4EN-yA-p0u">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Find" id="1b7-l0-nxx">
+ <items>
+ <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
+ <connections>
+ <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
+ <items>
+ <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
+ <connections>
+ <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
+ <connections>
+ <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
+ <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Substitutions" id="9ic-FL-obx">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
+ <items>
+ <menuItem title="Show Substitutions" id="z6F-FW-3nz">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
+ <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Smart Quotes" id="hQb-2v-fYv">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Smart Dashes" id="rgM-f4-ycn">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Smart Links" id="cwL-P1-jid">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Data Detectors" id="tRr-pd-1PS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Text Replacement" id="HFQ-gK-NFA">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Transformations" id="2oI-Rn-ZJC">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
+ <items>
+ <menuItem title="Make Upper Case" id="vmV-6d-7jI">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Make Lower Case" id="d9M-CD-aMd">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Capitalize" id="UEZ-Bs-lqG">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Speech" id="xrE-MZ-jX0">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
+ <items>
+ <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="View" id="H8h-7b-M4v">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="View" id="HyV-fh-RgO">
+ <items>
+ <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
+ <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
+ <connections>
+ <action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="aUF-d1-5bR">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+ <connections>
+ <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="R4o-n2-Eq4">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
+ <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Help" id="EPT-qC-fAb">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Help" systemMenu="help" id="rJ0-wn-3NY"/>
+ </menuItem>
+ </items>
+ <point key="canvasLocation" x="142" y="-258"/>
+ </menu>
+ <window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Runner" customModuleProvider="target">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+ <rect key="contentRect" x="335" y="390" width="800" height="600"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
+ <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
+ <rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </view>
+ </window>
+ </objects>
+</document>
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/adaptive_scaffold/example/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 0000000..a1f7408
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = example
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.example
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2022 dev.flutter. All rights reserved.
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Configs/Debug.xcconfig b/packages/adaptive_scaffold/example/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 0000000..36b0fd9
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Configs/Release.xcconfig b/packages/adaptive_scaffold/example/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 0000000..dff4f49
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Configs/Warnings.xcconfig b/packages/adaptive_scaffold/example/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 0000000..42bcbf4
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/packages/adaptive_scaffold/example/macos/Runner/DebugProfile.entitlements b/packages/adaptive_scaffold/example/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 0000000..dddb8a3
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.app-sandbox</key>
+ <true/>
+ <key>com.apple.security.cs.allow-jit</key>
+ <true/>
+ <key>com.apple.security.network.server</key>
+ <true/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Info.plist b/packages/adaptive_scaffold/example/macos/Runner/Info.plist
new file mode 100644
index 0000000..4789daa
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>$(FLUTTER_BUILD_NAME)</string>
+ <key>CFBundleVersion</key>
+ <string>$(FLUTTER_BUILD_NUMBER)</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>$(PRODUCT_COPYRIGHT)</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/macos/Runner/MainFlutterWindow.swift b/packages/adaptive_scaffold/example/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 0000000..32aaeed
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,19 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController.init()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/packages/adaptive_scaffold/example/macos/Runner/Release.entitlements b/packages/adaptive_scaffold/example/macos/Runner/Release.entitlements
new file mode 100644
index 0000000..852fa1a
--- /dev/null
+++ b/packages/adaptive_scaffold/example/macos/Runner/Release.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.app-sandbox</key>
+ <true/>
+</dict>
+</plist>
diff --git a/packages/adaptive_scaffold/example/pubspec.yaml b/packages/adaptive_scaffold/example/pubspec.yaml
index a43777a..82e7a9a 100644
--- a/packages/adaptive_scaffold/example/pubspec.yaml
+++ b/packages/adaptive_scaffold/example/pubspec.yaml
@@ -4,7 +4,7 @@
version: 0.0.1
environment:
- sdk: ">=2.12.0 <3.0.0"
+ sdk: ">=2.18.0 <3.0.0"
flutter: ">=3.0.0"
dependencies:
diff --git a/packages/adaptive_scaffold/example/test/adaptive_layout_demo_test.dart b/packages/adaptive_scaffold/example/test/adaptive_layout_demo_test.dart
index 45230be..64cdd5d 100644
--- a/packages/adaptive_scaffold/example/test/adaptive_layout_demo_test.dart
+++ b/packages/adaptive_scaffold/example/test/adaptive_layout_demo_test.dart
@@ -8,8 +8,9 @@
import 'package:flutter_test/flutter_test.dart';
void main() {
- final Finder body = find.byKey(const Key('body'));
- final Finder bn = find.byKey(const Key('bn'));
+ final Finder body = find.byKey(const Key('Body Small'));
+ final Finder bottomNavigation =
+ find.byKey(const Key('Bottom Navigation Small'));
Future<void> updateScreen(double width, WidgetTester tester) async {
await tester.binding.setSurfaceSize(Size(width, 800));
@@ -23,21 +24,21 @@
await tester.pumpAndSettle();
}
- testWidgets('dislays correct item of config based on screen width',
+ testWidgets('displays correct item of config based on screen width',
(WidgetTester tester) async {
await updateScreen(300, tester);
- expect(find.byKey(const Key('body')), findsOneWidget);
- expect(find.byKey(const Key('pnav')), findsNothing);
- expect(find.byKey(const Key('bn')), findsOneWidget);
- expect(find.byKey(const Key('body1')), findsNothing);
- expect(find.byKey(const Key('pn1')), findsNothing);
+ expect(find.byKey(const Key('Body Small')), findsOneWidget);
+ expect(find.byKey(const Key('Primary Navigation Medium')), findsNothing);
+ expect(find.byKey(const Key('Bottom Navigation Small')), findsOneWidget);
+ expect(find.byKey(const Key('Body Medium')), findsNothing);
+ expect(find.byKey(const Key('Primary Navigation Large')), findsNothing);
await updateScreen(700, tester);
- expect(find.byKey(const Key('body')), findsNothing);
- expect(find.byKey(const Key('bn')), findsNothing);
- expect(find.byKey(const Key('body1')), findsOneWidget);
- expect(find.byKey(const Key('pnav1')), findsOneWidget);
- expect(find.byKey(const Key('pn1')), findsNothing);
+ expect(find.byKey(const Key('Body')), findsNothing);
+ expect(find.byKey(const Key('Bottom Navigation Small')), findsNothing);
+ expect(find.byKey(const Key('Body Medium')), findsOneWidget);
+ expect(find.byKey(const Key('Primary Navigation Medium')), findsOneWidget);
+ expect(find.byKey(const Key('Primary Navigation Large')), findsNothing);
});
testWidgets(
@@ -47,7 +48,7 @@
final BuildContext context = tester.element(find.byType(MaterialApp));
// Bottom Navigation Bar
- final Finder findKey = find.byKey(const Key('bn'));
+ final Finder findKey = find.byKey(const Key('Bottom Navigation Small'));
final SlotLayoutConfig slotLayoutConfig =
tester.firstWidget<SlotLayoutConfig>(findKey);
final WidgetBuilder? widgetBuilder = slotLayoutConfig.builder;
@@ -65,7 +66,7 @@
await updateScreen(620, tester);
final BuildContext context = tester.element(find.byType(AdaptiveLayout));
- final Finder findKey = find.byKey(const Key('pnav1'));
+ final Finder findKey = find.byKey(const Key('Primary Navigation Medium'));
final SlotLayoutConfig slotLayoutConfig =
tester.firstWidget<SlotLayoutConfig>(findKey);
final WidgetBuilder? widgetBuilder = slotLayoutConfig.builder;
@@ -81,18 +82,18 @@
testWidgets('adaptive layout displays children in correct places',
(WidgetTester tester) async {
await updateScreen(400, tester);
- expect(tester.getBottomLeft(bn), const Offset(0, 800));
- expect(tester.getBottomRight(bn), const Offset(400, 800));
+ expect(tester.getBottomLeft(bottomNavigation), const Offset(0, 800));
+ expect(tester.getBottomRight(bottomNavigation), const Offset(400, 800));
expect(tester.getTopRight(body), const Offset(400, 0));
expect(tester.getTopLeft(body), Offset.zero);
});
testWidgets('adaptive layout does not animate when animations off',
(WidgetTester tester) async {
- final Finder b = find.byKey(const Key('body1'));
+ final Finder bodyMedium = find.byKey(const Key('Body Medium'));
await updateScreen(690, tester);
- expect(tester.getTopLeft(b), const Offset(88, 0));
- expect(tester.getBottomRight(b), const Offset(690, 800));
+ expect(tester.getTopLeft(bodyMedium), const Offset(88, 0));
+ expect(tester.getBottomRight(bodyMedium), const Offset(690, 800));
});
}
diff --git a/packages/adaptive_scaffold/example/web/favicon.png b/packages/adaptive_scaffold/example/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
--- /dev/null
+++ b/packages/adaptive_scaffold/example/web/favicon.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/web/icons/Icon-192.png b/packages/adaptive_scaffold/example/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
--- /dev/null
+++ b/packages/adaptive_scaffold/example/web/icons/Icon-192.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/web/icons/Icon-512.png b/packages/adaptive_scaffold/example/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
--- /dev/null
+++ b/packages/adaptive_scaffold/example/web/icons/Icon-512.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/web/icons/Icon-maskable-192.png b/packages/adaptive_scaffold/example/web/icons/Icon-maskable-192.png
new file mode 100644
index 0000000..eb9b4d7
--- /dev/null
+++ b/packages/adaptive_scaffold/example/web/icons/Icon-maskable-192.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/web/icons/Icon-maskable-512.png b/packages/adaptive_scaffold/example/web/icons/Icon-maskable-512.png
new file mode 100644
index 0000000..d69c566
--- /dev/null
+++ b/packages/adaptive_scaffold/example/web/icons/Icon-maskable-512.png
Binary files differ
diff --git a/packages/adaptive_scaffold/example/web/index.html b/packages/adaptive_scaffold/example/web/index.html
index 7fb138c..9be0ff0 100644
--- a/packages/adaptive_scaffold/example/web/index.html
+++ b/packages/adaptive_scaffold/example/web/index.html
@@ -4,10 +4,59 @@
found in the LICENSE file. -->
<html>
<head>
+ <!--
+ If you are serving your web app in a path other than the root, change the
+ href value below to reflect the base path you are serving from.
+
+ The path provided below has to start and end with a slash "/" in order for
+ it to work correctly.
+
+ For more details:
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
+
+ This is a placeholder for base href that will be replaced by the value of
+ the `--base-href` argument provided to `flutter build`.
+ -->
+ <base href="$FLUTTER_BASE_HREF">
+
<meta charset="UTF-8">
+ <meta content="IE=Edge" http-equiv="X-UA-Compatible">
+ <meta name="description" content="A new Flutter project.">
+
+ <!-- iOS meta tags & icons -->
+ <meta name="apple-mobile-web-app-capable" content="yes">
+ <meta name="apple-mobile-web-app-status-bar-style" content="black">
+ <meta name="apple-mobile-web-app-title" content="example">
+ <link rel="apple-touch-icon" href="icons/Icon-192.png">
+
+ <!-- Favicon -->
+ <link rel="icon" type="image/png" href="favicon.png"/>
+
<title>example</title>
+ <link rel="manifest" href="manifest.json">
+
+ <script>
+ // The value below is injected by flutter build, do not touch.
+ var serviceWorkerVersion = null;
+ </script>
+ <!-- This script adds the flutter initialization JS code -->
+ <script src="flutter.js" defer></script>
</head>
<body>
- <script src="main.dart.js" type="application/javascript"></script>
+ <script>
+ window.addEventListener('load', function(ev) {
+ // Download main.dart.js
+ _flutter.loader.loadEntrypoint({
+ serviceWorker: {
+ serviceWorkerVersion: serviceWorkerVersion,
+ },
+ onEntrypointLoaded: function(engineInitializer) {
+ engineInitializer.initializeEngine().then(function(appRunner) {
+ appRunner.runApp();
+ });
+ }
+ });
+ });
+ </script>
</body>
</html>
diff --git a/packages/adaptive_scaffold/example/web/manifest.json b/packages/adaptive_scaffold/example/web/manifest.json
new file mode 100644
index 0000000..096edf8
--- /dev/null
+++ b/packages/adaptive_scaffold/example/web/manifest.json
@@ -0,0 +1,35 @@
+{
+ "name": "example",
+ "short_name": "example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-maskable-192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "icons/Icon-maskable-512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ]
+}
diff --git a/packages/adaptive_scaffold/example/windows/.gitignore b/packages/adaptive_scaffold/example/windows/.gitignore
new file mode 100644
index 0000000..d492d0d
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/packages/adaptive_scaffold/example/windows/CMakeLists.txt b/packages/adaptive_scaffold/example/windows/CMakeLists.txt
new file mode 100644
index 0000000..c027074
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/CMakeLists.txt
@@ -0,0 +1,101 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.14)
+project(example LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "example")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Define build configuration option.
+get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(IS_MULTICONFIG)
+ set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
+ CACHE STRING "" FORCE)
+else()
+ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+ endif()
+endif()
+# Define settings for the Profile build mode.
+set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
+set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
+set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
+
+# Use Unicode for all projects.
+add_definitions(-DUNICODE -D_UNICODE)
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_17)
+ target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
+ target_compile_options(${TARGET} PRIVATE /EHsc)
+ target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+ target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# Application build; see runner/CMakeLists.txt.
+add_subdirectory("runner")
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# Support files are copied into place next to the executable, so that it can
+# run in place. This is done instead of making a separate bundle (as on Linux)
+# so that building and running from within Visual Studio will work.
+set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
+# Make the "install" step default, as it's required to run.
+set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+ install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ CONFIGURATIONS Profile;Release
+ COMPONENT Runtime)
diff --git a/packages/adaptive_scaffold/example/windows/flutter/CMakeLists.txt b/packages/adaptive_scaffold/example/windows/flutter/CMakeLists.txt
new file mode 100644
index 0000000..930d207
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/flutter/CMakeLists.txt
@@ -0,0 +1,104 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.14)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
+
+# === Flutter Library ===
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "flutter_export.h"
+ "flutter_windows.h"
+ "flutter_messenger.h"
+ "flutter_plugin_registrar.h"
+ "flutter_texture_registrar.h"
+)
+list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
+add_dependencies(flutter flutter_assemble)
+
+# === Wrapper ===
+list(APPEND CPP_WRAPPER_SOURCES_CORE
+ "core_implementations.cc"
+ "standard_codec.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
+ "plugin_registrar.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_APP
+ "flutter_engine.cc"
+ "flutter_view_controller.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
+
+# Wrapper sources needed for a plugin.
+add_library(flutter_wrapper_plugin STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+)
+apply_standard_settings(flutter_wrapper_plugin)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ POSITION_INDEPENDENT_CODE ON)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ CXX_VISIBILITY_PRESET hidden)
+target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
+target_include_directories(flutter_wrapper_plugin PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_plugin flutter_assemble)
+
+# Wrapper sources needed for the runner.
+add_library(flutter_wrapper_app STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
+apply_standard_settings(flutter_wrapper_app)
+target_link_libraries(flutter_wrapper_app PUBLIC flutter)
+target_include_directories(flutter_wrapper_app PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_app flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
+set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+ ${PHONY_OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
+ windows-x64 $<CONFIG>
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
diff --git a/packages/adaptive_scaffold/example/windows/flutter/generated_plugins.cmake b/packages/adaptive_scaffold/example/windows/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..b93c4c3
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/flutter/generated_plugins.cmake
@@ -0,0 +1,23 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/packages/adaptive_scaffold/example/windows/runner/CMakeLists.txt b/packages/adaptive_scaffold/example/windows/runner/CMakeLists.txt
new file mode 100644
index 0000000..17411a8
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 3.14)
+project(runner LANGUAGES CXX)
+
+# Define the application target. To change its name, change BINARY_NAME in the
+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
+# work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME} WIN32
+ "flutter_window.cpp"
+ "main.cpp"
+ "utils.cpp"
+ "win32_window.cpp"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+ "Runner.rc"
+ "runner.exe.manifest"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Add preprocessor definitions for the build version.
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
+target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
+
+# Disable Windows macros that collide with C++ standard library functions.
+target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
+
+# Add dependency libraries and include directories. Add any application-specific
+# dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
diff --git a/packages/adaptive_scaffold/example/windows/runner/Runner.rc b/packages/adaptive_scaffold/example/windows/runner/Runner.rc
new file mode 100644
index 0000000..267a156
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/Runner.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON ICON "resources\\app_icon.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
+#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
+#else
+#define VERSION_AS_NUMBER 1,0,0,0
+#endif
+
+#if defined(FLUTTER_VERSION)
+#define VERSION_AS_STRING FLUTTER_VERSION
+#else
+#define VERSION_AS_STRING "1.0.0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VERSION_AS_NUMBER
+ PRODUCTVERSION VERSION_AS_NUMBER
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "dev.flutter" "\0"
+ VALUE "FileDescription", "example" "\0"
+ VALUE "FileVersion", VERSION_AS_STRING "\0"
+ VALUE "InternalName", "example" "\0"
+ VALUE "LegalCopyright", "Copyright (C) 2022 dev.flutter. All rights reserved." "\0"
+ VALUE "OriginalFilename", "example.exe" "\0"
+ VALUE "ProductName", "example" "\0"
+ VALUE "ProductVersion", VERSION_AS_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/packages/adaptive_scaffold/example/windows/runner/flutter_window.cpp b/packages/adaptive_scaffold/example/windows/runner/flutter_window.cpp
new file mode 100644
index 0000000..8254bd9
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/flutter_window.cpp
@@ -0,0 +1,65 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter_window.h"
+
+#include <optional>
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(const flutter::DartProject& project)
+ : project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+bool FlutterWindow::OnCreate() {
+ if (!Win32Window::OnCreate()) {
+ return false;
+ }
+
+ RECT frame = GetClientArea();
+
+ // The size here must match the window dimensions to avoid unnecessary surface
+ // creation / destruction in the startup path.
+ flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
+ frame.right - frame.left, frame.bottom - frame.top, project_);
+ // Ensure that basic setup of the controller was successful.
+ if (!flutter_controller_->engine() || !flutter_controller_->view()) {
+ return false;
+ }
+ RegisterPlugins(flutter_controller_->engine());
+ SetChildContent(flutter_controller_->view()->GetNativeWindow());
+ return true;
+}
+
+void FlutterWindow::OnDestroy() {
+ if (flutter_controller_) {
+ flutter_controller_ = nullptr;
+ }
+
+ Win32Window::OnDestroy();
+}
+
+LRESULT
+FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ // Give Flutter, including plugins, an opportunity to handle window messages.
+ if (flutter_controller_) {
+ std::optional<LRESULT> result =
+ flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
+ lparam);
+ if (result) {
+ return *result;
+ }
+ }
+
+ switch (message) {
+ case WM_FONTCHANGE:
+ flutter_controller_->engine()->ReloadSystemFonts();
+ break;
+ }
+
+ return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
+}
diff --git a/packages/adaptive_scaffold/example/windows/runner/flutter_window.h b/packages/adaptive_scaffold/example/windows/runner/flutter_window.h
new file mode 100644
index 0000000..f1fc669
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/flutter_window.h
@@ -0,0 +1,37 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef RUNNER_FLUTTER_WINDOW_H_
+#define RUNNER_FLUTTER_WINDOW_H_
+
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+
+#include <memory>
+
+#include "win32_window.h"
+
+// A window that does nothing but host a Flutter view.
+class FlutterWindow : public Win32Window {
+ public:
+ // Creates a new FlutterWindow hosting a Flutter view running |project|.
+ explicit FlutterWindow(const flutter::DartProject& project);
+ virtual ~FlutterWindow();
+
+ protected:
+ // Win32Window:
+ bool OnCreate() override;
+ void OnDestroy() override;
+ LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
+ LPARAM const lparam) noexcept override;
+
+ private:
+ // The project to run.
+ flutter::DartProject project_;
+
+ // The Flutter instance hosted by this window.
+ std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
+};
+
+#endif // RUNNER_FLUTTER_WINDOW_H_
diff --git a/packages/adaptive_scaffold/example/windows/runner/main.cpp b/packages/adaptive_scaffold/example/windows/runner/main.cpp
new file mode 100644
index 0000000..df379fa
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/main.cpp
@@ -0,0 +1,46 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+#include <windows.h>
+
+#include "flutter_window.h"
+#include "utils.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
+ _In_ wchar_t* command_line, _In_ int show_command) {
+ // Attach to console when present (e.g., 'flutter run') or create a
+ // new console when running with a debugger.
+ if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
+ CreateAndAttachConsole();
+ }
+
+ // Initialize COM, so that it is available for use in the library and/or
+ // plugins.
+ ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+ flutter::DartProject project(L"data");
+
+ std::vector<std::string> command_line_arguments = GetCommandLineArguments();
+
+ project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
+ FlutterWindow window(project);
+ Win32Window::Point origin(10, 10);
+ Win32Window::Size size(1280, 720);
+ if (!window.CreateAndShow(L"example", origin, size)) {
+ return EXIT_FAILURE;
+ }
+ window.SetQuitOnClose(true);
+
+ ::MSG msg;
+ while (::GetMessage(&msg, nullptr, 0, 0)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+
+ ::CoUninitialize();
+ return EXIT_SUCCESS;
+}
diff --git a/packages/adaptive_scaffold/example/windows/runner/resource.h b/packages/adaptive_scaffold/example/windows/runner/resource.h
new file mode 100644
index 0000000..d5d958d
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/packages/adaptive_scaffold/example/windows/runner/resources/app_icon.ico b/packages/adaptive_scaffold/example/windows/runner/resources/app_icon.ico
new file mode 100644
index 0000000..c04e20c
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/resources/app_icon.ico
Binary files differ
diff --git a/packages/adaptive_scaffold/example/windows/runner/runner.exe.manifest b/packages/adaptive_scaffold/example/windows/runner/runner.exe.manifest
new file mode 100644
index 0000000..a42ea76
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
+ </windowsSettings>
+ </application>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 10 and Windows 11 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/packages/adaptive_scaffold/example/windows/runner/utils.cpp b/packages/adaptive_scaffold/example/windows/runner/utils.cpp
new file mode 100644
index 0000000..cb6aebe
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/utils.cpp
@@ -0,0 +1,67 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "utils.h"
+
+#include <flutter_windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include <iostream>
+
+void CreateAndAttachConsole() {
+ if (::AllocConsole()) {
+ FILE* unused;
+ if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+ _dup2(_fileno(stdout), 1);
+ }
+ if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+ _dup2(_fileno(stdout), 2);
+ }
+ std::ios::sync_with_stdio();
+ FlutterDesktopResyncOutputStreams();
+ }
+}
+
+std::vector<std::string> GetCommandLineArguments() {
+ // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+ int argc;
+ wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+ if (argv == nullptr) {
+ return std::vector<std::string>();
+ }
+
+ std::vector<std::string> command_line_arguments;
+
+ // Skip the first argument as it's the binary name.
+ for (int i = 1; i < argc; i++) {
+ command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+ }
+
+ ::LocalFree(argv);
+
+ return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+ if (utf16_string == nullptr) {
+ return std::string();
+ }
+ int target_length =
+ ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1,
+ nullptr, 0, nullptr, nullptr);
+ std::string utf8_string;
+ if (target_length == 0 || target_length > utf8_string.max_size()) {
+ return utf8_string;
+ }
+ utf8_string.resize(target_length);
+ int converted_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(),
+ target_length, nullptr, nullptr);
+ if (converted_length == 0) {
+ return std::string();
+ }
+ return utf8_string;
+}
diff --git a/packages/adaptive_scaffold/example/windows/runner/utils.h b/packages/adaptive_scaffold/example/windows/runner/utils.h
new file mode 100644
index 0000000..bd81e1e
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/utils.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef RUNNER_UTILS_H_
+#define RUNNER_UTILS_H_
+
+#include <string>
+#include <vector>
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector<std::string>,
+// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
+std::vector<std::string> GetCommandLineArguments();
+
+#endif // RUNNER_UTILS_H_
diff --git a/packages/adaptive_scaffold/example/windows/runner/win32_window.cpp b/packages/adaptive_scaffold/example/windows/runner/win32_window.cpp
new file mode 100644
index 0000000..85aa361
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/win32_window.cpp
@@ -0,0 +1,241 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "win32_window.h"
+
+#include <flutter_windows.h>
+
+#include "resource.h"
+
+namespace {
+
+constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
+
+// The number of Win32Window objects that currently exist.
+static int g_active_window_count = 0;
+
+using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
+
+// Scale helper to convert logical scaler values to physical using passed in
+// scale factor
+int Scale(int source, double scale_factor) {
+ return static_cast<int>(source * scale_factor);
+}
+
+// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
+// This API is only needed for PerMonitor V1 awareness mode.
+void EnableFullDpiSupportIfAvailable(HWND hwnd) {
+ HMODULE user32_module = LoadLibraryA("User32.dll");
+ if (!user32_module) {
+ return;
+ }
+ auto enable_non_client_dpi_scaling =
+ reinterpret_cast<EnableNonClientDpiScaling*>(
+ GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
+ if (enable_non_client_dpi_scaling != nullptr) {
+ enable_non_client_dpi_scaling(hwnd);
+ FreeLibrary(user32_module);
+ }
+}
+
+} // namespace
+
+// Manages the Win32Window's window class registration.
+class WindowClassRegistrar {
+ public:
+ ~WindowClassRegistrar() = default;
+
+ // Returns the singleton registar instance.
+ static WindowClassRegistrar* GetInstance() {
+ if (!instance_) {
+ instance_ = new WindowClassRegistrar();
+ }
+ return instance_;
+ }
+
+ // Returns the name of the window class, registering the class if it hasn't
+ // previously been registered.
+ const wchar_t* GetWindowClass();
+
+ // Unregisters the window class. Should only be called if there are no
+ // instances of the window.
+ void UnregisterWindowClass();
+
+ private:
+ WindowClassRegistrar() = default;
+
+ static WindowClassRegistrar* instance_;
+
+ bool class_registered_ = false;
+};
+
+WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
+
+const wchar_t* WindowClassRegistrar::GetWindowClass() {
+ if (!class_registered_) {
+ WNDCLASS window_class{};
+ window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ window_class.lpszClassName = kWindowClassName;
+ window_class.style = CS_HREDRAW | CS_VREDRAW;
+ window_class.cbClsExtra = 0;
+ window_class.cbWndExtra = 0;
+ window_class.hInstance = GetModuleHandle(nullptr);
+ window_class.hIcon =
+ LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
+ window_class.hbrBackground = 0;
+ window_class.lpszMenuName = nullptr;
+ window_class.lpfnWndProc = Win32Window::WndProc;
+ RegisterClass(&window_class);
+ class_registered_ = true;
+ }
+ return kWindowClassName;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass() {
+ UnregisterClass(kWindowClassName, nullptr);
+ class_registered_ = false;
+}
+
+Win32Window::Win32Window() { ++g_active_window_count; }
+
+Win32Window::~Win32Window() {
+ --g_active_window_count;
+ Destroy();
+}
+
+bool Win32Window::CreateAndShow(const std::wstring& title, const Point& origin,
+ const Size& size) {
+ Destroy();
+
+ const wchar_t* window_class =
+ WindowClassRegistrar::GetInstance()->GetWindowClass();
+
+ const POINT target_point = {static_cast<LONG>(origin.x),
+ static_cast<LONG>(origin.y)};
+ HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
+ UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
+ double scale_factor = dpi / 96.0;
+
+ HWND window = CreateWindow(
+ window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
+ Scale(size.width, scale_factor), Scale(size.height, scale_factor),
+ nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+ if (!window) {
+ return false;
+ }
+
+ return OnCreate();
+}
+
+// static
+LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ if (message == WM_NCCREATE) {
+ auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
+ SetWindowLongPtr(window, GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
+
+ auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
+ EnableFullDpiSupportIfAvailable(window);
+ that->window_handle_ = window;
+ } else if (Win32Window* that = GetThisFromHandle(window)) {
+ return that->MessageHandler(window, message, wparam, lparam);
+ }
+
+ return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ switch (message) {
+ case WM_DESTROY:
+ window_handle_ = nullptr;
+ Destroy();
+ if (quit_on_close_) {
+ PostQuitMessage(0);
+ }
+ return 0;
+
+ case WM_DPICHANGED: {
+ auto newRectSize = reinterpret_cast<RECT*>(lparam);
+ LONG newWidth = newRectSize->right - newRectSize->left;
+ LONG newHeight = newRectSize->bottom - newRectSize->top;
+
+ SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
+ newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ return 0;
+ }
+ case WM_SIZE: {
+ RECT rect = GetClientArea();
+ if (child_content_ != nullptr) {
+ // Size and position the child window.
+ MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
+ rect.bottom - rect.top, TRUE);
+ }
+ return 0;
+ }
+
+ case WM_ACTIVATE:
+ if (child_content_ != nullptr) {
+ SetFocus(child_content_);
+ }
+ return 0;
+ }
+
+ return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy() {
+ OnDestroy();
+
+ if (window_handle_) {
+ DestroyWindow(window_handle_);
+ window_handle_ = nullptr;
+ }
+ if (g_active_window_count == 0) {
+ WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
+ }
+}
+
+Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
+ return reinterpret_cast<Win32Window*>(
+ GetWindowLongPtr(window, GWLP_USERDATA));
+}
+
+void Win32Window::SetChildContent(HWND content) {
+ child_content_ = content;
+ SetParent(content, window_handle_);
+ RECT frame = GetClientArea();
+
+ MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+ frame.bottom - frame.top, true);
+
+ SetFocus(child_content_);
+}
+
+RECT Win32Window::GetClientArea() {
+ RECT frame;
+ GetClientRect(window_handle_, &frame);
+ return frame;
+}
+
+HWND Win32Window::GetHandle() { return window_handle_; }
+
+void Win32Window::SetQuitOnClose(bool quit_on_close) {
+ quit_on_close_ = quit_on_close;
+}
+
+bool Win32Window::OnCreate() {
+ // No-op; provided for subclasses.
+ return true;
+}
+
+void Win32Window::OnDestroy() {
+ // No-op; provided for subclasses.
+}
diff --git a/packages/adaptive_scaffold/example/windows/runner/win32_window.h b/packages/adaptive_scaffold/example/windows/runner/win32_window.h
new file mode 100644
index 0000000..d2a7300
--- /dev/null
+++ b/packages/adaptive_scaffold/example/windows/runner/win32_window.h
@@ -0,0 +1,99 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef RUNNER_WIN32_WINDOW_H_
+#define RUNNER_WIN32_WINDOW_H_
+
+#include <windows.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// rendering and input handling
+class Win32Window {
+ public:
+ struct Point {
+ unsigned int x;
+ unsigned int y;
+ Point(unsigned int x, unsigned int y) : x(x), y(y) {}
+ };
+
+ struct Size {
+ unsigned int width;
+ unsigned int height;
+ Size(unsigned int width, unsigned int height)
+ : width(width), height(height) {}
+ };
+
+ Win32Window();
+ virtual ~Win32Window();
+
+ // Creates and shows a win32 window with |title| and position and size using
+ // |origin| and |size|. New windows are created on the default monitor. Window
+ // sizes are specified to the OS in physical pixels, hence to ensure a
+ // consistent size to will treat the width height passed in to this function
+ // as logical pixels and scale to appropriate for the default monitor. Returns
+ // true if the window was created successfully.
+ bool CreateAndShow(const std::wstring& title, const Point& origin,
+ const Size& size);
+
+ // Release OS resources associated with window.
+ void Destroy();
+
+ // Inserts |content| into the window tree.
+ void SetChildContent(HWND content);
+
+ // Returns the backing Window handle to enable clients to set icon and other
+ // window properties. Returns nullptr if the window has been destroyed.
+ HWND GetHandle();
+
+ // If true, closing this window will quit the application.
+ void SetQuitOnClose(bool quit_on_close);
+
+ // Return a RECT representing the bounds of the current client area.
+ RECT GetClientArea();
+
+ protected:
+ // Processes and route salient window messages for mouse handling,
+ // size change and DPI. Delegates handling of these to member overloads that
+ // inheriting classes can handle.
+ virtual LRESULT MessageHandler(HWND window, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Called when CreateAndShow is called, allowing subclass window-related
+ // setup. Subclasses should return false if setup fails.
+ virtual bool OnCreate();
+
+ // Called when Destroy is called.
+ virtual void OnDestroy();
+
+ private:
+ friend class WindowClassRegistrar;
+
+ // OS callback called by message pump. Handles the WM_NCCREATE message which
+ // is passed when the non-client area is being created and enables automatic
+ // non-client DPI scaling so that the non-client area automatically
+ // responsponds to changes in DPI. All other messages are handled by
+ // MessageHandler.
+ static LRESULT CALLBACK WndProc(HWND const window, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Retrieves a class instance pointer for |window|
+ static Win32Window* GetThisFromHandle(HWND const window) noexcept;
+
+ bool quit_on_close_ = false;
+
+ // window handle for top level window.
+ HWND window_handle_ = nullptr;
+
+ // window handle for hosted content.
+ HWND child_content_ = nullptr;
+};
+
+#endif // RUNNER_WIN32_WINDOW_H_
diff --git a/packages/adaptive_scaffold/lib/src/adaptive_layout.dart b/packages/adaptive_scaffold/lib/src/adaptive_layout.dart
index 073f95c..7ed1536 100644
--- a/packages/adaptive_scaffold/lib/src/adaptive_layout.dart
+++ b/packages/adaptive_scaffold/lib/src/adaptive_layout.dart
@@ -18,23 +18,24 @@
/// Layout an app that adapts to different screens using predefined slots.
///
-/// This widget separates the app window into predefined sections called "slots".
-/// It lays out the app using the following kinds of slots (in order):
+/// This widget separates the app window into predefined sections called
+/// "slots". It lays out the app using the following kinds of slots (in order):
///
/// * [topNavigation], full width at the top. Must have defined size.
/// * [bottomNavigation], full width at the bottom. Must have defined size.
-/// * [primaryNavigation], displayed on the beginning side of the app window from
-/// the bottom of [topNavigation] to the top of [bottomNavigation]. Must have
-/// defined size.
-/// * [secondaryNavigation], displayed on the end side of the app window from the
-/// bottom of [topNavigation] to the top of [bottomNavigation]. Must have defined
-/// size.
+/// * [primaryNavigation], displayed on the beginning side of the app window
+/// from the bottom of [topNavigation] to the top of [bottomNavigation]. Must
+/// have defined size.
+/// * [secondaryNavigation], displayed on the end side of the app window from
+/// the bottom of [topNavigation] to the top of [bottomNavigation]. Must have
+/// defined size.
/// * [body], first panel; fills the remaining space from the beginning side.
-/// The main view should have flexible size (like a container).
-/// * [secondaryBody], second panel; fills the remaining space from the end side.
-/// The use of this property is common in apps that have a main view and a detail
-/// view. The main view should have flexible size (like a Container). This
-/// provides some automatic functionality with foldable screens.
+/// The main view should have flexible size (like a container).
+/// * [secondaryBody], second panel; fills the remaining space from the end
+/// side. The use of this property is common in apps that have a main view
+/// and a detail view. The main view should have flexible size (like a
+/// Container). This provides some automatic functionality with foldable
+/// screens.
///
/// Slots can display differently under different screen conditions (such as
/// different widths), and each slot is defined with a [SlotLayout], which maps
@@ -48,14 +49,17 @@
/// AdaptiveLayout(
/// primaryNavigation: SlotLayout(
/// config: {
-/// Breakpoints.small: SlotLayout.from(key: const Key('pnav'), builder: (_) => const SizedBox.shrink()),
+/// Breakpoints.small: SlotLayout.from(
+/// key: const Key('Primary Navigation Small'),
+/// builder: (_) => const SizedBox.shrink(),
+/// ),
/// Breakpoints.medium: SlotLayout.from(
/// inAnimation: leftOutIn,
-/// key: const Key('pnav1'),
+/// key: const Key('Primary Navigation Medium'),
/// builder: (_) => AdaptiveScaffold.toNavigationRail(destinations: destinations),
/// ),
/// Breakpoints.large: SlotLayout.from(
-/// key: const Key('pnav2'),
+/// key: const Key('Primary Navigation Large'),
/// inAnimation: leftOutIn,
/// builder: (_) => AdaptiveScaffold.toNavigationRail(extended: true, destinations: destinations),
/// ),
@@ -64,14 +68,14 @@
/// body: SlotLayout(
/// config: {
/// Breakpoints.small: SlotLayout.from(
-/// key: const Key('body'),
+/// key: const Key('Body Small'),
/// builder: (_) => ListView.builder(
/// itemCount: children.length,
/// itemBuilder: (_, idx) => children[idx]
/// ),
/// ),
/// Breakpoints.medium: SlotLayout.from(
-/// key: const Key('body1'),
+/// key: const Key('Body Medium'),
/// builder: (_) => GridView.count(
/// crossAxisCount: 2,
/// children: children
@@ -82,7 +86,7 @@
/// bottomNavigation: SlotLayout(
/// config: {
/// Breakpoints.small: SlotLayout.from(
-/// key: const Key('botnav'),
+/// key: const Key('Bottom Navigation Small'),
/// inAnimation: bottomToTop,
/// builder: (_) => AdaptiveScaffold.toBottomNavigationBar(destinations: destinations),
/// ),
@@ -94,14 +98,14 @@
/// See also:
///
/// * [SlotLayout], which handles the actual switching and animations between
-/// elements based on [Breakpoint]s.
+/// elements based on [Breakpoint]s.
/// * [SlotLayout.from], which holds information regarding the actual Widgets
-/// and the desired way to animate between switches. Often used within
-/// [SlotLayout].
+/// and the desired way to animate between switches. Often used within
+/// [SlotLayout].
/// * [AdaptiveScaffold], which provides a more friendly API with less
-/// customizability. and holds a preset of animations and helper builders.
+/// customizability. and holds a preset of animations and helper builders.
/// * [Design Doc](https://flutter.dev/go/adaptive-layout-foldables).
-/// * [Material Design 3 Specifications] (https://m3.material.io/foundations/adaptive-design/overview).
+/// * [Material Design 3 Specifications](https://m3.material.io/foundations/adaptive-design/overview).
class AdaptiveLayout extends StatefulWidget {
/// Creates a const [AdaptiveLayout] widget.
const AdaptiveLayout({
@@ -122,9 +126,10 @@
/// The beginning side means the right when the ambient [Directionality] is
/// [TextDirection.rtl] and on the left when it is [TextDirection.ltr].
///
- /// If the content is a flexibly sized Widget like [Container], wrap the content
- /// in a [SizedBox] or limit its size (width and height) by another method. See
- /// the builder in [AdaptiveScaffold.standardNavigationRail] for an example.
+ /// If the content is a flexibly sized Widget like [Container], wrap the
+ /// content in a [SizedBox] or limit its size (width and height) by another
+ /// method. See the builder in [AdaptiveScaffold.standardNavigationRail] for
+ /// an example.
final SlotLayout? primaryNavigation;
/// The slot placed on the end side of the app window.
@@ -132,23 +137,26 @@
/// The end side means the right when the ambient [Directionality] is
/// [TextDirection.ltr] and on the left when it is [TextDirection.rtl].
///
- /// If the content is a flexibly sized Widget like [Container], wrap the content
- /// in a [SizedBox] or limit its size (width and height) by another method. See
- /// the builder in [AdaptiveScaffold.standardNavigationRail] for an example.
+ /// If the content is a flexibly sized Widget like [Container], wrap the
+ /// content in a [SizedBox] or limit its size (width and height) by another
+ /// method. See the builder in [AdaptiveScaffold.standardNavigationRail] for
+ /// an example.
final SlotLayout? secondaryNavigation;
/// The slot placed on the top part of the app window.
///
- /// If the content is a flexibly sized Widget like [Container], wrap the content
- /// in a [SizedBox] or limit its size (width and height) by another method. See
- /// the builder in [AdaptiveScaffold.standardNavigationRail] for an example.
+ /// If the content is a flexibly sized Widget like [Container], wrap the
+ /// content in a [SizedBox] or limit its size (width and height) by another
+ /// method. See the builder in [AdaptiveScaffold.standardNavigationRail] for
+ /// an example.
final SlotLayout? topNavigation;
/// The slot placed on the bottom part of the app window.
///
- /// If the content is a flexibly sized Widget like [Container], wrap the content
- /// in a [SizedBox] or limit its size (width and height) by another method. See
- /// the builder in [AdaptiveScaffold.standardNavigationRail] for an example.
+ /// If the content is a flexibly sized Widget like [Container], wrap the
+ /// content in a [SizedBox] or limit its size (width and height) by another
+ /// method. See the builder in [AdaptiveScaffold.standardNavigationRail] for
+ /// an example.
final SlotLayout? bottomNavigation;
/// The slot that fills the rest of the space in the center.
@@ -306,7 +314,8 @@
}
}
-/// The delegate responsible for laying out the slots in their correct positions.
+/// The delegate responsible for laying out the slots in their correct
+/// positions.
class _AdaptiveLayoutDelegate extends MultiChildLayoutDelegate {
_AdaptiveLayoutDelegate({
required this.slots,
@@ -339,7 +348,8 @@
double rightMargin = 0;
double bottomMargin = 0;
- // An animation that is used as either a width or height value on the Size for the body/secondaryBody.
+ // An animation that is used as either a width or height value on the Size
+ // for the body/secondaryBody.
double animatedSize(double begin, double end) {
if (isAnimating.contains(_SlotIds.secondaryBody.name)) {
return internalAnimations
@@ -353,63 +363,76 @@
}
if (hasChild(_SlotIds.topNavigation.name)) {
- final Size childSize =
- layoutChild(_SlotIds.topNavigation.name, BoxConstraints.loose(size));
+ final Size childSize = layoutChild(
+ _SlotIds.topNavigation.name,
+ BoxConstraints.loose(size),
+ );
// Trigger the animation if the new size is different from the old size.
updateSize(_SlotIds.topNavigation.name, childSize);
- // Tween not the actual size, but the size that is used in the margins so the offsets can be animated.
+ // Tween not the actual size, but the size that is used in the margins so
+ // the offsets can be animated.
final Size currentSize = Tween<Size>(
- begin: slotSizes[_SlotIds.topNavigation.name] ?? Size.zero,
- end: childSize)
- .animate(controller)
- .value;
+ begin: slotSizes[_SlotIds.topNavigation.name] ?? Size.zero,
+ end: childSize,
+ ).animate(controller).value;
positionChild(_SlotIds.topNavigation.name, Offset.zero);
topMargin += currentSize.height;
}
if (hasChild(_SlotIds.bottomNavigation.name)) {
final Size childSize = layoutChild(
- _SlotIds.bottomNavigation.name, BoxConstraints.loose(size));
+ _SlotIds.bottomNavigation.name,
+ BoxConstraints.loose(size),
+ );
updateSize(_SlotIds.bottomNavigation.name, childSize);
final Size currentSize = Tween<Size>(
- begin: slotSizes[_SlotIds.bottomNavigation.name] ?? Size.zero,
- end: childSize)
- .animate(controller)
- .value;
- positionChild(_SlotIds.bottomNavigation.name,
- Offset(0, size.height - currentSize.height));
+ begin: slotSizes[_SlotIds.bottomNavigation.name] ?? Size.zero,
+ end: childSize,
+ ).animate(controller).value;
+ positionChild(
+ _SlotIds.bottomNavigation.name,
+ Offset(0, size.height - currentSize.height),
+ );
bottomMargin += currentSize.height;
}
if (hasChild(_SlotIds.primaryNavigation.name)) {
final Size childSize = layoutChild(
- _SlotIds.primaryNavigation.name, BoxConstraints.loose(size));
+ _SlotIds.primaryNavigation.name,
+ BoxConstraints.loose(size),
+ );
updateSize(_SlotIds.primaryNavigation.name, childSize);
final Size currentSize = Tween<Size>(
- begin: slotSizes[_SlotIds.primaryNavigation.name] ?? Size.zero,
- end: childSize)
- .animate(controller)
- .value;
+ begin: slotSizes[_SlotIds.primaryNavigation.name] ?? Size.zero,
+ end: childSize,
+ ).animate(controller).value;
if (textDirection) {
positionChild(
- _SlotIds.primaryNavigation.name, Offset(leftMargin, topMargin));
+ _SlotIds.primaryNavigation.name,
+ Offset(leftMargin, topMargin),
+ );
leftMargin += currentSize.width;
} else {
- positionChild(_SlotIds.primaryNavigation.name,
- Offset(size.width - currentSize.width, topMargin));
+ positionChild(
+ _SlotIds.primaryNavigation.name,
+ Offset(size.width - currentSize.width, topMargin),
+ );
rightMargin += currentSize.width;
}
}
if (hasChild(_SlotIds.secondaryNavigation.name)) {
final Size childSize = layoutChild(
- _SlotIds.secondaryNavigation.name, BoxConstraints.loose(size));
+ _SlotIds.secondaryNavigation.name,
+ BoxConstraints.loose(size),
+ );
updateSize(_SlotIds.secondaryNavigation.name, childSize);
final Size currentSize = Tween<Size>(
- begin: slotSizes[_SlotIds.secondaryNavigation.name] ?? Size.zero,
- end: childSize)
- .animate(controller)
- .value;
+ begin: slotSizes[_SlotIds.secondaryNavigation.name] ?? Size.zero,
+ end: childSize,
+ ).animate(controller).value;
if (textDirection) {
- positionChild(_SlotIds.secondaryNavigation.name,
- Offset(size.width - currentSize.width, topMargin));
+ positionChild(
+ _SlotIds.secondaryNavigation.name,
+ Offset(size.width - currentSize.width, topMargin),
+ );
rightMargin += currentSize.width;
} else {
positionChild(_SlotIds.secondaryNavigation.name, Offset(0, topMargin));
@@ -429,8 +452,12 @@
if (chosenWidgets[_SlotIds.secondaryBody.name] == null ||
chosenWidgets[_SlotIds.secondaryBody.name]!.builder == null) {
if (!textDirection) {
- currentBodySize = layoutChild(_SlotIds.body.name,
- BoxConstraints.tight(Size(remainingWidth, remainingHeight)));
+ currentBodySize = layoutChild(
+ _SlotIds.body.name,
+ BoxConstraints.tight(
+ Size(remainingWidth, remainingHeight),
+ ),
+ );
} else if (bodyOrientation == Axis.horizontal) {
double beginWidth;
if (bodyRatio == null) {
@@ -439,9 +466,11 @@
beginWidth = remainingWidth * bodyRatio!;
}
currentBodySize = layoutChild(
- _SlotIds.body.name,
- BoxConstraints.tight(Size(
- animatedSize(beginWidth, remainingWidth), remainingHeight)));
+ _SlotIds.body.name,
+ BoxConstraints.tight(
+ Size(animatedSize(beginWidth, remainingWidth), remainingHeight),
+ ),
+ );
} else {
double beginHeight;
if (bodyRatio == null) {
@@ -450,9 +479,11 @@
beginHeight = remainingHeight * bodyRatio!;
}
currentBodySize = layoutChild(
- _SlotIds.body.name,
- BoxConstraints.tight(Size(
- remainingWidth, animatedSize(beginHeight, remainingHeight))));
+ _SlotIds.body.name,
+ BoxConstraints.tight(
+ Size(remainingWidth, animatedSize(beginHeight, remainingHeight)),
+ ),
+ );
}
layoutChild(_SlotIds.secondaryBody.name, BoxConstraints.loose(size));
} else {
@@ -475,12 +506,18 @@
}
currentBodySize = layoutChild(
- _SlotIds.body.name,
- BoxConstraints.tight(Size(
- animatedSize(remainingWidth, finalBodySize),
- remainingHeight)));
- layoutChild(_SlotIds.secondaryBody.name,
- BoxConstraints.tight(Size(finalSBodySize, remainingHeight)));
+ _SlotIds.body.name,
+ BoxConstraints.tight(
+ Size(animatedSize(remainingWidth, finalBodySize),
+ remainingHeight),
+ ),
+ );
+ layoutChild(
+ _SlotIds.secondaryBody.name,
+ BoxConstraints.tight(
+ Size(finalSBodySize, remainingHeight),
+ ),
+ );
} else {
// Take this path if the textDirection is RTL.
double finalBodySize;
@@ -497,11 +534,17 @@
finalSBodySize = halfWidth - leftMargin;
}
currentSBodySize = layoutChild(
- _SlotIds.secondaryBody.name,
- BoxConstraints.tight(
- Size(animatedSize(0, finalSBodySize), remainingHeight)));
- layoutChild(_SlotIds.body.name,
- BoxConstraints.tight(Size(finalBodySize, remainingHeight)));
+ _SlotIds.secondaryBody.name,
+ BoxConstraints.tight(
+ Size(animatedSize(0, finalSBodySize), remainingHeight),
+ ),
+ );
+ layoutChild(
+ _SlotIds.body.name,
+ BoxConstraints.tight(
+ Size(finalBodySize, remainingHeight),
+ ),
+ );
}
} else {
// Take this path if the body and secondaryBody are laid out vertically.
@@ -538,14 +581,16 @@
chosenWidgets[_SlotIds.secondaryBody.name] != null) {
if (hinge != null) {
positionChild(
- _SlotIds.body.name,
- Offset(
- currentSBodySize.width + leftMargin + hingeWidth, topMargin));
+ _SlotIds.body.name,
+ Offset(currentSBodySize.width + leftMargin + hingeWidth, topMargin),
+ );
positionChild(
_SlotIds.secondaryBody.name, Offset(leftMargin, topMargin));
} else {
- positionChild(_SlotIds.body.name,
- Offset(currentSBodySize.width + leftMargin, topMargin));
+ positionChild(
+ _SlotIds.body.name,
+ Offset(currentSBodySize.width + leftMargin, topMargin),
+ );
positionChild(
_SlotIds.secondaryBody.name, Offset(leftMargin, topMargin));
}
@@ -554,25 +599,38 @@
if (bodyOrientation == Axis.horizontal) {
if (hinge != null) {
positionChild(
- _SlotIds.secondaryBody.name,
- Offset(currentBodySize.width + leftMargin + hingeWidth,
- topMargin));
+ _SlotIds.secondaryBody.name,
+ Offset(
+ currentBodySize.width + leftMargin + hingeWidth, topMargin),
+ );
} else {
- positionChild(_SlotIds.secondaryBody.name,
- Offset(currentBodySize.width + leftMargin, topMargin));
+ positionChild(
+ _SlotIds.secondaryBody.name,
+ Offset(currentBodySize.width + leftMargin, topMargin),
+ );
}
} else {
- positionChild(_SlotIds.secondaryBody.name,
- Offset(leftMargin, topMargin + currentBodySize.height));
+ positionChild(
+ _SlotIds.secondaryBody.name,
+ Offset(leftMargin, topMargin + currentBodySize.height),
+ );
}
}
} else if (hasChild(_SlotIds.body.name)) {
- layoutChild(_SlotIds.body.name,
- BoxConstraints.tight(Size(remainingWidth, remainingHeight)));
+ layoutChild(
+ _SlotIds.body.name,
+ BoxConstraints.tight(
+ Size(remainingWidth, remainingHeight),
+ ),
+ );
positionChild(_SlotIds.body.name, Offset(leftMargin, topMargin));
} else if (hasChild(_SlotIds.secondaryBody.name)) {
- layoutChild(_SlotIds.secondaryBody.name,
- BoxConstraints.tight(Size(remainingWidth, remainingHeight)));
+ layoutChild(
+ _SlotIds.secondaryBody.name,
+ BoxConstraints.tight(
+ Size(remainingWidth, remainingHeight),
+ ),
+ );
}
}
diff --git a/packages/adaptive_scaffold/lib/src/adaptive_scaffold.dart b/packages/adaptive_scaffold/lib/src/adaptive_scaffold.dart
index 07c83f0..c64ee3f 100644
--- a/packages/adaptive_scaffold/lib/src/adaptive_scaffold.dart
+++ b/packages/adaptive_scaffold/lib/src/adaptive_scaffold.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
-import 'package:masonry_grid/masonry_grid.dart';
import 'adaptive_layout.dart';
import 'breakpoints.dart';
@@ -309,15 +308,19 @@
int currentIndex = 0,
double iconSize = 24}) {
return Builder(
- builder: (_) => BottomNavigationBar(
- currentIndex: currentIndex,
- iconSize: iconSize,
- items: destinations
- .map((NavigationDestination e) => _toBottomNavItem(e))
- .toList()));
+ builder: (_) {
+ return BottomNavigationBar(
+ currentIndex: currentIndex,
+ iconSize: iconSize,
+ items: destinations
+ .map((NavigationDestination e) => _toBottomNavItem(e))
+ .toList(),
+ );
+ },
+ );
}
- /// Public helper method to be used for creating a [MasonryGrid] following m3
+ /// Public helper method to be used for creating a staggered grid following m3
/// specs from a list of [Widget]s
static Builder toMaterialGrid({
List<Widget> thisWidgets = const <Widget>[],
@@ -361,10 +364,11 @@
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.all(thisMargin),
- child: MasonryGrid(
- column: itemColumns,
- crossAxisSpacing: kMaterialGutterValue,
- mainAxisSpacing: kMaterialGutterValue,
+ child: _BrickLayout(
+ columns: itemColumns,
+ columnSpacing: kMaterialGutterValue,
+ itemPadding:
+ const EdgeInsets.only(bottom: kMaterialGutterValue),
children: thisWidgets,
),
),
@@ -441,7 +445,9 @@
static Widget fadeOut(Widget child, Animation<double> animation) {
return FadeTransition(
opacity: CurvedAnimation(
- parent: ReverseAnimation(animation), curve: Curves.easeInCubic),
+ parent: ReverseAnimation(animation),
+ curve: Curves.easeInCubic,
+ ),
child: child,
);
}
@@ -615,3 +621,102 @@
icon: destination.icon,
);
}
+
+class _BrickLayout extends StatelessWidget {
+ const _BrickLayout({
+ this.columns = 1,
+ this.itemPadding = EdgeInsets.zero,
+ this.columnSpacing = 0,
+ required this.children,
+ });
+
+ final int columns;
+ final double columnSpacing;
+ final EdgeInsetsGeometry itemPadding;
+ final List<Widget> children;
+
+ @override
+ Widget build(BuildContext context) {
+ int i = -1;
+ return Column(
+ mainAxisSize: MainAxisSize.min,
+ children: <Widget>[
+ Expanded(
+ child: CustomMultiChildLayout(
+ delegate: _BrickLayoutDelegate(
+ columns: columns,
+ columnSpacing: columnSpacing,
+ itemPadding: itemPadding,
+ ),
+ children: children
+ .map<Widget>(
+ (Widget child) => LayoutId(id: i += 1, child: child),
+ )
+ .toList(),
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class _BrickLayoutDelegate extends MultiChildLayoutDelegate {
+ _BrickLayoutDelegate({
+ this.columns = 1,
+ this.columnSpacing = 0,
+ this.itemPadding = EdgeInsets.zero,
+ });
+
+ final int columns;
+ final EdgeInsetsGeometry itemPadding;
+ final double columnSpacing;
+
+ @override
+ void performLayout(Size size) {
+ final BoxConstraints looseConstraints = BoxConstraints.loose(size);
+ final BoxConstraints fullWidthConstraints =
+ looseConstraints.tighten(width: size.width);
+
+ final List<Size> childSizes = <Size>[];
+ int childCount = 0;
+ // Count how many children we have.
+ for (; hasChild(childCount); childCount += 1) {}
+ final BoxConstraints itemConstraints = BoxConstraints(
+ maxWidth: fullWidthConstraints.maxWidth / columns -
+ columnSpacing / 2 -
+ itemPadding.horizontal,
+ );
+
+ for (int i = 0; i < childCount; i += 1) {
+ childSizes.add(layoutChild(i, itemConstraints));
+ }
+
+ int columnIndex = 0;
+ int childId = 0;
+ final double totalColumnSpacing = columnSpacing * (columns - 1);
+ final double columnWidth = (size.width - totalColumnSpacing) / columns;
+ final double topPadding = itemPadding.resolve(TextDirection.ltr).top;
+ final List<double> columnUsage =
+ List<double>.generate(columns, (int index) => topPadding);
+ for (final Size childSize in childSizes) {
+ positionChild(
+ childId,
+ Offset(
+ columnSpacing * columnIndex +
+ columnWidth * columnIndex +
+ (columnWidth - childSize.width) / 2,
+ columnUsage[columnIndex],
+ ),
+ );
+ columnUsage[columnIndex] += childSize.height + itemPadding.vertical;
+ columnIndex = (columnIndex + 1) % columns;
+ childId += 1;
+ }
+ }
+
+ @override
+ bool shouldRelayout(_BrickLayoutDelegate oldDelegate) {
+ return itemPadding != oldDelegate.itemPadding ||
+ columnSpacing != oldDelegate.columnSpacing;
+ }
+}
diff --git a/packages/adaptive_scaffold/lib/src/breakpoints.dart b/packages/adaptive_scaffold/lib/src/breakpoints.dart
index 702287b..e236189 100644
--- a/packages/adaptive_scaffold/lib/src/breakpoints.dart
+++ b/packages/adaptive_scaffold/lib/src/breakpoints.dart
@@ -79,8 +79,8 @@
/// no lower bound.
final double? begin;
- /// The end width dp value. If left null then the [Breakpoint] will have
- /// no upper bound.
+ /// The end width dp value. If left null then the [Breakpoint] will have no
+ /// upper bound.
final double? end;
/// A Set of [TargetPlatform]s that the [Breakpoint] will be active on. If
@@ -112,8 +112,8 @@
/// Override this class by defining `isActive` to fetch the screen property
/// (usually `MediaQuery.of`) and return true if the condition is met.
///
-/// Breakpoints do not need to be exclusive because they are tested in order with
-/// the last Breakpoint active taking priority.
+/// Breakpoints do not need to be exclusive because they are tested in order
+/// with the last Breakpoint active taking priority.
///
/// If the condition is only based on the screen width and/or the device type,
/// use [WidthPlatformBreakpoint] to define the [Breakpoint].
@@ -123,7 +123,7 @@
/// * [SlotLayout.config], which uses breakpoints to dictate the layout of the
/// screen.
abstract class Breakpoint {
- /// Returns a [Breakpoint].
+ /// Returns a const [Breakpoint].
const Breakpoint();
/// A method that returns true based on conditions related to the context of
diff --git a/packages/adaptive_scaffold/pubspec.yaml b/packages/adaptive_scaffold/pubspec.yaml
index 87c1952..1733318 100644
--- a/packages/adaptive_scaffold/pubspec.yaml
+++ b/packages/adaptive_scaffold/pubspec.yaml
@@ -7,13 +7,12 @@
publish_to: none
environment:
- sdk: '>=2.17.0 <3.0.0'
+ sdk: '>=2.18.0 <3.0.0'
flutter: ">=3.0.0"
dependencies:
flutter:
sdk: flutter
- masonry_grid: ^1.0.0
dev_dependencies:
flutter_test:
diff --git a/packages/adaptive_scaffold/test/adaptive_layout_test.dart b/packages/adaptive_scaffold/test/adaptive_layout_test.dart
index 7a84193..7405d65 100644
--- a/packages/adaptive_scaffold/test/adaptive_layout_test.dart
+++ b/packages/adaptive_scaffold/test/adaptive_layout_test.dart
@@ -8,6 +8,240 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
+void main() {
+ testWidgets(
+ 'slot layout displays correct item of config based on screen width',
+ (WidgetTester tester) async {
+ MediaQuery slot(double width) {
+ return MediaQuery(
+ data: MediaQueryData.fromWindow(WidgetsBinding.instance.window)
+ .copyWith(size: Size(width, 800)),
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: SlotLayout(
+ config: <Breakpoint, SlotLayoutConfig>{
+ TestBreakpoint0(): SlotLayout.from(
+ key: const Key('0'), builder: (_) => const SizedBox()),
+ TestBreakpoint400(): SlotLayout.from(
+ key: const Key('400'), builder: (_) => const SizedBox()),
+ TestBreakpoint800(): SlotLayout.from(
+ key: const Key('800'), builder: (_) => const SizedBox()),
+ },
+ ),
+ ),
+ );
+ }
+
+ await tester.pumpWidget(slot(300));
+ expect(find.byKey(const Key('0')), findsOneWidget);
+ expect(find.byKey(const Key('400')), findsNothing);
+ expect(find.byKey(const Key('800')), findsNothing);
+
+ await tester.pumpWidget(slot(500));
+ expect(find.byKey(const Key('0')), findsNothing);
+ expect(find.byKey(const Key('400')), findsOneWidget);
+ expect(find.byKey(const Key('800')), findsNothing);
+
+ await tester.pumpWidget(slot(1000));
+ expect(find.byKey(const Key('0')), findsNothing);
+ expect(find.byKey(const Key('400')), findsNothing);
+ expect(find.byKey(const Key('800')), findsOneWidget);
+ });
+
+ testWidgets('adaptive layout displays children in correct places',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(await layout(width: 400, tester: tester));
+ await tester.pumpAndSettle();
+ expect(tester.getTopLeft(topNavigation), Offset.zero);
+ expect(tester.getTopLeft(secondaryNavigation), const Offset(390, 10));
+ expect(tester.getTopLeft(primaryNavigation), const Offset(0, 10));
+ expect(tester.getTopLeft(bottomNavigation), const Offset(0, 790));
+ expect(tester.getTopLeft(testBreakpoint), const Offset(10, 10));
+ expect(tester.getBottomRight(testBreakpoint), const Offset(200, 790));
+ expect(tester.getTopLeft(secondaryTestBreakpoint), const Offset(200, 10));
+ expect(
+ tester.getBottomRight(secondaryTestBreakpoint), const Offset(390, 790));
+ });
+
+ testWidgets('adaptive layout correct layout when body vertical',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ await layout(width: 400, tester: tester, orientation: Axis.vertical));
+ await tester.pumpAndSettle();
+ expect(tester.getTopLeft(topNavigation), Offset.zero);
+ expect(tester.getTopLeft(secondaryNavigation), const Offset(390, 10));
+ expect(tester.getTopLeft(primaryNavigation), const Offset(0, 10));
+ expect(tester.getTopLeft(bottomNavigation), const Offset(0, 790));
+ expect(tester.getTopLeft(testBreakpoint), const Offset(10, 10));
+ expect(tester.getBottomRight(testBreakpoint), const Offset(390, 400));
+ expect(tester.getTopLeft(secondaryTestBreakpoint), const Offset(10, 400));
+ expect(
+ tester.getBottomRight(secondaryTestBreakpoint), const Offset(390, 790));
+ });
+
+ testWidgets('adaptive layout correct layout when rtl',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(await layout(
+ width: 400, tester: tester, directionality: TextDirection.rtl));
+ await tester.pumpAndSettle();
+ expect(tester.getTopLeft(topNavigation), Offset.zero);
+ expect(tester.getTopLeft(secondaryNavigation), const Offset(0, 10));
+ expect(tester.getTopLeft(primaryNavigation), const Offset(390, 10));
+ expect(tester.getTopLeft(bottomNavigation), const Offset(0, 790));
+ expect(tester.getTopLeft(testBreakpoint), const Offset(200, 10));
+ expect(tester.getBottomRight(testBreakpoint), const Offset(390, 790));
+ expect(tester.getTopLeft(secondaryTestBreakpoint), const Offset(10, 10));
+ expect(
+ tester.getBottomRight(secondaryTestBreakpoint), const Offset(200, 790));
+ });
+
+ testWidgets('adaptive layout correct layout when body ratio not default',
+ (WidgetTester tester) async {
+ await tester
+ .pumpWidget(await layout(width: 400, tester: tester, bodyRatio: 1 / 3));
+ await tester.pumpAndSettle();
+ expect(tester.getTopLeft(topNavigation), Offset.zero);
+ expect(tester.getTopLeft(secondaryNavigation), const Offset(390, 10));
+ expect(tester.getTopLeft(primaryNavigation), const Offset(0, 10));
+ expect(tester.getTopLeft(bottomNavigation), const Offset(0, 790));
+ expect(tester.getTopLeft(testBreakpoint), const Offset(10, 10));
+ expect(tester.getBottomRight(testBreakpoint),
+ offsetMoreOrLessEquals(const Offset(136.7, 790), epsilon: 1.0));
+ expect(tester.getTopLeft(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(136.7, 10), epsilon: 1.0));
+ expect(
+ tester.getBottomRight(secondaryTestBreakpoint), const Offset(390, 790));
+ });
+
+ final Finder begin = find.byKey(const Key('0'));
+ final Finder end = find.byKey(const Key('400'));
+ Finder slideIn(String key) => find.byKey(Key('in-${Key(key)}'));
+ Finder slideOut(String key) => find.byKey(Key('out-${Key(key)}'));
+ testWidgets(
+ 'slot layout properly switches between items with the appropriate animation',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(slot(300));
+ expect(begin, findsOneWidget);
+ expect(end, findsNothing);
+
+ await tester.pumpWidget(slot(500));
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 500));
+ expect(tester.widget<SlideTransition>(slideOut('0')).position.value,
+ const Offset(-0.5, 0));
+ expect(tester.widget<SlideTransition>(slideIn('400')).position.value,
+ const Offset(-0.5, 0));
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 500));
+ expect(tester.widget<SlideTransition>(slideOut('0')).position.value,
+ const Offset(-1.0, 0));
+ expect(tester.widget<SlideTransition>(slideIn('400')).position.value,
+ Offset.zero);
+
+ await tester.pumpAndSettle();
+ expect(begin, findsNothing);
+ expect(end, findsOneWidget);
+ });
+ testWidgets('slot layout can tolerate rapid changes in breakpoints',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(slot(300));
+ expect(begin, findsOneWidget);
+ expect(end, findsNothing);
+
+ await tester.pumpWidget(slot(500));
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 100));
+ expect(tester.widget<SlideTransition>(slideOut('0')).position.value,
+ offsetMoreOrLessEquals(const Offset(-0.1, 0), epsilon: 0.05));
+ expect(tester.widget<SlideTransition>(slideIn('400')).position.value,
+ offsetMoreOrLessEquals(const Offset(-0.9, 0), epsilon: 0.05));
+ await tester.pumpWidget(slot(300));
+ await tester.pumpAndSettle();
+ expect(begin, findsOneWidget);
+ expect(end, findsNothing);
+ // TODO(gspencergoog): Remove skip when AnimatedSwitcher fix rolls into stable.
+ // https://github.com/flutter/flutter/pull/107476
+ }, skip: true);
+
+ // This test reflects the behavior of the internal animations of both the body
+ // and secondary body and also the navigational items. This is reflected in
+ // the changes in LTRB offsets from all sides instead of just LR for the body
+ // animations.
+ testWidgets('adaptive layout handles internal animations correctly',
+ (WidgetTester tester) async {
+ final Finder testBreakpoint = find.byKey(const Key('Test Breakpoint'));
+ final Finder secondaryTestBreakpoint =
+ find.byKey(const Key('Secondary Test Breakpoint'));
+
+ await tester.pumpWidget(await layout(width: 400, tester: tester));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 100));
+
+ expect(tester.getTopLeft(testBreakpoint), const Offset(1, 1));
+ expect(tester.getBottomRight(testBreakpoint),
+ offsetMoreOrLessEquals(const Offset(395.8, 799), epsilon: 1.0));
+ expect(tester.getTopLeft(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(395.8, 1.0), epsilon: 1.0));
+ expect(tester.getBottomRight(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(594.8, 799.0), epsilon: 1.0));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 400));
+
+ expect(tester.getTopLeft(testBreakpoint), const Offset(5, 5));
+ expect(tester.getBottomRight(testBreakpoint),
+ offsetMoreOrLessEquals(const Offset(294.2, 795), epsilon: 1.0));
+ expect(tester.getTopLeft(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(294.2, 5.0), epsilon: 1.0));
+ expect(tester.getBottomRight(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(489.2, 795.0), epsilon: 1.0));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 400));
+
+ expect(tester.getTopLeft(testBreakpoint), const Offset(9, 9));
+ expect(tester.getBottomRight(testBreakpoint),
+ offsetMoreOrLessEquals(const Offset(201.7, 791), epsilon: 1.0));
+ expect(tester.getTopLeft(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(201.7, 9.0), epsilon: 1.0));
+ expect(tester.getBottomRight(secondaryTestBreakpoint),
+ offsetMoreOrLessEquals(const Offset(392.7, 791), epsilon: 1.0));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 100));
+
+ expect(tester.getTopLeft(testBreakpoint), const Offset(10, 10));
+ expect(tester.getBottomRight(testBreakpoint), const Offset(200, 790));
+ expect(tester.getTopLeft(secondaryTestBreakpoint), const Offset(200, 10));
+ expect(
+ tester.getBottomRight(secondaryTestBreakpoint), const Offset(390, 790));
+ // TODO(gspencergoog): Remove skip when AnimatedSwitcher fix rolls into stable.
+ // https://github.com/flutter/flutter/pull/107476
+ }, skip: true);
+
+ testWidgets('adaptive layout does not animate when animations off',
+ (WidgetTester tester) async {
+ final Finder testBreakpoint = find.byKey(const Key('Test Breakpoint'));
+ final Finder secondaryTestBreakpoint =
+ find.byKey(const Key('Secondary Test Breakpoint'));
+
+ await tester.pumpWidget(
+ await layout(width: 400, tester: tester, animations: false));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 100));
+
+ expect(tester.getTopLeft(testBreakpoint), const Offset(10, 10));
+ expect(tester.getBottomRight(testBreakpoint), const Offset(200, 790));
+ expect(tester.getTopLeft(secondaryTestBreakpoint), const Offset(200, 10));
+ expect(
+ tester.getBottomRight(secondaryTestBreakpoint), const Offset(390, 790));
+ // TODO(gspencergoog): Remove skip when AnimatedSwitcher fix rolls into stable.
+ // https://github.com/flutter/flutter/pull/107476
+ }, skip: true);
+}
+
class TestBreakpoint0 extends Breakpoint {
@override
bool isActive(BuildContext context) {
@@ -29,12 +263,16 @@
}
}
-final Finder tnav = find.byKey(const Key('tnav'));
-final Finder snav = find.byKey(const Key('snav'));
-final Finder pnav = find.byKey(const Key('pnav'));
-final Finder bnav = find.byKey(const Key('bnav'));
-final Finder b = find.byKey(const Key('b'));
-final Finder sb = find.byKey(const Key('sb'));
+final Finder topNavigation = find.byKey(const Key('Top Navigation'));
+final Finder secondaryNavigation =
+ find.byKey(const Key('Secondary Navigation Small'));
+final Finder primaryNavigation =
+ find.byKey(const Key('Primary Navigation Small'));
+final Finder bottomNavigation =
+ find.byKey(const Key('Bottom Navigation Small'));
+final Finder testBreakpoint = find.byKey(const Key('Test Breakpoint'));
+final Finder secondaryTestBreakpoint =
+ find.byKey(const Key('Secondary Test Breakpoint'));
Widget on(BuildContext _) {
return const SizedBox(width: 10, height: 10);
@@ -59,38 +297,38 @@
internalAnimations: animations,
primaryNavigation: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
- TestBreakpoint0():
- SlotLayout.from(key: const Key('pnav'), builder: on),
- TestBreakpoint400():
- SlotLayout.from(key: const Key('pnav1'), builder: on),
- TestBreakpoint800():
- SlotLayout.from(key: const Key('pnav2'), builder: on),
+ TestBreakpoint0(): SlotLayout.from(
+ key: const Key('Primary Navigation Small'), builder: on),
+ TestBreakpoint400(): SlotLayout.from(
+ key: const Key('Primary Navigation Medium'), builder: on),
+ TestBreakpoint800(): SlotLayout.from(
+ key: const Key('Primary Navigation Large'), builder: on),
},
),
secondaryNavigation: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
- TestBreakpoint0():
- SlotLayout.from(key: const Key('snav'), builder: on),
- TestBreakpoint400():
- SlotLayout.from(key: const Key('snav1'), builder: on),
- TestBreakpoint800():
- SlotLayout.from(key: const Key('snav2'), builder: on),
+ TestBreakpoint0(): SlotLayout.from(
+ key: const Key('Secondary Navigation Small'), builder: on),
+ TestBreakpoint400(): SlotLayout.from(
+ key: const Key('Secondary Navigation Medium'), builder: on),
+ TestBreakpoint800(): SlotLayout.from(
+ key: const Key('Secondary Navigation Large'), builder: on),
},
),
topNavigation: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
TestBreakpoint0():
- SlotLayout.from(key: const Key('tnav'), builder: on),
+ SlotLayout.from(key: const Key('Top Navigation'), builder: on),
TestBreakpoint400():
- SlotLayout.from(key: const Key('tnav1'), builder: on),
+ SlotLayout.from(key: const Key('Top Navigation1'), builder: on),
TestBreakpoint800():
- SlotLayout.from(key: const Key('tnav2'), builder: on),
+ SlotLayout.from(key: const Key('Top Navigation2'), builder: on),
},
),
bottomNavigation: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
- TestBreakpoint0():
- SlotLayout.from(key: const Key('bnav'), builder: on),
+ TestBreakpoint0(): SlotLayout.from(
+ key: const Key('Bottom Navigation Small'), builder: on),
TestBreakpoint400():
SlotLayout.from(key: const Key('bnav1'), builder: on),
TestBreakpoint800():
@@ -100,15 +338,15 @@
body: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
TestBreakpoint0(): SlotLayout.from(
- key: const Key('b'),
+ key: const Key('Test Breakpoint'),
builder: (_) => Container(color: Colors.red),
),
TestBreakpoint400(): SlotLayout.from(
- key: const Key('b1'),
+ key: const Key('Test Breakpoint 1'),
builder: (_) => Container(color: Colors.red),
),
TestBreakpoint800(): SlotLayout.from(
- key: const Key('b2'),
+ key: const Key('Test Breakpoint 2'),
builder: (_) => Container(color: Colors.red),
),
},
@@ -116,15 +354,15 @@
secondaryBody: SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
TestBreakpoint0(): SlotLayout.from(
- key: const Key('sb'),
+ key: const Key('Secondary Test Breakpoint'),
builder: (_) => Container(color: Colors.blue),
),
TestBreakpoint400(): SlotLayout.from(
- key: const Key('sb1'),
+ key: const Key('Secondary Test Breakpoint 1'),
builder: (_) => Container(color: Colors.blue),
),
TestBreakpoint800(): SlotLayout.from(
- key: const Key('sb2'),
+ key: const Key('Secondary Test Breakpoint 2'),
builder: (_) => Container(color: Colors.blue),
),
},
@@ -181,227 +419,3 @@
),
);
}
-
-void main() {
- testWidgets(
- 'slot layout dislays correct item of config based on screen width',
- (WidgetTester tester) async {
- MediaQuery slot(double width) {
- return MediaQuery(
- data: MediaQueryData.fromWindow(WidgetsBinding.instance.window)
- .copyWith(size: Size(width, 800)),
- child: Directionality(
- textDirection: TextDirection.ltr,
- child: SlotLayout(
- config: <Breakpoint, SlotLayoutConfig>{
- TestBreakpoint0(): SlotLayout.from(
- key: const Key('0'), builder: (_) => const SizedBox()),
- TestBreakpoint400(): SlotLayout.from(
- key: const Key('400'), builder: (_) => const SizedBox()),
- TestBreakpoint800(): SlotLayout.from(
- key: const Key('800'), builder: (_) => const SizedBox()),
- },
- ),
- ),
- );
- }
-
- await tester.pumpWidget(slot(300));
- expect(find.byKey(const Key('0')), findsOneWidget);
- expect(find.byKey(const Key('400')), findsNothing);
- expect(find.byKey(const Key('800')), findsNothing);
-
- await tester.pumpWidget(slot(500));
- expect(find.byKey(const Key('0')), findsNothing);
- expect(find.byKey(const Key('400')), findsOneWidget);
- expect(find.byKey(const Key('800')), findsNothing);
-
- await tester.pumpWidget(slot(1000));
- expect(find.byKey(const Key('0')), findsNothing);
- expect(find.byKey(const Key('400')), findsNothing);
- expect(find.byKey(const Key('800')), findsOneWidget);
- });
-
- testWidgets('adaptive layout displays children in correct places',
- (WidgetTester tester) async {
- await tester.pumpWidget(await layout(width: 400, tester: tester));
- await tester.pumpAndSettle();
- expect(tester.getTopLeft(tnav), Offset.zero);
- expect(tester.getTopLeft(snav), const Offset(390, 10));
- expect(tester.getTopLeft(pnav), const Offset(0, 10));
- expect(tester.getTopLeft(bnav), const Offset(0, 790));
- expect(tester.getTopLeft(b), const Offset(10, 10));
- expect(tester.getBottomRight(b), const Offset(200, 790));
- expect(tester.getTopLeft(sb), const Offset(200, 10));
- expect(tester.getBottomRight(sb), const Offset(390, 790));
- });
-
- testWidgets('adaptive layout correct layout when body vertical',
- (WidgetTester tester) async {
- await tester.pumpWidget(
- await layout(width: 400, tester: tester, orientation: Axis.vertical));
- await tester.pumpAndSettle();
- expect(tester.getTopLeft(tnav), Offset.zero);
- expect(tester.getTopLeft(snav), const Offset(390, 10));
- expect(tester.getTopLeft(pnav), const Offset(0, 10));
- expect(tester.getTopLeft(bnav), const Offset(0, 790));
- expect(tester.getTopLeft(b), const Offset(10, 10));
- expect(tester.getBottomRight(b), const Offset(390, 400));
- expect(tester.getTopLeft(sb), const Offset(10, 400));
- expect(tester.getBottomRight(sb), const Offset(390, 790));
- });
-
- testWidgets('adaptive layout correct layout when rtl',
- (WidgetTester tester) async {
- await tester.pumpWidget(await layout(
- width: 400, tester: tester, directionality: TextDirection.rtl));
- await tester.pumpAndSettle();
- expect(tester.getTopLeft(tnav), Offset.zero);
- expect(tester.getTopLeft(snav), const Offset(0, 10));
- expect(tester.getTopLeft(pnav), const Offset(390, 10));
- expect(tester.getTopLeft(bnav), const Offset(0, 790));
- expect(tester.getTopLeft(b), const Offset(200, 10));
- expect(tester.getBottomRight(b), const Offset(390, 790));
- expect(tester.getTopLeft(sb), const Offset(10, 10));
- expect(tester.getBottomRight(sb), const Offset(200, 790));
- });
-
- testWidgets('adaptive layout correct layout when body ratio not default',
- (WidgetTester tester) async {
- await tester
- .pumpWidget(await layout(width: 400, tester: tester, bodyRatio: 1 / 3));
- await tester.pumpAndSettle();
- expect(tester.getTopLeft(tnav), Offset.zero);
- expect(tester.getTopLeft(snav), const Offset(390, 10));
- expect(tester.getTopLeft(pnav), const Offset(0, 10));
- expect(tester.getTopLeft(bnav), const Offset(0, 790));
- expect(tester.getTopLeft(b), const Offset(10, 10));
- expect(tester.getBottomRight(b),
- offsetMoreOrLessEquals(const Offset(136.7, 790), epsilon: 1.0));
- expect(tester.getTopLeft(sb),
- offsetMoreOrLessEquals(const Offset(136.7, 10), epsilon: 1.0));
- expect(tester.getBottomRight(sb), const Offset(390, 790));
- });
-
- final Finder begin = find.byKey(const Key('0'));
- final Finder end = find.byKey(const Key('400'));
- Finder slideIn(String key) => find.byKey(Key('in-${Key(key)}'));
- Finder slideOut(String key) => find.byKey(Key('out-${Key(key)}'));
- testWidgets(
- 'slot layout properly switches between items with the appropriate animation',
- (WidgetTester tester) async {
- await tester.pumpWidget(slot(300));
- expect(begin, findsOneWidget);
- expect(end, findsNothing);
-
- await tester.pumpWidget(slot(500));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 500));
- expect(tester.widget<SlideTransition>(slideOut('0')).position.value,
- const Offset(-0.5, 0));
- expect(tester.widget<SlideTransition>(slideIn('400')).position.value,
- const Offset(-0.5, 0));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 500));
- expect(tester.widget<SlideTransition>(slideOut('0')).position.value,
- const Offset(-1.0, 0));
- expect(tester.widget<SlideTransition>(slideIn('400')).position.value,
- Offset.zero);
-
- await tester.pumpAndSettle();
- expect(begin, findsNothing);
- expect(end, findsOneWidget);
- });
- testWidgets('slot layout can tolerate rapid changes in breakpoints',
- (WidgetTester tester) async {
- await tester.pumpWidget(slot(300));
- expect(begin, findsOneWidget);
- expect(end, findsNothing);
-
- await tester.pumpWidget(slot(500));
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 100));
- expect(tester.widget<SlideTransition>(slideOut('0')).position.value,
- offsetMoreOrLessEquals(const Offset(-0.1, 0), epsilon: 0.05));
- expect(tester.widget<SlideTransition>(slideIn('400')).position.value,
- offsetMoreOrLessEquals(const Offset(-0.9, 0), epsilon: 0.05));
- await tester.pumpWidget(slot(300));
- await tester.pumpAndSettle();
- expect(begin, findsOneWidget);
- expect(end, findsNothing);
- }, skip: true);
-
- // This test reflects the behavior of the internal animations of both the body
- // and secondary body and also the navigational items. This is reflected in
- // the changes in LTRB offsets from all sides instead of just LR for the body
- // animations.
- testWidgets('adaptive layout handles internal animations correctly',
- (WidgetTester tester) async {
- final Finder b = find.byKey(const Key('b'));
- final Finder sb = find.byKey(const Key('sb'));
-
- await tester.pumpWidget(await layout(width: 400, tester: tester));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 100));
-
- expect(tester.getTopLeft(b), const Offset(1, 1));
- expect(tester.getBottomRight(b),
- offsetMoreOrLessEquals(const Offset(395.8, 799), epsilon: 1.0));
- expect(tester.getTopLeft(sb),
- offsetMoreOrLessEquals(const Offset(395.8, 1.0), epsilon: 1.0));
- expect(tester.getBottomRight(sb),
- offsetMoreOrLessEquals(const Offset(594.8, 799.0), epsilon: 1.0));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 400));
-
- expect(tester.getTopLeft(b), const Offset(5, 5));
- expect(tester.getBottomRight(b),
- offsetMoreOrLessEquals(const Offset(294.2, 795), epsilon: 1.0));
- expect(tester.getTopLeft(sb),
- offsetMoreOrLessEquals(const Offset(294.2, 5.0), epsilon: 1.0));
- expect(tester.getBottomRight(sb),
- offsetMoreOrLessEquals(const Offset(489.2, 795.0), epsilon: 1.0));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 400));
-
- expect(tester.getTopLeft(b), const Offset(9, 9));
- expect(tester.getBottomRight(b),
- offsetMoreOrLessEquals(const Offset(201.7, 791), epsilon: 1.0));
- expect(tester.getTopLeft(sb),
- offsetMoreOrLessEquals(const Offset(201.7, 9.0), epsilon: 1.0));
- expect(tester.getBottomRight(sb),
- offsetMoreOrLessEquals(const Offset(392.7, 791), epsilon: 1.0));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 100));
-
- expect(tester.getTopLeft(b), const Offset(10, 10));
- expect(tester.getBottomRight(b), const Offset(200, 790));
- expect(tester.getTopLeft(sb), const Offset(200, 10));
- expect(tester.getBottomRight(sb), const Offset(390, 790));
- }, skip: true);
-
- testWidgets('adaptive layout does not animate when animations off',
- (WidgetTester tester) async {
- final Finder b = find.byKey(const Key('b'));
- final Finder sb = find.byKey(const Key('sb'));
-
- await tester.pumpWidget(
- await layout(width: 400, tester: tester, animations: false));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 100));
-
- expect(tester.getTopLeft(b), const Offset(10, 10));
- expect(tester.getBottomRight(b), const Offset(200, 790));
- expect(tester.getTopLeft(sb), const Offset(200, 10));
- expect(tester.getBottomRight(sb), const Offset(390, 790));
- }, skip: true);
-}
-// Some animation related tests are temporarily disabled while waiting for the
-// roll to packages to be fixed.
-// TODO(serenabehera): remove the skip: true from the tests once they properly
-// pass.
diff --git a/packages/adaptive_scaffold/test/adaptive_scaffold_test.dart b/packages/adaptive_scaffold/test/adaptive_scaffold_test.dart
index 3171c0f..d09bc26 100644
--- a/packages/adaptive_scaffold/test/adaptive_scaffold_test.dart
+++ b/packages/adaptive_scaffold/test/adaptive_scaffold_test.dart
@@ -7,6 +7,121 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
+void main() {
+ testWidgets('adaptive scaffold lays out slots as expected',
+ (WidgetTester tester) async {
+ final Finder smallBody = find.byKey(const Key('smallBody'));
+ final Finder body = find.byKey(const Key('body'));
+ final Finder largeBody = find.byKey(const Key('largeBody'));
+ final Finder smallSBody = find.byKey(const Key('smallSBody'));
+ final Finder sBody = find.byKey(const Key('sBody'));
+ final Finder largeSBody = find.byKey(const Key('largeSBody'));
+ final Finder bottomNav = find.byKey(const Key('bottomNavigation'));
+ final Finder primaryNav = find.byKey(const Key('primaryNavigation'));
+ final Finder primaryNav1 = find.byKey(const Key('primaryNavigation1'));
+
+ await tester.pumpWidget(await scaffold(width: 300, tester: tester));
+ await tester.pumpAndSettle();
+
+ expect(smallBody, findsOneWidget);
+ expect(smallSBody, findsOneWidget);
+ expect(bottomNav, findsOneWidget);
+ expect(primaryNav, findsNothing);
+
+ expect(tester.getTopLeft(smallBody), Offset.zero);
+ expect(tester.getTopLeft(smallSBody), const Offset(150, 0));
+ expect(tester.getTopLeft(bottomNav), const Offset(0, 744));
+
+ await tester.pumpWidget(await scaffold(width: 900, tester: tester));
+ await tester.pumpAndSettle();
+
+ expect(smallBody, findsNothing);
+ expect(body, findsOneWidget);
+ expect(smallSBody, findsNothing);
+ expect(sBody, findsOneWidget);
+ expect(bottomNav, findsNothing);
+ expect(primaryNav, findsOneWidget);
+
+ expect(tester.getTopLeft(body), const Offset(88, 0));
+ expect(tester.getTopLeft(sBody), const Offset(450, 0));
+ expect(tester.getTopLeft(primaryNav), Offset.zero);
+ expect(tester.getBottomRight(primaryNav), const Offset(88, 800));
+
+ await tester.pumpWidget(await scaffold(width: 1100, tester: tester));
+ await tester.pumpAndSettle();
+
+ expect(body, findsNothing);
+ expect(largeBody, findsOneWidget);
+ expect(sBody, findsNothing);
+ expect(largeSBody, findsOneWidget);
+ expect(primaryNav, findsNothing);
+ expect(primaryNav1, findsOneWidget);
+
+ expect(tester.getTopLeft(largeBody), const Offset(208, 0));
+ expect(tester.getTopLeft(largeSBody), const Offset(550, 0));
+ expect(tester.getTopLeft(primaryNav1), Offset.zero);
+ expect(tester.getBottomRight(primaryNav1), const Offset(208, 800));
+ });
+
+ testWidgets('adaptive scaffold animations work correctly',
+ (WidgetTester tester) async {
+ final Finder b = find.byKey(const Key('body'));
+ final Finder sBody = find.byKey(const Key('sBody'));
+
+ await tester.pumpWidget(await scaffold(width: 400, tester: tester));
+ await tester.pumpWidget(await scaffold(width: 800, tester: tester));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 200));
+
+ expect(tester.getTopLeft(b), const Offset(17.6, 0));
+ expect(tester.getBottomRight(b),
+ offsetMoreOrLessEquals(const Offset(778.2, 755.2), epsilon: 1.0));
+ expect(tester.getTopLeft(sBody),
+ offsetMoreOrLessEquals(const Offset(778.2, 0), epsilon: 1.0));
+ expect(tester.getBottomRight(sBody),
+ offsetMoreOrLessEquals(const Offset(1178.2, 755.2), epsilon: 1.0));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 600));
+
+ expect(tester.getTopLeft(b), const Offset(70.4, 0));
+ expect(tester.getBottomRight(b),
+ offsetMoreOrLessEquals(const Offset(416.0, 788.8), epsilon: 1.0));
+ expect(tester.getTopLeft(sBody),
+ offsetMoreOrLessEquals(const Offset(416, 0), epsilon: 1.0));
+ expect(tester.getBottomRight(sBody),
+ offsetMoreOrLessEquals(const Offset(816, 788.8), epsilon: 1.0));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 200));
+
+ expect(tester.getTopLeft(b), const Offset(88.0, 0));
+ expect(tester.getBottomRight(b), const Offset(400, 800));
+ expect(tester.getTopLeft(sBody), const Offset(400, 0));
+ expect(tester.getBottomRight(sBody), const Offset(800, 800));
+ });
+
+ testWidgets('adaptive scaffold animations can be disabled',
+ (WidgetTester tester) async {
+ final Finder b = find.byKey(const Key('body'));
+ final Finder sBody = find.byKey(const Key('sBody'));
+
+ await tester.pumpWidget(
+ await scaffold(width: 400, tester: tester, animations: false));
+ await tester.pumpWidget(
+ await scaffold(width: 800, tester: tester, animations: false));
+
+ await tester.pump();
+ await tester.pump(const Duration(milliseconds: 200));
+
+ expect(tester.getTopLeft(b), const Offset(88.0, 0));
+ expect(tester.getBottomRight(b), const Offset(400, 800));
+ expect(tester.getTopLeft(sBody), const Offset(400, 0));
+ expect(tester.getBottomRight(sBody), const Offset(800, 800));
+ });
+}
+
class TestBreakpoint0 extends Breakpoint {
@override
bool isActive(BuildContext context) {
@@ -68,116 +183,3 @@
),
);
}
-
-void main() {
- testWidgets('adaptive scaffold lays out slots as expected',
- (WidgetTester tester) async {
- final Finder smallBody = find.byKey(const Key('smallBody'));
- final Finder body = find.byKey(const Key('body'));
- final Finder largeBody = find.byKey(const Key('largeBody'));
- final Finder smallSBody = find.byKey(const Key('smallSBody'));
- final Finder sBody = find.byKey(const Key('sBody'));
- final Finder largeSBody = find.byKey(const Key('largeSBody'));
- final Finder bnav = find.byKey(const Key('bottomNavigation'));
- final Finder pnav = find.byKey(const Key('primaryNavigation'));
- final Finder pnav1 = find.byKey(const Key('primaryNavigation1'));
-
- await tester.pumpWidget(await scaffold(width: 300, tester: tester));
- await tester.pumpAndSettle();
-
- expect(smallBody, findsOneWidget);
- expect(smallSBody, findsOneWidget);
- expect(bnav, findsOneWidget);
- expect(pnav, findsNothing);
-
- expect(tester.getTopLeft(smallBody), Offset.zero);
- expect(tester.getTopLeft(smallSBody), const Offset(150, 0));
- expect(tester.getTopLeft(bnav), const Offset(0, 744));
-
- await tester.pumpWidget(await scaffold(width: 900, tester: tester));
- await tester.pumpAndSettle();
-
- expect(smallBody, findsNothing);
- expect(body, findsOneWidget);
- expect(smallSBody, findsNothing);
- expect(sBody, findsOneWidget);
- expect(bnav, findsNothing);
- expect(pnav, findsOneWidget);
-
- expect(tester.getTopLeft(body), const Offset(88, 0));
- expect(tester.getTopLeft(sBody), const Offset(450, 0));
- expect(tester.getTopLeft(pnav), Offset.zero);
- expect(tester.getBottomRight(pnav), const Offset(88, 800));
-
- await tester.pumpWidget(await scaffold(width: 1100, tester: tester));
- await tester.pumpAndSettle();
-
- expect(body, findsNothing);
- expect(largeBody, findsOneWidget);
- expect(sBody, findsNothing);
- expect(largeSBody, findsOneWidget);
- expect(pnav, findsNothing);
- expect(pnav1, findsOneWidget);
-
- expect(tester.getTopLeft(largeBody), const Offset(208, 0));
- expect(tester.getTopLeft(largeSBody), const Offset(550, 0));
- expect(tester.getTopLeft(pnav1), Offset.zero);
- expect(tester.getBottomRight(pnav1), const Offset(208, 800));
- });
- testWidgets('adaptive scaffold animations work correctly',
- (WidgetTester tester) async {
- final Finder b = find.byKey(const Key('body'));
- final Finder sBody = find.byKey(const Key('sBody'));
-
- await tester.pumpWidget(await scaffold(width: 400, tester: tester));
- await tester.pumpWidget(await scaffold(width: 800, tester: tester));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 200));
-
- expect(tester.getTopLeft(b), const Offset(17.6, 0));
- expect(tester.getBottomRight(b),
- offsetMoreOrLessEquals(const Offset(778.2, 755.2), epsilon: 1.0));
- expect(tester.getTopLeft(sBody),
- offsetMoreOrLessEquals(const Offset(778.2, 0), epsilon: 1.0));
- expect(tester.getBottomRight(sBody),
- offsetMoreOrLessEquals(const Offset(1178.2, 755.2), epsilon: 1.0));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 600));
-
- expect(tester.getTopLeft(b), const Offset(70.4, 0));
- expect(tester.getBottomRight(b),
- offsetMoreOrLessEquals(const Offset(416.0, 788.8), epsilon: 1.0));
- expect(tester.getTopLeft(sBody),
- offsetMoreOrLessEquals(const Offset(416, 0), epsilon: 1.0));
- expect(tester.getBottomRight(sBody),
- offsetMoreOrLessEquals(const Offset(816, 788.8), epsilon: 1.0));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 200));
-
- expect(tester.getTopLeft(b), const Offset(88.0, 0));
- expect(tester.getBottomRight(b), const Offset(400, 800));
- expect(tester.getTopLeft(sBody), const Offset(400, 0));
- expect(tester.getBottomRight(sBody), const Offset(800, 800));
- });
- testWidgets('adaptive scaffold animations can be disabled',
- (WidgetTester tester) async {
- final Finder b = find.byKey(const Key('body'));
- final Finder sBody = find.byKey(const Key('sBody'));
-
- await tester.pumpWidget(
- await scaffold(width: 400, tester: tester, animations: false));
- await tester.pumpWidget(
- await scaffold(width: 800, tester: tester, animations: false));
-
- await tester.pump();
- await tester.pump(const Duration(milliseconds: 200));
-
- expect(tester.getTopLeft(b), const Offset(88.0, 0));
- expect(tester.getBottomRight(b), const Offset(400, 800));
- expect(tester.getTopLeft(sBody), const Offset(400, 0));
- expect(tester.getBottomRight(sBody), const Offset(800, 800));
- });
-}