From c9d982a3e7927c3eaccd47bd615920fc8527cf37 Mon Sep 17 00:00:00 2001 From: Brett Morgan Date: Thu, 22 Feb 2024 22:54:57 +1100 Subject: [PATCH 1/6] Update for Flutter 3.19 --- example/.metadata | 34 +-- example/android/app/build.gradle | 25 +- .../android/app/src/debug/AndroidManifest.xml | 6 +- .../android/app/src/main/AndroidManifest.xml | 16 +- .../com/example/example/MainActivity.kt | 3 +- .../app/src/main/res/values-night/styles.xml | 2 +- .../app/src/main/res/values/styles.xml | 2 +- .../app/src/profile/AndroidManifest.xml | 6 +- example/android/build.gradle | 15 +- example/android/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 3 +- example/android/settings.gradle | 31 ++- example/ios/.gitignore | 2 + example/ios/Flutter/AppFrameworkInfo.plist | 4 +- example/ios/Podfile | 5 +- example/ios/Runner.xcodeproj/project.pbxproj | 175 +++++++++++--- .../xcshareddata/xcschemes/Runner.xcscheme | 21 +- .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 564 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1283 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1588 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 1025 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1716 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 1920 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1283 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 1895 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 2665 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 2665 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 3831 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 1888 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 3294 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 3612 -> 1418 bytes example/ios/Runner/Info.plist | 8 +- example/lib/main.dart | 2 +- example/lib/mock.dart | 2 +- example/lib/ssh.dart | 5 +- example/lib/suggestion.dart | 4 +- example/lib/zmodem.dart | 2 +- example/linux/CMakeLists.txt | 64 ++++- example/linux/flutter/CMakeLists.txt | 4 +- example/linux/my_application.cc | 92 ++++++- example/macos/Podfile | 3 + example/macos/Podfile.lock | 4 +- .../macos/Runner.xcodeproj/project.pbxproj | 226 +++++++++++++++--- .../xcshareddata/xcschemes/Runner.xcscheme | 13 +- example/macos/Runner/Configs/AppInfo.xcconfig | 2 +- example/macos/Runner/MainFlutterWindow.swift | 2 +- example/macos/Runner/Release.entitlements | 5 +- example/pubspec.lock | 174 +++++++++----- example/pubspec.yaml | 6 +- example/web/index.html | 44 +++- example/web/manifest.json | 12 + example/windows/CMakeLists.txt | 29 ++- example/windows/flutter/CMakeLists.txt | 8 +- example/windows/runner/CMakeLists.txt | 23 ++ example/windows/runner/Runner.rc | 14 +- example/windows/runner/flutter_window.cpp | 10 + example/windows/runner/main.cpp | 2 +- example/windows/runner/runner.exe.manifest | 2 +- example/windows/runner/utils.cpp | 13 +- example/windows/runner/win32_window.cpp | 55 ++++- example/windows/runner/win32_window.h | 20 +- lib/src/core/buffer/range_block.dart | 2 +- lib/src/core/buffer/range_line.dart | 2 +- lib/src/terminal_view.dart | 42 ++-- lib/src/ui/custom_text_edit.dart | 14 +- lib/src/ui/keyboard_listener.dart | 30 +-- lib/src/ui/keyboard_visibility.dart | 4 +- lib/src/ui/painter.dart | 21 +- lib/src/ui/paragraph_cache.dart | 4 +- lib/src/ui/render.dart | 14 +- lib/src/utils/debugger_view.dart | 7 +- lib/zmodem.dart | 2 +- pubspec.lock | 198 ++++++++------- pubspec.yaml | 2 +- test/src/terminal_view_test.dart | 14 +- 75 files changed, 1104 insertions(+), 454 deletions(-) diff --git a/example/.metadata b/example/.metadata index e94891d5..8629a4e1 100644 --- a/example/.metadata +++ b/example/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - channel: stable + revision: "abb292a07e20d696c4568099f918f6c5f330e6b0" + channel: "stable" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 - platform: android - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 - platform: ios - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 - platform: linux - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 - platform: macos - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 - platform: web - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 - platform: windows - create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 - base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 + base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 # User provided section diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 5fe3c929..e28b4e76 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -1,3 +1,9 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -21,12 +22,10 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - android { - compileSdkVersion flutter.compileSdkVersion + namespace "com.example.example" + compileSdk flutter.compileSdkVersion + ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -44,6 +43,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() @@ -63,6 +64,4 @@ flutter { source '../..' } -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} +dependencies {} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml index c208884f..399f6981 100644 --- a/example/android/app/src/debug/AndroidManifest.xml +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,6 @@ - - diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 3f41384d..aff7dec7 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - - + @@ -31,4 +30,15 @@ android:name="flutterEmbedding" android:value="2" /> + + + + + + + diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt index e793a000..70f8f08f 100644 --- a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt +++ b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -2,5 +2,4 @@ package com.example.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() { -} +class MainActivity: FlutterActivity() diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml index 3db14bb5..06952be7 100644 --- a/example/android/app/src/main/res/values-night/styles.xml +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -3,7 +3,7 @@ diff --git a/example/android/build.gradle b/example/android/build.gradle index 4256f917..bc157bd1 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,16 +1,3 @@ -buildscript { - ext.kotlin_version = '1.6.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - allprojects { repositories { google() @@ -26,6 +13,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 94adc3a3..598d13fe 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx4G android.useAndroidX=true android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index bc6a58af..e1ca574e 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/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.6.3-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 44e62bcf..1d6d19b7 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,11 +1,26 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -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" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/example/ios/.gitignore b/example/ios/.gitignore index e96ef602..7a7f9873 100644 --- a/example/ios/.gitignore +++ b/example/ios/.gitignore @@ -1,3 +1,4 @@ +**/dgph *.mode1v3 *.mode2v3 *.moved-aside @@ -18,6 +19,7 @@ Flutter/App.framework Flutter/Flutter.framework Flutter/Flutter.podspec Flutter/Generated.xcconfig +Flutter/ephemeral/ Flutter/app.flx Flutter/app.zip Flutter/flutter_assets/ diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index f2872cf4..7c569640 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + en CFBundleExecutable App CFBundleIdentifier @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 12.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c90..d97f17e2 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -32,6 +32,9 @@ target 'Runner' do use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end end post_install do |installer| diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 6e267c40..beb4e92f 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,11 +3,12 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -15,6 +16,16 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -31,6 +42,8 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -55,6 +68,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +93,7 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, ); sourceTree = ""; }; @@ -79,6 +101,7 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -101,6 +124,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; @@ -127,9 +167,14 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -150,11 +195,19 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -171,10 +224,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -185,6 +240,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -200,6 +256,14 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -211,6 +275,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -235,6 +307,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -264,6 +337,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -272,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -288,21 +362,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = BA88US33G6; + DEVELOPMENT_TEAM = TC87DMJLQP; 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 = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.example.example; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -311,10 +377,58 @@ }; name = Profile; }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -344,6 +458,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -358,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -370,6 +485,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -399,6 +515,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -407,7 +524,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -425,21 +542,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = BA88US33G6; + DEVELOPMENT_TEAM = TC87DMJLQP; 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 = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.example.example; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -456,21 +565,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = BA88US33G6; + DEVELOPMENT_TEAM = TC87DMJLQP; 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 = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.example.example; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -482,6 +583,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3db53b6e..8e3ca5df 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ - - - - + + + + + + - - Gw7hsN~k)CYt4dQDFxbs5*_&e@Hj)wtt(&JE<3Eq*D z;_gQLvqXoKv=I*gWqM9C(Tvu0>=?hTbOp9!6k6AF;>f6|S5%jGEE}TA9h)e`Yuiu8 d7)l?o1NFcJg%EAfM$P~L002ovPDHLkV1g^Dnv?(l delta 550 zcmV+>0@?ki0<;8>8Gi-<0051N9Sr~g00DDSM?wIu&K&6g00HhvL_t(I5v`QFOB_)Y z#?QI;j_a;jjf#Z$YJ7mH(xecJU?W)A`9CN~KrBV85C}GDQ=|;GDFPNjtWty!L{u=? zh>8yo%^GE+J9o~_IZFoiamQVQXP7%LzTbT3F@uf+9x&7cvVV%GdjTaC;zf>@mq<=3 z!c<%*UT)@yJ|0BK6~d4Jx-*KV`ZQ(@VyUPupum=XhInNG#Z_k-X|hK{B}~9IfiWx} zLD5QY6Vm)p0NrWymdkrHPN5Vgwd>5>4HI1=@PA+e^rq~CEj|n2X`??)0mUI*D{KBn zjv{V=y5X9|X@3grkpcXC6oou4ML~ezCc2EtnsQTB4tWNg?4bkf;hG7IMfhgNI(FV5 zGs4|*GyMTIY0$B=_*mso9+>eB z?J{?+FLkYu+4_Uk`r_>LHF~flZm0oBf#vr8%vJ>#p~!KNvqGG3)|f1T_)ydeh8$vDceZ>oNbH^|*hJ*t?Yc*1`WB&W>VYVEzu) zq#7;;VjO)t*nbgf(!`OXJBr45rP>>AQr$6c7slJWvbpNW@KTwna6d?PP>hvXCcp=4 zF;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f<+$JJpcdz delta 1274 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 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde12118dda48d71e01fcb589a74d069c5d7cb5..4cd7b0099ca80c806f8fe495613e8d6c69460d76 100644 GIT binary patch delta 266 zcmV+l0rmcY2$}+r8Gi!+003c4mpuRg09{Z_R7L;)|5U~JDYo_jSDX9(|7FYh`2GLd z^Zv2r{H^2sT*&w!Y^SB+`<>qVZqE6)=lqo0`vF#&*75!I`TIh@_d&k*HoEtQyV-iD z%Xz2D9EQRbeYh5Nr~y=#0ZD;^+vz0$004MNL_t(2&&|%+4u6C&2tZM$Wf&dzefR%A z(^3-?6X>hnCz2Ba@RH&`m!pgy?n@#@AuLYB&}Q)FGY`?vcft0!vht0Z@M&ZeNCWXh75gzRTXR8EE3oN&6 Q00000NkvXXt^-0~g5kS`djJ3c delta 1014 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 Zxpx7IC@PekH?;r&002ovPDHLkV1i)CYaajr delta 1916 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 delta 1274 zcmV@pi1MCNO0zH7s z{8#}P0)7Ba8DqYf&QgSne>X__O83t$NZM4&R0{XJq|x}oAU?tcfC@|eNz$04T}34& z8DJf78R&>*Zz`k$q{`#gfGHnx7nlH^G{y`jfER)1<_fNi<9aM%_zrm1C`yPkKma(+ ztQ;y*CR2bbBYz>zG*SVsfpkGU(q>uHZf3iogk_%#9E|5SWeHrmAo>P;ejX7mwq#*} zW25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+X$F_KMdb6sRz!~7K zkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&IDi_4_D!s#MVXp|-XhH;H z#&@_;oApJVd}}5O@b=X_gJboD^-fM@6|#V@sA%X)Rlkd}3MLH0dGXGG&-HX|aD~|M zC)W#H7=H?AbtdaV#dGpubj_O^J-SlWpVNv-5(;wR%mvE9`Qaqo>03b&##eNNf=m#B z9@^lsd8tJ;BvI86kNV zc~0CY(7V{s+h%cWG|y=gt|q`z$l<(@qU=i?9q#uz`G?PgDMK!VMGidHZt*N+1L0ZI zFkH=mFtywc6rJ}C_?)=m)18V!ZQ`*-j(D`gCFK|nt#{bk*%%zuQ7o7kvJgA^=(^7b zzkm5GZ;jxRn{Wup8IOUx8D4uh&(=Ox-7$a;U><*5L^!% zxRlw)vAbh;sdlR||&e}8_8%)c2Fwy=F& zH|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}Jb#viX>Oi;kBKp1x_fc0#UIbIeSJ^EkWFox zijdim{ojmn@#7EC*aY;fC0W*WN+DmQtE06pNK3SfZ^#@2K`6RgEuU_KwJTQ>E?Yar zc_9e#I$F8%>kuy-JI6ocSsYvQGbsxUCx04(w1z-pMRz9`kH5smmF@WHEG?dcYkv){ zV?kn3XB$_3zr*h1Uow)(<5)w5;3Wh1jHI)`ZlXp&!yEV{Y_~@;?CLwq;4eeaGOe6( zEsSSbwSGD0-`dUUl014$1_O8Gi!+006nq0-pc?0H{z*R7L;)|5U~JDYo_jSDXF*|5nEMy6F5^ z$M}8I`uzU?*Yf=uXr;5|{0m;6_Wb|A>ik^D_|)+I$?g3CSDK^3+eX0mD!2CP`2NN0 z{dLg!a?km&%iyTt`yiax0acdp`~T(l{$a`ZF1YpsRg(cvjDG_-U$Er-fz#Bw>2W$eUI#iU z)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G!hkE!s;%oku3;IwG3U^2k zw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn_j%}l|2+O?a>_7qq7W zmx(qtA2nV^tZlLpy_#$U%ZNx5;$`0L&dZ!@e7rFXPGAOup%q`|03hpdtXsPP0000< KMNUMnLSTZ1N;Pr- delta 1891 zcmV-p2b}oI1m_Nr8Gi-<0052=@~r>>2QEoOK~#9!?VW3E6jc<*XLh$yKNt;)Mial3 z7z%<>zxaV5DhMs*(b6YIW1=KP6Jj(m21QYbiJ}su&;o5EN=$%gptMj6p|(7#AOTUJ zlt8fsX(iGq?ZQ50=XmbU+~w|cmz~|6$KBbz$-g^IcV>Hk`+q<8%-p?uMi3G-0B~!5 ze-yPCwFPw?HGmpMc~K)7BCq;C528+>zC*o^8h^XKC)IFgkv#xzm!ewK7j|kRa9dFo zC>MoDSR@P2#cWSU{i1oH5K2-Xb3jRz>|h7VOh0K` zhq^--L3H}A0r)nr z;Tr|-kPjB1s=ItpnS`oT%|U=a4oK-ZFIE^YBLH{u2#~@%%D^K)$`9*Tg(~9M-B+Zj z;~H?4LVsEt0eFtN4&>H(DZ@KpI6RhBKLL21CxC`J&m4Gc^9wwMZU#7SR1+KtuhSZM z+yLY}Vekzw6T_ApfEkuB_yU;e&a)L@rX~z70A_N+upOXN!qygmPDmKG0d%7CECcAI zgkd>ArzH$a0XjKsO$X@IgkcH5Y;m3`0G*yNOn(KK4GF_EfL4aB5i1j9o&Z{vFk~k> z&?@K2jQcJO%W!cddG(_DyfSoO55bUMHtbDF8DPkwF^~Ql#Eq4w15k{h%ML5Ar&pzi zl-D7v8kQXQ!&RRgKCW#5DZB$$6?mjWm50rRw*ukK>P-GkA|k69h{NARc>e}uLx+U4 z0DqE>7pa}9Fez+Vc-3jb`%i^uulglFoMzAVR|2%rf= zf#;74FXF^Ku_4+G&-4$KVy%YP>%2rxu2VG_cdm?XRjEhF&wPXJ># z_Q2+jGs=l~Fyx#MmGn+PZ0`@kBfGp|fO;Vov<$;z`(+sSZ7;Y=zXaF(8rb@CuQDV^ zq3i(2LfqO%AS!Ss>V%j7%>{6mtbYQrtQK5V4InPq0NZSaXv+f2U=&2}Z6OvkBfNHi z{LSaVJ!d5dC2K*ft_L^DRk;boQhOoVw!~Kt#0b2vd%!(&DF|~u1F@nG#LA5zR&7Fv z4GKgXooMSKb1g)6Obo-rgpuEP20T;W0Aa>55KC4gtQrKkAq-Hgs@FigV1GG8+rQ=z z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRet3L_uNyQ*c zE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=kyx=~RKa4{iT zm{_>_vSCm?$Ej=i6@=m%@PE9t1zZaoM}@2|h!#1K02~31S_I<0ZV=|K0}n!RRX6Ac zXmMf*5P-dLW}WPVsCKq)-x(0*txpZ2xrv3cxJ%l=7lpoNCyG< zK92ySAcmb-3m&}s@VwXv9(0#p<>B-5$bMxT;rk;OmENa6eM4D&LVo~01soUL39?R{ zyFLt3m|v?rCK7#KNu9E9Q4KV-pEUv^{rrClE&X&9I4-e7%pu_31#zGTOfC=ab%w20R*zBP+uT#l2{a~~~0wuG%6 zco*tVxK&e>%SJj*K!2tq*_h&ES5S9@TKb8WzpK;`&b9dNdxh4S)z%Q)o`aYWUh}9L z(`p!#WO5IxI|nf?yz{90R93Ed6@2qim*}Zjj$H&Esd`?JsFJUnDfiAgF_eYiWR3GC z>M9SHDylEWrA(%mfm~;u7OU9!Wz^!7Z%jZF zi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i0WYBP d*#0Ks^FNSabJA*5${_#%002ovPDHLkV1gB0Vle;! diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b8609df07bf62e5100a53a01510388bd2b22..0ec303439225b78712f49115768196d8d76f6790 100644 GIT binary patch delta 850 zcmV-Y1Fih&6y64q8Gi!+000iU#^3+|0OwFlR7L;)|5U~J09TtSw)Xt~|5(QO`~Ck( z!T0|D|3<*~RmJ%E{r+;#`2ba!klFf7!uJMSo%Q?vP{jByxcAZE>;OrUCbaZYjJo^$ z{nGILmD~Da$@upC{`C6(Ey4dPw)Pyc^>5DkHoEo!QcuK-Jwl-l}t(fQKv z{dds$V#@dygS`PvhX6is7Z+@*x-d;$ zb=6f@U3Jw}_s+W3%*+b9H_vS)-R#9?zrXogeLVI2We2RFTTAL}&3C8PS~<5D&v@UI z+`s*$wqQ=yd$laNUY-|ovcS9~n_90tFUdl#qq0tEUXle|k{Op|DHpSrbxEeZ5~$>o%>OSe z^=41qvh3LlC2xXzu+-2eQoqs1^L>7ylB$bCP);(%(xYZL1 cY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f@rA97ytkO literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b8609df07bf62e5100a53a01510388bd2b22..0ec303439225b78712f49115768196d8d76f6790 100644 GIT binary patch delta 850 zcmV-Y1Fih&6y64q8Gi!+000iU#^3+|0OwFlR7L;)|5U~J09TtSw)Xt~|5(QO`~Ck( z!T0|D|3<*~RmJ%E{r+;#`2ba!klFf7!uJMSo%Q?vP{jByxcAZE>;OrUCbaZYjJo^$ z{nGILmD~Da$@upC{`C6(Ey4dPw)Pyc^>5DkHoEo!QcuK-Jwl-l}t(fQKv z{dds$V#@dygS`PvhX6is7Z+@*x-d;$ zb=6f@U3Jw}_s+W3%*+b9H_vS)-R#9?zrXogeLVI2We2RFTTAL}&3C8PS~<5D&v@UI z+`s*$wqQ=yd$laNUY-|ovcS9~n_90tFUdl#qq0tEUXle|k{Op|DHpSrbxEeZ5~$>o%>OSe z^=41qvh3LlC2xXzu+-2eQoqs1^L>7ylB$bCP);(%(xYZL1 cY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f@rA97ytkO literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d164a5a98e212cca15ea7bf2ab5de5108680..e9f5fea27c705180eb716271f41b582e76dcbd90 100644 GIT binary patch delta 1668 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 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d39da7941ef3f6dcb7f06a192d8dcb308d..84ac32ae7d989f82d5e46a60405adcc8279e8001 100644 GIT binary patch delta 749 zcmVg;Ps8|O$@u8^{Z_{KM!@$5TAfS6_e#O{MZfpz`2O`0$7~@NRr(1{THzH08y3x{{PYM{eL;T_A9^tcF_4Sxb`8l z_9V3RD6;a(-0A^Pjsi!1?)d#Ap4Tk3^CP0(07;VpJ7@tgQ}z4)*zx@&yZwC9`DV-b z0ZobH_5IB4{KxD3;p_6%|f=bdFhu+F!zMZ2UFj;GUKX7tI;hv3{q~!*pMj75WP_c}> z6)IWvg5_yyg<9Op()eD1hWC19M@?_9_MHec{Z8n3FMs~w_u?Av_yNBmRxVYrpi(M% zFMP21g+hmocQp3ay*Su=qM6He)*HaaTg$E^sym`(t%s3A)x!M+vfjXUBEpK6X9%iU zU!u9jj3(-$dM~sJ%Liy#?|+!6IY#MTau#O6vVj`yh_7%Ni!?!VS+MPTO(_fG+1<#p zqu;A#i+_(N%CmVnYvb>#nA{>Q%3E`Ds7<~jZMywn@h2t>G-LrYy7?Dj{aZqhQd6tzX%(Trn+ z)HNF}%-F{rr=m*0{=a;s#YDL00000NkvXXu0mjfaGjYE delta 1884 zcmV-i2c!7<1>g>l8Gi-<0076AQ7Zrd2Pa8HK~#9!?VNjT6h$1z_m0EFf5bmb1dTDK zp;kdKV1h(V(8Sc1M<37!RE>znAk{x4#zX@eOeE1j3~!+nB5IL z<xS}u?#DBMB>w^b($1Z)`9G?eP95EKi& z$eOy@K%h;ryrR3la%;>|o*>CgB(s>dDcNOXg}CK9SPmD?Uu$P4(=PGA0ShFasNfcIHTL?9WjB9#(2xSLC z`0%$#9DW9F;B4mbU{BlaYx!SjF!QSeF~(msQRxwboh5B_O$BWOQja)GboJz$&!?mgB&3$ytsA zvns&b3Cl5Hx#%p%faR*Q906u&fbXy$maV`n?S>A)vJIH!F-vxCrY+rq5_JA(GcOgu7(Ky4X3ATR9z8*%k&<5qYeV&4Y`~}XYmK(j{)!g8d2UgHXIINM!Rvn zKtEq~Foe0s!U{kux~F6Y7Sp+2f|*Cc${S{@oh8D0=XhB8Ec-w9CflfL+te4ium2cU zoPTCj_m<3d#gjK=<*8R`HP^C$lOPM5d~UhKhRRmvv{LI za^|oavk1$QiEApSrP@~Jjbg`<*dW4TO@DPEEX$Tg$xh?Y>Qd}y@kaH~IT8!lLpS^J zR7(&wZSI6+>Eb)tX>9Z?GX#q$u z4I>7e#b7ojyJ1grOh!^}s8S#ubi^Jkd1?UK)3mp6rI^_zxRY zrx6_QmhoWoDR`fp4R7gu6@OBFGu7IDVR6~nJsB{^f5jHn<{WJ&&f^X?3f8TIk3#U& zu1*Q-e@;snJxNx8-PBnpI|uFTKN!+Lp;fPfZ+eqqU^Y1|#DJY~126?zOx-+d>%4*? z&o`TbrXSNXZW^!P0t2>@$6&aiBtUDh2wLXLD9&a(1J=k_FK|iGbAQ@x4Qmx}Ms+*; zze&q6bH(=wYuXHfz0H6<05!LkE4rl~v^!bj=^9d+vI5fN<;GP>*Pas=q2l9RxDkk` zPRk&EQI+t_0$Y%nKE)Ma)W?jaA@4Z{h zTk*7;;#lG?hvTN_On=Jaxp%bdE;mDq(q#dgdYF|-?wrMeI4h`$idZ6^VyXZVlaCd0 z;i)OYR3npf@9>00Gqn##Zb4HRurgaWFCzL9u6@J@sse>Z1XznxWvSy%Td32I3!#YN zXt9v0)RQtDDZRd?#WY?~KF7A0UcR{jt9 W+;fr}hV%pg0000&=UXv0SHh`R7L;)|5U~JDYo_jSDRDC`1<|-SjPDL z{{Q{{{{H{}09Kk-#rR9Y_viNgVafPO!S|ls`uzR=MZfp^{QU=8od8La1X`Tr_Wmff z_5e$ivgQ1@=KMy$_g9a+`TPAle6cOJ_Fc#L7qIpvwDkd1mw$fK`6IOUD75rX!}mad zv(fMTE4=(Nx%L54lL1hVF1YpqNrC`FddBPg#_Ietx%Lrkq5wX00X1L{S%Cm9QY*av z#_Rh5PKy9KYTWbvz3BX9%J>0Hi1+#X{rLA{m%$Kamk?i!03AC38#Yrxs)5QTeTVRiEmz~MKK1WAjCw(c-JK6eox;2O)?`?TG`AHia671e^vgmp!llK zp|=5sVHk#C7=~epA~VAf-~%aPC=%Qw01h8mnSZ|p?tc*y?iZ$PR7_ceEIapF3KB14K0Pog?7wtd+^xgUCa_GVmlD z<^nU>AU_Yn-JU?NFdu|wf^bTCNf-wSBYVZltDdvGBln-YrbeGvJ!|s{#`gjN@yAMb zM6cjFz0eFECCsc|_8hTa3*9-JQGehksdoVP^K4m?&wpA~+|b%{EP5D-+7h)6CE; z*{>BP=GRR3Ea}xyV*bqry{l^J=0#DaC4ej;1qs8_by?H6Tr@7hl>UKNZt)^B&yl;)&oqzLg zcfZxpE?3k%_iTOVywh%`XVN-E#COl+($9{v(pqSQcrz=)>G!!3HeNxbXGM@})1|9g zG4*@(OBaMvY0P0_TfMFPh fVHk#CZX3S=^^2mI>Ux-D00000NkvXXu0mjfzK(<8 literal 3294 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 cX)(b1KSk$MOV07*qoM6N<$f&{Qds= z{r_0T`1}6fwc-8!#-TGX}_?g)CZq4{k!uZ_g@DrQdoW0kI zu+W69&uN^)W`CK&06mMNcYMVF00dG=L_t(|+U?wHQxh>12H+Dm+1+fh+IF>G0SjJM zkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJTkdTm&kdTm&kdTm&kdP`e zsgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>VI$fQI%^ugM`#6By?GeadWcu z0gy9!D`m!H>Bd!JW(@avE8`|5XX(0PN}!8K>`dkavs;rHL+wy96QGNT=S@#7%xtlm zIW!++@*2zm-Py#Zr`DzqsLm!b{iskFNULSqE9A>SqHem>o31A%XL>S_5?=;V_i_y+ z(xxXhnt#r-l1Y8_*h`r?8Tr|)(RAiO)4jQR`13X0mx07C&p@KBP_2s``KEhv^|*8c z$$_T(v6^1Ig=#R}sE{vjA?ErGDZGUsyoJuWdJMc7Nb1^KF)-u<7q zPy$=;)0>vuWuK2hQhswLf!9yg`88u&eBbR8uhod?Nw09AXH}-#qOLLxeT2%C;R)QQ$Za#qp~cM&YVmS4i-*Fpd!cC zBXc?(4wcg>sHmXGd^VdE<5QX{Kyz$;$sCPl(_*-P2Iw?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF34$0Z;QO!J zOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUCUoZo%k(yku QW&i*H07*qoM6N<$g47z!?*IS* literal 3612 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 iW8 CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -39,7 +41,9 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UIViewControllerBasedStatusBarAppearance - + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/main.dart b/example/lib/main.dart index 5f8e5c97..586f829e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -34,7 +34,7 @@ class MyApp extends StatelessWidget { } class Home extends StatefulWidget { - Home({Key? key}) : super(key: key); + Home({super.key}); @override // ignore: library_private_types_in_public_api diff --git a/example/lib/mock.dart b/example/lib/mock.dart index 3ca3ad81..8bda3bd0 100644 --- a/example/lib/mock.dart +++ b/example/lib/mock.dart @@ -27,7 +27,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - MyHomePage({Key? key}) : super(key: key); + MyHomePage({super.key}); @override // ignore: library_private_types_in_public_api diff --git a/example/lib/ssh.dart b/example/lib/ssh.dart index 22879167..11aaf7ab 100644 --- a/example/lib/ssh.dart +++ b/example/lib/ssh.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:typed_data'; import 'package:dartssh2/dartssh2.dart'; import 'package:example/src/virtual_keyboard.dart'; @@ -27,7 +26,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - MyHomePage({Key? key}) : super(key: key); + MyHomePage({super.key}); @override // ignore: library_private_types_in_public_api @@ -77,7 +76,7 @@ class _MyHomePageState extends State { }; terminal.onOutput = (data) { - session.write(utf8.encode(data) as Uint8List); + session.write(utf8.encode(data)); }; session.stdout diff --git a/example/lib/suggestion.dart b/example/lib/suggestion.dart index 584b9447..1cfd1fa6 100644 --- a/example/lib/suggestion.dart +++ b/example/lib/suggestion.dart @@ -40,7 +40,7 @@ class MyApp extends StatelessWidget { } class Home extends StatefulWidget { - Home({Key? key}) : super(key: key); + Home({super.key}); @override // ignore: library_private_types_in_public_api @@ -266,7 +266,7 @@ class _HomeState extends State { autofocus: true, backgroundOpacity: 0.7, onKey: (node, event) { - if (event is! RawKeyDownEvent) { + if (event is! KeyDownEvent) { return KeyEventResult.ignored; } diff --git a/example/lib/zmodem.dart b/example/lib/zmodem.dart index 4e792ff3..7caeacca 100644 --- a/example/lib/zmodem.dart +++ b/example/lib/zmodem.dart @@ -28,7 +28,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - MyHomePage({Key? key}) : super(key: key); + MyHomePage({super.key}); @override // ignore: library_private_types_in_public_api diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt index 0236a880..9cb0d1dd 100644 --- a/example/linux/CMakeLists.txt +++ b/example/linux/CMakeLists.txt @@ -1,13 +1,32 @@ +# 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 "com.example.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") -# Configure build options. +# 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) @@ -16,6 +35,10 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 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) @@ -23,26 +46,47 @@ function(APPLY_STANDARD_SETTINGS TARGET) target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") endfunction() -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") - # 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) -# Application build +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) @@ -73,11 +117,17 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR} install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -endif() +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. diff --git a/example/linux/flutter/CMakeLists.txt b/example/linux/flutter/CMakeLists.txt index 94f43ff7..d5bd0164 100644 --- a/example/linux/flutter/CMakeLists.txt +++ b/example/linux/flutter/CMakeLists.txt @@ -1,3 +1,4 @@ +# 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") @@ -78,7 +79,8 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - linux-x64 ${CMAKE_BUILD_TYPE} + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc index c2357f17..c0530d42 100644 --- a/example/linux/my_application.cc +++ b/example/linux/my_application.cc @@ -1,28 +1,57 @@ #include "my_application.h" #include +#ifdef GDK_WINDOWING_X11 +#include +#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))); - 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)); + + // 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)); @@ -33,12 +62,63 @@ static void my_application_activate(GApplication* application) { 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 GApplication::startup. +static void my_application_startup(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// 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_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + 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(), nullptr)); + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); } diff --git a/example/macos/Podfile b/example/macos/Podfile index 049abe29..c795730d 100644 --- a/example/macos/Podfile +++ b/example/macos/Podfile @@ -31,6 +31,9 @@ target 'Runner' do use_modular_headers! flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end end post_install do |installer| diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index dafff0ca..6d2dbc33 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -17,6 +17,6 @@ SPEC CHECKSUMS: flutter_pty: 41b6f848ade294be726a6b94cdd4a67c3bc52f59 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 -PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 +PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 -COCOAPODS: 1.11.3 +COCOAPODS: 1.15.0 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 41f8428b..28438dca 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,15 +21,24 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 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 */; }; - A63EDDC4424F7733E4F1089E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BFF3568FCDF6A623BAE2DF2 /* Pods_Runner.framework */; }; + 46ACFF2CEAECB3D93F67B110 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA738BE89B1C6EA42CB3992B /* Pods_Runner.framework */; }; + D0A1FD10376EC2F0535AE888 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D57CFDCD10E714CD4C1D911 /* Pods_RunnerTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 33CC10E52044A3C60003C045 /* Project object */; @@ -53,7 +62,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 327BAFDBBDAC4BC4B3F62492 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 03B174ABD6DD291DF8A4E0CD /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -68,25 +79,59 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 3BFF3568FCDF6A623BAE2DF2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 33EB9BC9837E04A25764711F /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 538E36A797711121F1B742FB /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 5B21B17BA6645796A0F64779 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 831993642494A8EE586D7606 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 7D57CFDCD10E714CD4C1D911 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - 98BB7BB02D086BDD59672A1C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + C85CB6616050D0F73AACA3AC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + E65F58E1DED7B3DDBB3A925D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + FA738BE89B1C6EA42CB3992B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D0A1FD10376EC2F0535AE888 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 33CC10EA2044A3C60003C045 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A63EDDC4424F7733E4F1089E /* Pods_Runner.framework in Frameworks */, + 46ACFF2CEAECB3D93F67B110 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3065DD8A94270A9F820AEBCC /* Pods */ = { + isa = PBXGroup; + children = ( + 03B174ABD6DD291DF8A4E0CD /* Pods-Runner.debug.xcconfig */, + C85CB6616050D0F73AACA3AC /* Pods-Runner.release.xcconfig */, + 5B21B17BA6645796A0F64779 /* Pods-Runner.profile.xcconfig */, + 538E36A797711121F1B742FB /* Pods-RunnerTests.debug.xcconfig */, + 33EB9BC9837E04A25764711F /* Pods-RunnerTests.release.xcconfig */, + E65F58E1DED7B3DDBB3A925D /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -103,9 +148,10 @@ children = ( 33FAB671232836740065AC1E /* Runner */, 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, - 5D0EEDE84B575FFD99D06C18 /* Pods */, + 3065DD8A94270A9F820AEBCC /* Pods */, ); sourceTree = ""; }; @@ -113,6 +159,7 @@ isa = PBXGroup; children = ( 33CC10ED2044A3C60003C045 /* example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -152,21 +199,11 @@ path = Runner; sourceTree = ""; }; - 5D0EEDE84B575FFD99D06C18 /* Pods */ = { - isa = PBXGroup; - children = ( - 327BAFDBBDAC4BC4B3F62492 /* Pods-Runner.debug.xcconfig */, - 98BB7BB02D086BDD59672A1C /* Pods-Runner.release.xcconfig */, - 831993642494A8EE586D7606 /* Pods-Runner.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( - 3BFF3568FCDF6A623BAE2DF2 /* Pods_Runner.framework */, + FA738BE89B1C6EA42CB3992B /* Pods_Runner.framework */, + 7D57CFDCD10E714CD4C1D911 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -174,17 +211,36 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + E95771784C0FB2DFBD907097 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 33CC10EC2044A3C60003C045 /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 8E54A65EC2374C96D72E72EB /* [CP] Check Pods Manifest.lock */, + 84DDCA2D784CB1382B106832 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - 8AEB9E182B43A490F7FF61EE /* [CP] Embed Pods Frameworks */, + 1291B2833C2CFBBE59E0ABC2 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -202,10 +258,15 @@ 33CC10E52044A3C60003C045 /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; @@ -236,12 +297,20 @@ projectRoot = ""; targets = ( 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, 33CC111A2044C6BA0003C045 /* Flutter Assemble */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 33CC10EB2044A3C60003C045 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -254,6 +323,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 1291B2833C2CFBBE59E0ABC2 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -292,24 +378,29 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 8AEB9E182B43A490F7FF61EE /* [CP] Embed Pods Frameworks */ = { + 84DDCA2D784CB1382B106832 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 8E54A65EC2374C96D72E72EB /* [CP] Check Pods Manifest.lock */ = { + E95771784C0FB2DFBD907097 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -324,7 +415,7 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -334,6 +425,14 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 33CC10E92044A3C60003C045 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -347,6 +446,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; @@ -367,11 +471,57 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 538E36A797711121F1B742FB /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33EB9BC9837E04A25764711F /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E65F58E1DED7B3DDBB3A925D /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; + }; + name = Profile; + }; 338D0CE9231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -395,9 +545,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -445,6 +597,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -468,9 +621,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -498,6 +653,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -521,9 +677,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -597,6 +755,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 83d88728..15368ecc 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + - + + com.apple.security.app-sandbox + + diff --git a/example/pubspec.lock b/example/pubspec.lock index ce1a5872..25262108 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: d976d24314f193899a3079b14fe336215a63a3b1e1c3743eabba8f83e049e9a9 + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a url: "https://pub.dev" source: hosted - version: "49.0.0" + version: "61.0.0" after_layout: dependency: "direct main" description: @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: analyzer - sha256: "40ba2c6d2ab41a66476f8f1f099da6be0795c1b47221f5e2c5f8ad6048cdffae" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.13.0" analyzer_plugin: dependency: transitive description: @@ -37,26 +37,26 @@ packages: dependency: transitive description: name: ansicolor - sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" + sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" args: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + sha256: c9c85fedbe2188b95133cbe960e16f5f448860f7133330e272edbbca5893ddc6 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.2" async: dependency: transitive description: @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" convert: dependency: transitive description: @@ -117,26 +117,34 @@ packages: dependency: transitive description: name: csslib - sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" url: "https://pub.dev" source: hosted - version: "0.17.2" + version: "1.0.0" dart_code_metrics: dependency: "direct dev" description: name: dart_code_metrics - sha256: "219607f5abbf4c0d254ca39ee009f9ff28df91c40aef26718fde15af6b7a6c24" + sha256: "3dede3f7abc077a4181ec7445448a289a9ce08e2981e6a4d49a3fb5099d47e1f" url: "https://pub.dev" source: hosted - version: "4.21.3" + version: "5.7.6" + dart_code_metrics_presets: + dependency: transitive + description: + name: dart_code_metrics_presets + sha256: b71eadf02a3787ebd5c887623f83f6fdc204d45c75a081bd636c4104b3fd8b73 + url: "https://pub.dev" + source: hosted + version: "1.8.0" dart_style: dependency: transitive description: name: dart_style - sha256: "5be16bf1707658e4c03078d4a9b90208ded217fb02c163e207d334082412f2fb" + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.2.5" + version: "2.3.2" dartssh2: dependency: "direct main" description: @@ -165,10 +173,10 @@ packages: dependency: transitive description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.2" file: dependency: transitive description: @@ -181,10 +189,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: c7a8e25ca60e7f331b153b0cb3d405828f18d3e72a6fa1d9440c86556fffc877 + sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6" url: "https://pub.dev" source: hosted - version: "5.3.0" + version: "6.1.1" flutter: dependency: "direct main" description: flutter @@ -194,10 +202,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0" + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da url: "https://pub.dev" source: hosted - version: "2.0.14" + version: "2.0.17" flutter_pty: dependency: "direct main" description: @@ -220,18 +228,18 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" html: dependency: transitive description: name: html - sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" url: "https://pub.dev" source: hosted - version: "0.15.3" + version: "0.15.4" http: dependency: transitive description: @@ -252,10 +260,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -264,38 +272,62 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: "direct dev" description: name: lints - sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "3.0.0" matcher: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" package_config: dependency: transitive description: @@ -308,18 +340,18 @@ packages: dependency: "direct main" description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" petitparser: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" pinenacl: dependency: transitive description: @@ -332,26 +364,26 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.8" pointycastle: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" process: dependency: transitive description: @@ -372,10 +404,10 @@ packages: dependency: transitive description: name: pub_updater - sha256: "42890302ab2672adf567dc2b20e55b4ecc29d7e19c63b6b98143ab68dd717d3a" + sha256: "05ae70703e06f7fdeb05f7f02dd680b8aad810e87c756a618f33e1794635115c" url: "https://pub.dev" source: hosted - version: "0.2.4" + version: "0.3.0" quiver: dependency: transitive description: @@ -393,26 +425,26 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -433,10 +465,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" typed_data: dependency: transitive description: @@ -445,6 +477,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" vector_math: dependency: transitive description: @@ -453,6 +493,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: @@ -465,18 +513,18 @@ packages: dependency: transitive description: name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "5.2.0" xml: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" xterm: dependency: "direct main" description: @@ -501,5 +549,5 @@ packages: source: hosted version: "0.0.6" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.3.0-279.1.beta <4.0.0" flutter: ">=3.10.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 0796cf57..9ac7d9e5 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -39,7 +39,7 @@ dependencies: after_layout: ^1.1.0 - file_picker: ^5.0.1 + file_picker: ^6.1.1 path: ^1.8.2 @@ -47,9 +47,9 @@ dev_dependencies: flutter_test: sdk: flutter - lints: ^2.0.0 + lints: ^3.0.0 - dart_code_metrics: ^4.16.0 + dart_code_metrics: ^5.7.6 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/example/web/index.html b/example/web/index.html index 9b7a438f..45cf2ca3 100644 --- a/example/web/index.html +++ b/example/web/index.html @@ -1,6 +1,21 @@ + + + @@ -12,22 +27,33 @@ - + example + + + + - - diff --git a/example/web/manifest.json b/example/web/manifest.json index 8c012917..096edf8f 100644 --- a/example/web/manifest.json +++ b/example/web/manifest.json @@ -18,6 +18,18 @@ "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/example/windows/CMakeLists.txt b/example/windows/CMakeLists.txt index 1633297a..d960948a 100644 --- a/example/windows/CMakeLists.txt +++ b/example/windows/CMakeLists.txt @@ -1,13 +1,16 @@ +# 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") -cmake_policy(SET CMP0063 NEW) +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Configure build options. +# Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(IS_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" @@ -20,7 +23,7 @@ else() "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}") @@ -30,6 +33,10 @@ set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 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") @@ -38,14 +45,14 @@ function(APPLY_STANDARD_SETTINGS TARGET) target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") - # Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") add_subdirectory(${FLUTTER_MANAGED_DIR}) -# Application build +# 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) @@ -80,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # 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") diff --git a/example/windows/flutter/CMakeLists.txt b/example/windows/flutter/CMakeLists.txt index b2e4bd8d..903f4899 100644 --- a/example/windows/flutter/CMakeLists.txt +++ b/example/windows/flutter/CMakeLists.txt @@ -1,3 +1,4 @@ +# 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") @@ -9,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -91,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/example/windows/runner/CMakeLists.txt b/example/windows/runner/CMakeLists.txt index de2d8916..394917c0 100644 --- a/example/windows/runner/CMakeLists.txt +++ b/example/windows/runner/CMakeLists.txt @@ -1,6 +1,11 @@ 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" @@ -10,8 +15,26 @@ add_executable(${BINARY_NAME} WIN32 "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_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") 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/example/windows/runner/Runner.rc b/example/windows/runner/Runner.rc index 51812dcd..687e6bd2 100644 --- a/example/windows/runner/Runner.rc +++ b/example/windows/runner/Runner.rc @@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" // Version // -#ifdef FLUTTER_BUILD_NUMBER -#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#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 +#define VERSION_AS_NUMBER 1,0,0,0 #endif -#ifdef FLUTTER_BUILD_NAME -#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION #else #define VERSION_AS_STRING "1.0.0" #endif @@ -90,10 +90,10 @@ BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileDescription", "example" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" VALUE "OriginalFilename", "example.exe" "\0" VALUE "ProductName", "example" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/example/windows/runner/flutter_window.cpp b/example/windows/runner/flutter_window.cpp index b43b9095..955ee303 100644 --- a/example/windows/runner/flutter_window.cpp +++ b/example/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/example/windows/runner/main.cpp b/example/windows/runner/main.cpp index bcb57b0e..a61bf80d 100644 --- a/example/windows/runner/main.cpp +++ b/example/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"example", origin, size)) { + if (!window.Create(L"example", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/example/windows/runner/runner.exe.manifest b/example/windows/runner/runner.exe.manifest index c977c4a4..a42ea768 100644 --- a/example/windows/runner/runner.exe.manifest +++ b/example/windows/runner/runner.exe.manifest @@ -7,7 +7,7 @@ - + diff --git a/example/windows/runner/utils.cpp b/example/windows/runner/utils.cpp index d19bdbbc..b2b08734 100644 --- a/example/windows/runner/utils.cpp +++ b/example/windows/runner/utils.cpp @@ -47,16 +47,17 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { } int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); - if (target_length == 0) { - return std::string(); - } + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); 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); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/example/windows/runner/win32_window.cpp b/example/windows/runner/win32_window.cpp index c10f08dc..60608d0f 100644 --- a/example/windows/runner/win32_window.cpp +++ b/example/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, 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); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/example/windows/runner/win32_window.h b/example/windows/runner/win32_window.h index 17ba4311..e901dde6 100644 --- a/example/windows/runner/win32_window.h +++ b/example/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized 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); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // 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 + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. diff --git a/lib/src/core/buffer/range_block.dart b/lib/src/core/buffer/range_block.dart index 67dd033e..33c18365 100644 --- a/lib/src/core/buffer/range_block.dart +++ b/lib/src/core/buffer/range_block.dart @@ -7,7 +7,7 @@ import 'package:xterm/src/core/buffer/segment.dart'; class BufferRangeBlock extends BufferRange { BufferRangeBlock(super.begin, super.end); - BufferRangeBlock.collapsed(CellOffset begin) : super.collapsed(begin); + BufferRangeBlock.collapsed(super.begin) : super.collapsed(); @override bool get isNormalized { diff --git a/lib/src/core/buffer/range_line.dart b/lib/src/core/buffer/range_line.dart index 2f061e38..83218eb9 100644 --- a/lib/src/core/buffer/range_line.dart +++ b/lib/src/core/buffer/range_line.dart @@ -5,7 +5,7 @@ import 'package:xterm/src/core/buffer/segment.dart'; class BufferRangeLine extends BufferRange { BufferRangeLine(super.begin, super.end); - BufferRangeLine.collapsed(CellOffset begin) : super.collapsed(begin); + BufferRangeLine.collapsed(super.begin) : super.collapsed(); @override BufferRangeLine get normalized { diff --git a/lib/src/terminal_view.dart b/lib/src/terminal_view.dart index cbf92229..d0dc5578 100644 --- a/lib/src/terminal_view.dart +++ b/lib/src/terminal_view.dart @@ -24,11 +24,11 @@ import 'package:xterm/src/ui/themes.dart'; class TerminalView extends StatefulWidget { const TerminalView( this.terminal, { - Key? key, + super.key, this.controller, this.theme = TerminalThemes.defaultTheme, this.textStyle = const TerminalStyle(), - this.textScaleFactor, + this.textScaler, this.padding, this.scrollController, this.autoResize = true, @@ -49,7 +49,7 @@ class TerminalView extends StatefulWidget { this.readOnly = false, this.hardwareKeyboardOnly = false, this.simulateScroll = true, - }) : super(key: key); + }); /// The underlying terminal that this widget renders. final Terminal terminal; @@ -62,10 +62,7 @@ class TerminalView extends StatefulWidget { /// The style to use for painting characters. final TerminalStyle textStyle; - /// The number of font pixels for each logical pixel. If null, will use the - /// [MediaQueryData.textScaleFactor] obtained from [MediaQuery], or 1.0 if - /// there is no [MediaQuery] in scope. - final double? textScaleFactor; + final TextScaler? textScaler; /// Padding around the inner [Scrollable] widget. final EdgeInsets? padding; @@ -129,7 +126,7 @@ class TerminalView extends StatefulWidget { /// Keyboard event handler of the terminal. This has higher priority than /// [shortcuts] and input handler of the terminal. - final FocusOnKeyCallback? onKey; + final FocusOnKeyEventCallback? onKey; /// True if no input should send to the terminal. final bool readOnly; @@ -233,8 +230,7 @@ class TerminalViewState extends State { padding: MediaQuery.of(context).padding, autoResize: widget.autoResize, textStyle: widget.textStyle, - textScaleFactor: - widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context), + textScaler: widget.textScaler ?? MediaQuery.textScalerOf(context), theme: widget.theme, focusNode: _focusNode, cursorType: widget.cursorType, @@ -273,7 +269,7 @@ class TerminalViewState extends State { widget.terminal.keyInput(TerminalKey.enter); } }, - onKey: _handleKeyEvent, + onKeyEvent: _handleKeyEvent, readOnly: widget.readOnly, child: child, ); @@ -285,7 +281,7 @@ class TerminalViewState extends State { autofocus: widget.autofocus, onInsert: _onInsert, onComposing: _onComposing, - onKey: _handleKeyEvent, + onKeyEvent: _handleKeyEvent, ); } @@ -394,7 +390,7 @@ class TerminalViewState extends State { setState(() => _composingText = text); } - KeyEventResult _handleKeyEvent(FocusNode focusNode, RawKeyEvent event) { + KeyEventResult _handleKeyEvent(FocusNode focusNode, KeyEvent event) { final resultOverride = widget.onKey?.call(focusNode, event); if (resultOverride != null && resultOverride != KeyEventResult.ignored) { return resultOverride; @@ -410,7 +406,7 @@ class TerminalViewState extends State { return shortcutResult; } - if (event is! RawKeyDownEvent) { + if (event is! KeyDownEvent) { return KeyEventResult.ignored; } @@ -422,9 +418,9 @@ class TerminalViewState extends State { final handled = widget.terminal.keyInput( key, - ctrl: event.isControlPressed, - alt: event.isAltPressed, - shift: event.isShiftPressed, + ctrl: HardwareKeyboard.instance.isControlPressed, + alt: HardwareKeyboard.instance.isAltPressed, + shift: HardwareKeyboard.instance.isShiftPressed, ); if (handled) { @@ -456,21 +452,21 @@ class TerminalViewState extends State { class _TerminalView extends LeafRenderObjectWidget { const _TerminalView({ - Key? key, + super.key, required this.terminal, required this.controller, required this.offset, required this.padding, required this.autoResize, required this.textStyle, - required this.textScaleFactor, + required this.textScaler, required this.theme, required this.focusNode, required this.cursorType, required this.alwaysShowCursor, this.onEditableRect, this.composingText, - }) : super(key: key); + }); final Terminal terminal; @@ -484,7 +480,7 @@ class _TerminalView extends LeafRenderObjectWidget { final TerminalStyle textStyle; - final double textScaleFactor; + final TextScaler textScaler; final TerminalTheme theme; @@ -507,7 +503,7 @@ class _TerminalView extends LeafRenderObjectWidget { padding: padding, autoResize: autoResize, textStyle: textStyle, - textScaleFactor: textScaleFactor, + textScaler: textScaler, theme: theme, focusNode: focusNode, cursorType: cursorType, @@ -526,7 +522,7 @@ class _TerminalView extends LeafRenderObjectWidget { ..padding = padding ..autoResize = autoResize ..textStyle = textStyle - ..textScaleFactor = textScaleFactor + ..textScaler = textScaler ..theme = theme ..focusNode = focusNode ..cursorType = cursorType diff --git a/lib/src/ui/custom_text_edit.dart b/lib/src/ui/custom_text_edit.dart index 6b237019..1d33c7a2 100644 --- a/lib/src/ui/custom_text_edit.dart +++ b/lib/src/ui/custom_text_edit.dart @@ -4,13 +4,13 @@ import 'package:flutter/services.dart'; class CustomTextEdit extends StatefulWidget { CustomTextEdit({ - Key? key, + super.key, required this.child, required this.onInsert, required this.onDelete, required this.onComposing, required this.onAction, - required this.onKey, + required this.onKeyEvent, required this.focusNode, this.autofocus = false, this.readOnly = false, @@ -19,7 +19,7 @@ class CustomTextEdit extends StatefulWidget { this.inputAction = TextInputAction.newline, this.keyboardAppearance = Brightness.light, this.deleteDetection = false, - }) : super(key: key); + }); final Widget child; @@ -31,7 +31,7 @@ class CustomTextEdit extends StatefulWidget { final void Function(TextInputAction) onAction; - final KeyEventResult Function(FocusNode, RawKeyEvent) onKey; + final KeyEventResult Function(FocusNode, KeyEvent) onKeyEvent; final FocusNode focusNode; @@ -90,7 +90,7 @@ class CustomTextEditState extends State with TextInputClient { return Focus( focusNode: widget.focusNode, autofocus: widget.autofocus, - onKey: _onKey, + onKeyEvent: _onKeyEvent, child: widget.child, ); } @@ -133,9 +133,9 @@ class CustomTextEditState extends State with TextInputClient { _openOrCloseInputConnectionIfNeeded(); } - KeyEventResult _onKey(FocusNode focusNode, RawKeyEvent event) { + KeyEventResult _onKeyEvent(FocusNode focusNode, KeyEvent event) { if (_currentEditingState.composing.isCollapsed) { - return widget.onKey(focusNode, event); + return widget.onKeyEvent(focusNode, event); } return KeyEventResult.skipRemainingHandlers; diff --git a/lib/src/ui/keyboard_listener.dart b/lib/src/ui/keyboard_listener.dart index 6a5e1aef..bb2f9920 100644 --- a/lib/src/ui/keyboard_listener.dart +++ b/lib/src/ui/keyboard_listener.dart @@ -1,4 +1,3 @@ -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; class CustomKeyboardListener extends StatelessWidget { @@ -12,42 +11,27 @@ class CustomKeyboardListener extends StatelessWidget { final void Function(String?) onComposing; - final KeyEventResult Function(FocusNode, RawKeyEvent) onKey; + final KeyEventResult Function(FocusNode, KeyEvent) onKeyEvent; const CustomKeyboardListener({ - Key? key, + super.key, required this.child, required this.focusNode, this.autofocus = false, required this.onInsert, required this.onComposing, - required this.onKey, - }) : super(key: key); + required this.onKeyEvent, + }); - KeyEventResult _onKey(FocusNode focusNode, RawKeyEvent keyEvent) { + KeyEventResult _onKeyEvent(FocusNode focusNode, KeyEvent keyEvent) { // First try to handle the key event directly. - final handled = onKey(focusNode, keyEvent); + final handled = onKeyEvent(focusNode, keyEvent); if (handled == KeyEventResult.ignored) { // If it was not handled, but the key corresponds to a character, // insert the character. if (keyEvent.character != null && keyEvent.character != "") { onInsert(keyEvent.character!); return KeyEventResult.handled; - } else if (keyEvent.data is RawKeyEventDataIos && - keyEvent is RawKeyDownEvent) { - // On iOS keyEvent.character is always null. But data.characters - // contains the the character(s) corresponding to the input. - final data = keyEvent.data as RawKeyEventDataIos; - if (data.characters != "") { - onComposing(null); - onInsert(data.characters); - } else if (data.charactersIgnoringModifiers != "") { - // If characters is an empty string but charactersIgnoringModifiers is - // not an empty string, this indicates that the current characters is - // being composed. The current composing state is - // charactersIgnoringModifiers. - onComposing(data.charactersIgnoringModifiers); - } } } return handled; @@ -58,7 +42,7 @@ class CustomKeyboardListener extends StatelessWidget { return Focus( focusNode: focusNode, autofocus: autofocus, - onKey: _onKey, + onKeyEvent: _onKeyEvent, child: child, ); } diff --git a/lib/src/ui/keyboard_visibility.dart b/lib/src/ui/keyboard_visibility.dart index 0b3b0095..158c5d11 100644 --- a/lib/src/ui/keyboard_visibility.dart +++ b/lib/src/ui/keyboard_visibility.dart @@ -2,11 +2,11 @@ import 'package:flutter/widgets.dart'; class KeyboardVisibilty extends StatefulWidget { const KeyboardVisibilty({ - Key? key, + super.key, required this.child, this.onKeyboardShow, this.onKeyboardHide, - }) : super(key: key); + }); final Widget child; diff --git a/lib/src/ui/painter.dart b/lib/src/ui/painter.dart index 378e635d..64a78e08 100644 --- a/lib/src/ui/painter.dart +++ b/lib/src/ui/painter.dart @@ -1,4 +1,5 @@ import 'dart:ui'; +import 'package:flutter/painting.dart'; import 'package:xterm/src/ui/palette_builder.dart'; import 'package:xterm/src/ui/paragraph_cache.dart'; @@ -9,10 +10,10 @@ class TerminalPainter { TerminalPainter({ required TerminalTheme theme, required TerminalStyle textStyle, - required double textScaleFactor, + required TextScaler textScaler, }) : _textStyle = textStyle, _theme = theme, - _textScaleFactor = textScaleFactor; + _textScaler = textScaler; /// A lookup table from terminal colors to Flutter colors. late var _colorPalette = PaletteBuilder(_theme).build(); @@ -34,11 +35,11 @@ class TerminalPainter { _paragraphCache.clear(); } - double get textScaleFactor => _textScaleFactor; - double _textScaleFactor = 1.0; - set textScaleFactor(double value) { - if (value == _textScaleFactor) return; - _textScaleFactor = value; + TextScaler get textScaler => _textScaler; + TextScaler _textScaler = TextScaler.linear(1.0); + set textScaler(TextScaler value) { + if (value == _textScaler) return; + _textScaler = value; _cellSize = _measureCharSize(); _paragraphCache.clear(); } @@ -58,7 +59,7 @@ class TerminalPainter { final textStyle = _textStyle.toTextStyle(); final builder = ParagraphBuilder(textStyle.getParagraphStyle()); builder.pushStyle( - textStyle.getTextStyle(textScaleFactor: _textScaleFactor), + textStyle.getTextStyle(textScaler: _textScaler), ); builder.addText(test); @@ -173,7 +174,7 @@ class TerminalPainter { final charCode = cellData.content & CellContent.codepointMask; if (charCode == 0) return; - final cacheKey = cellData.getHash() ^ _textScaleFactor.hashCode; + final cacheKey = cellData.getHash() ^ _textScaler.hashCode; var paragraph = _paragraphCache.getLayoutFromCache(cacheKey); if (paragraph == null) { @@ -208,7 +209,7 @@ class TerminalPainter { paragraph = _paragraphCache.performAndCacheLayout( char, style, - _textScaleFactor, + _textScaler, cacheKey, ); } diff --git a/lib/src/ui/paragraph_cache.dart b/lib/src/ui/paragraph_cache.dart index 8dd71589..1dfd4bae 100644 --- a/lib/src/ui/paragraph_cache.dart +++ b/lib/src/ui/paragraph_cache.dart @@ -23,11 +23,11 @@ class ParagraphCache { Paragraph performAndCacheLayout( String text, TextStyle style, - double textScaleFactor, + TextScaler textScaler, int key, ) { final builder = ParagraphBuilder(style.getParagraphStyle()); - builder.pushStyle(style.getTextStyle(textScaleFactor: textScaleFactor)); + builder.pushStyle(style.getTextStyle(textScaler: textScaler)); builder.addText(text); final paragraph = builder.build(); diff --git a/lib/src/ui/render.dart b/lib/src/ui/render.dart index 08f07f24..de2a2f7f 100644 --- a/lib/src/ui/render.dart +++ b/lib/src/ui/render.dart @@ -1,4 +1,4 @@ -import 'dart:math' show min, max; +import 'dart:math' show max; import 'dart:ui'; import 'package:flutter/rendering.dart'; @@ -27,7 +27,7 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin { required EdgeInsets padding, required bool autoResize, required TerminalStyle textStyle, - required double textScaleFactor, + required TextScaler textScaler, required TerminalTheme theme, required FocusNode focusNode, required TerminalCursorType cursorType, @@ -47,7 +47,7 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin { _painter = TerminalPainter( theme: theme, textStyle: textStyle, - textScaleFactor: textScaleFactor, + textScaler: textScaler, ); Terminal _terminal; @@ -98,9 +98,9 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin { markNeedsLayout(); } - set textScaleFactor(double value) { - if (value == _painter.textScaleFactor) return; - _painter.textScaleFactor = value; + set textScaler(TextScaler value) { + if (value == _painter.textScaler) return; + _painter.textScaler = value; markNeedsLayout(); } @@ -475,7 +475,7 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin { PlaceholderAlignment.middle, ); builder.pushStyle( - style.getTextStyle(textScaleFactor: _painter.textScaleFactor), + style.getTextStyle(textScaler: _painter.textScaler), ); builder.addText(composingText); diff --git a/lib/src/utils/debugger_view.dart b/lib/src/utils/debugger_view.dart index 00d6f0d6..f5ff556a 100644 --- a/lib/src/utils/debugger_view.dart +++ b/lib/src/utils/debugger_view.dart @@ -4,10 +4,10 @@ import 'package:xterm/src/utils/debugger.dart'; class TerminalDebuggerView extends StatefulWidget { const TerminalDebuggerView( this.debugger, { - Key? key, + super.key, this.scrollController, this.onSeek, - }) : super(key: key); + }); final TerminalDebugger debugger; @@ -78,10 +78,9 @@ class _CommandItem extends StatelessWidget { const _CommandItem( this.index, this.command, { - Key? key, this.onTap, this.selected = false, - }) : super(key: key); + }); final int index; diff --git a/lib/zmodem.dart b/lib/zmodem.dart index c45b8076..6498e6d5 100644 --- a/lib/zmodem.dart +++ b/lib/zmodem.dart @@ -93,7 +93,7 @@ class ZModemMux { /// buffered if a ZModem session is active. void terminalWrite(String input) { if (_session == null) { - stdin.add(utf8.encode(input) as Uint8List); + stdin.add(utf8.encode(input)); } } diff --git a/pubspec.lock b/pubspec.lock index 38a104ae..1bd3e87c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "8880b4cfe7b5b17d57c052a5a3a8cc1d4f546261c7cc8fbd717bd53f48db0568" + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a url: "https://pub.dev" source: hosted - version: "59.0.0" + version: "61.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: a89627f49b0e70e068130a36571409726b04dab12da7e5625941d2c8ec278b96 + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 url: "https://pub.dev" source: hosted - version: "5.11.1" + version: "5.13.0" analyzer_plugin: dependency: transitive description: @@ -29,18 +29,18 @@ packages: dependency: transitive description: name: ansicolor - sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" + sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" args: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" async: dependency: transitive description: @@ -61,10 +61,10 @@ packages: dependency: transitive description: name: build - sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" build_config: dependency: transitive description: @@ -77,34 +77,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "220ae4553e50d7c21a17c051afc7b183d28a24a420502e842f303f8e4e6edced" + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.8" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "30859c90e9ddaccc484f56303931f477b1f1ba2bab74aa32ed5d6ce15870f8cf" + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.8" + version: "7.3.0" built_collection: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: built_value - sha256: "2f17434bd5d52a26762043d6b43bb53b3acd029b4d9071a329f46d67ef297e6d" + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e url: "https://pub.dev" source: hosted - version: "8.5.0" + version: "8.9.1" characters: dependency: transitive description: @@ -149,18 +149,18 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.10.0" collection: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" convert: dependency: "direct main" description: @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.7.2" crypto: dependency: transitive description: @@ -189,34 +189,34 @@ packages: dependency: transitive description: name: csslib - sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" url: "https://pub.dev" source: hosted - version: "0.17.2" + version: "1.0.0" dart_code_metrics: dependency: "direct dev" description: name: dart_code_metrics - sha256: "162c81dbd0a2ba182f38ca615335f3e8878f212ec7beea83d6bfad4e99eb541a" + sha256: "3dede3f7abc077a4181ec7445448a289a9ce08e2981e6a4d49a3fb5099d47e1f" url: "https://pub.dev" source: hosted - version: "5.7.3" + version: "5.7.6" dart_code_metrics_presets: dependency: transitive description: name: dart_code_metrics_presets - sha256: "22e27f98e8c7d8b11cca43d2656a822935280747050ae65e8cd03c52d09c0d1c" + sha256: b71eadf02a3787ebd5c887623f83f6fdc204d45c75a081bd636c4104b3fd8b73 url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.8.0" dart_style: dependency: transitive description: name: dart_style - sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" equatable: dependency: "direct main" description: @@ -271,26 +271,26 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" graphs: dependency: transitive description: name: graphs - sha256: "772db3d53d23361d4ffcf5a9bb091cf3ee9b22f2be52cd107cd7a2683a89ba0e" + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" html: dependency: transitive description: name: html - sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" url: "https://pub.dev" source: hosted - version: "0.15.3" + version: "0.15.4" http: dependency: transitive description: @@ -339,62 +339,86 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: "direct dev" description: name: lints - sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "3.0.0" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" matcher: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: "direct main" description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" mockito: dependency: "direct dev" description: name: mockito - sha256: dd61809f04da1838a680926de50a9e87385c1de91c6579629c3d1723946e8059 + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "5.4.4" node_preamble: dependency: transitive description: @@ -415,26 +439,26 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" petitparser: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" pool: dependency: transitive description: @@ -524,10 +548,10 @@ packages: dependency: transitive description: name: source_gen - sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.5.0" source_map_stack_trace: dependency: transitive description: @@ -548,26 +572,26 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -596,26 +620,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.1" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.5.9" timing: dependency: transitive description: @@ -652,10 +676,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f3743ca475e0c9ef71df4ba15eb2d7684eecd5c8ba20a462462e4e8b561b2e11 + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.6.0" + version: "13.0.0" watcher: dependency: transitive description: @@ -664,30 +688,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad" + url: "https://pub.dev" + source: hosted + version: "0.5.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" xml: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" yaml: dependency: transitive description: @@ -705,5 +737,5 @@ packages: source: hosted version: "0.0.6" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.3.0 <4.0.0" flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7e7bee3b..53d80ba5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ dev_dependencies: flutter_test: sdk: flutter test: ^1.6.5 - lints: ^2.0.0 + lints: ^3.0.0 dart_code_metrics: ^5.0.0 mockito: ^5.3.1 build_runner: ^2.1.1 diff --git a/test/src/terminal_view_test.dart b/test/src/terminal_view_test.dart index 86355f09..f9e76604 100644 --- a/test/src/terminal_view_test.dart +++ b/test/src/terminal_view_test.dart @@ -310,17 +310,17 @@ void main() { testWidgets('works', (tester) async { final terminal = Terminal(); - final textScaleFactor = ValueNotifier(1.0); + final textScaler = ValueNotifier(TextScaler.linear(1.0)); await tester.pumpWidget( MaterialApp( home: Scaffold( - body: ValueListenableBuilder( - valueListenable: textScaleFactor, - builder: (context, textScaleFactor, child) { + body: ValueListenableBuilder( + valueListenable: textScaler, + builder: (context, textScaler, child) { return TerminalView( terminal, - textScaleFactor: textScaleFactor, + textScaler: textScaler, ); }, ), @@ -336,7 +336,7 @@ void main() { matchesGoldenFile('_goldens/text_scale_factor@1x.png'), ); - textScaleFactor.value = 2.0; + textScaler.value = TextScaler.linear(2.0); await tester.pump(); await expectLater( @@ -352,7 +352,7 @@ void main() { MaterialApp( home: Scaffold( body: MediaQuery( - data: const MediaQueryData(textScaleFactor: 2.0), + data: const MediaQueryData(textScaler: TextScaler.linear(2.0)), child: TerminalView( terminal, ), From 5c40122c2775b239f4aef7bb3fad3318620f30b1 Mon Sep 17 00:00:00 2001 From: Brett Morgan Date: Fri, 23 Feb 2024 08:23:43 +1100 Subject: [PATCH 2/6] Revert `Release.entitlements` change --- example/macos/Runner/Release.entitlements | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/example/macos/Runner/Release.entitlements b/example/macos/Runner/Release.entitlements index 852fa1a4..0c67376e 100644 --- a/example/macos/Runner/Release.entitlements +++ b/example/macos/Runner/Release.entitlements @@ -1,8 +1,5 @@ - - com.apple.security.app-sandbox - - + From 41cd7512e11a9c7bdc636117c1500b5a29b67937 Mon Sep 17 00:00:00 2001 From: Brett Morgan Date: Fri, 23 Feb 2024 08:25:50 +1100 Subject: [PATCH 3/6] `onKey` -> `onKeyEvent` --- example/lib/suggestion.dart | 2 +- lib/src/terminal_view.dart | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/lib/suggestion.dart b/example/lib/suggestion.dart index 1cfd1fa6..65f2e8c0 100644 --- a/example/lib/suggestion.dart +++ b/example/lib/suggestion.dart @@ -265,7 +265,7 @@ class _HomeState extends State { controller: terminalController, autofocus: true, backgroundOpacity: 0.7, - onKey: (node, event) { + onKeyEvent: (node, event) { if (event is! KeyDownEvent) { return KeyEventResult.ignored; } diff --git a/lib/src/terminal_view.dart b/lib/src/terminal_view.dart index d0dc5578..7d2416a1 100644 --- a/lib/src/terminal_view.dart +++ b/lib/src/terminal_view.dart @@ -45,7 +45,7 @@ class TerminalView extends StatefulWidget { this.alwaysShowCursor = false, this.deleteDetection = false, this.shortcuts, - this.onKey, + this.onKeyEvent, this.readOnly = false, this.hardwareKeyboardOnly = false, this.simulateScroll = true, @@ -126,7 +126,7 @@ class TerminalView extends StatefulWidget { /// Keyboard event handler of the terminal. This has higher priority than /// [shortcuts] and input handler of the terminal. - final FocusOnKeyEventCallback? onKey; + final FocusOnKeyEventCallback? onKeyEvent; /// True if no input should send to the terminal. final bool readOnly; @@ -391,7 +391,7 @@ class TerminalViewState extends State { } KeyEventResult _handleKeyEvent(FocusNode focusNode, KeyEvent event) { - final resultOverride = widget.onKey?.call(focusNode, event); + final resultOverride = widget.onKeyEvent?.call(focusNode, event); if (resultOverride != null && resultOverride != KeyEventResult.ignored) { return resultOverride; } From acaba2ce9e0270b92fb644c149568b77cc982cf8 Mon Sep 17 00:00:00 2001 From: Brett Morgan Date: Fri, 23 Feb 2024 09:00:07 +1100 Subject: [PATCH 4/6] Update goldens Context: https://medium.com/flutter-community/flutter-golden-tests-compare-widgets-with-snapshots-27f83f266cea --- test/src/_goldens/colors.png | Bin 22011 -> 21740 bytes test/src/_goldens/htop_80x25_3s.png | Bin 12705 -> 12724 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/src/_goldens/colors.png b/test/src/_goldens/colors.png index 6ec0ea256002468e2913ef0a2ce90b55b3cce725..c2f98fbc45b3b0d0aa1f6fc947c0da928a82f66a 100644 GIT binary patch literal 21740 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 literal 22011 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 From 6adab96fe24d6ff11a4e616e394ef2443216b29d Mon Sep 17 00:00:00 2001 From: Brett Morgan Date: Fri, 23 Feb 2024 09:35:23 +1100 Subject: [PATCH 5/6] Add key repeat and enable debugging for DebugProfile on macOS --- example/macos/Runner/DebugProfile.entitlements | 2 ++ lib/src/terminal_view.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/example/macos/Runner/DebugProfile.entitlements b/example/macos/Runner/DebugProfile.entitlements index d35e43ae..4eac53fe 100644 --- a/example/macos/Runner/DebugProfile.entitlements +++ b/example/macos/Runner/DebugProfile.entitlements @@ -4,5 +4,7 @@ com.apple.security.cs.allow-jit + com.apple.security.network.server + diff --git a/lib/src/terminal_view.dart b/lib/src/terminal_view.dart index 7d2416a1..cf2c3c3c 100644 --- a/lib/src/terminal_view.dart +++ b/lib/src/terminal_view.dart @@ -406,7 +406,7 @@ class TerminalViewState extends State { return shortcutResult; } - if (event is! KeyDownEvent) { + if (event is KeyUpEvent) { return KeyEventResult.ignored; } From 9e601c25491d67682c41aacdc4d51fd99a680e6b Mon Sep 17 00:00:00 2001 From: Brett Morgan Date: Sat, 24 Feb 2024 00:45:29 +1100 Subject: [PATCH 6/6] Clean up remaining `TextScaleFactor` references --- lib/src/ui/char_metrics.dart | 5 +++-- lib/src/ui/paragraph_cache.dart | 2 +- test/src/terminal_view_test.dart | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/src/ui/char_metrics.dart b/lib/src/ui/char_metrics.dart index d7d37108..e35439d4 100644 --- a/lib/src/ui/char_metrics.dart +++ b/lib/src/ui/char_metrics.dart @@ -1,13 +1,14 @@ import 'dart:ui'; +import 'package:flutter/painting.dart'; import 'package:xterm/src/ui/terminal_text_style.dart'; -Size calcCharSize(TerminalStyle style, double textScaleFactor) { +Size calcCharSize(TerminalStyle style, TextScaler textScaler) { const test = 'mmmmmmmmmm'; final textStyle = style.toTextStyle(); final builder = ParagraphBuilder(textStyle.getParagraphStyle()); - builder.pushStyle(textStyle.getTextStyle(textScaleFactor: textScaleFactor)); + builder.pushStyle(textStyle.getTextStyle(textScaler: textScaler)); builder.addText(test); final paragraph = builder.build(); diff --git a/lib/src/ui/paragraph_cache.dart b/lib/src/ui/paragraph_cache.dart index 1dfd4bae..80896a04 100644 --- a/lib/src/ui/paragraph_cache.dart +++ b/lib/src/ui/paragraph_cache.dart @@ -17,7 +17,7 @@ class ParagraphCache { return _cache[key]; } - /// Applies [style] and [textScaleFactor] to [text] and lays it out to create + /// Applies [style] and [textScaler] to [text] and lays it out to create /// a [Paragraph]. The [Paragraph] is cached and can be retrieved with the /// same [key] by calling [getLayoutFromCache]. Paragraph performAndCacheLayout( diff --git a/test/src/terminal_view_test.dart b/test/src/terminal_view_test.dart index f9e76604..0540e09d 100644 --- a/test/src/terminal_view_test.dart +++ b/test/src/terminal_view_test.dart @@ -306,7 +306,7 @@ void main() { }); }); - group('TerminalView.textScaleFactor', () { + group('TerminalView.textScaler', () { testWidgets('works', (tester) async { final terminal = Terminal(); @@ -345,7 +345,7 @@ void main() { ); }); - testWidgets('can obtain textScaleFactor from parent', (tester) async { + testWidgets('can obtain textScaler from parent', (tester) async { final terminal = Terminal(); await tester.pumpWidget(