From 23efa0a603ca9c81325127302cbe427e7de3a56e Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 15:06:51 -0700 Subject: [PATCH 1/7] Add Flutter logo to assets/logos directory --- assets/logos/flutter.png | Bin 0 -> 6749 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/logos/flutter.png diff --git a/assets/logos/flutter.png b/assets/logos/flutter.png new file mode 100644 index 0000000000000000000000000000000000000000..ee515bea2b7d3a9a5081706cbbe2de421a822b1a GIT binary patch literal 6749 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 literal 0 HcmV?d00001 From cdd79c44a76fa16221877412d687ee51c45142ba Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 18:21:19 -0700 Subject: [PATCH 2/7] Optimize Flutter logo PNG --- assets/logos/flutter.png | Bin 6749 -> 4218 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/logos/flutter.png b/assets/logos/flutter.png index ee515bea2b7d3a9a5081706cbbe2de421a822b1a..df6cb5cfaff48b2af6c5140312c2b23ce3e976e4 100644 GIT binary patch literal 4218 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 Q*Zxg_99-W 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 From 06c9c864f6f886d58989371347954e03d563659a Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 18:27:08 -0700 Subject: [PATCH 3/7] Apply CI formatting fixes manually --- packages/diagram_capture/lib/diagram_capture.dart | 8 ++++++-- packages/diagram_capture/test/diagram_capture_test.dart | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/diagram_capture/lib/diagram_capture.dart b/packages/diagram_capture/lib/diagram_capture.dart index c91ff344..ba0715b0 100644 --- a/packages/diagram_capture/lib/diagram_capture.dart +++ b/packages/diagram_capture/lib/diagram_capture.dart @@ -341,8 +341,12 @@ typedef DiagramKeyframe = void Function(Duration duration); /// A callback given to drawAnimatedDiagramToFiles that is called for each /// frame. -typedef DiagramGestureCallback = - void Function(DiagramController diagram, Duration now); +typedef DiagramGestureCallback = void Function( + DiagramController diagram, + Duration now, +); + Duration now, +); /// A controller for creating diagrams generated by using Flutter widgets. /// diff --git a/packages/diagram_capture/test/diagram_capture_test.dart b/packages/diagram_capture/test/diagram_capture_test.dart index c6edf92b..6d897c3c 100644 --- a/packages/diagram_capture/test/diagram_capture_test.dart +++ b/packages/diagram_capture/test/diagram_capture_test.dart @@ -128,9 +128,9 @@ void main() { expect(outputFile.lengthSync(), greaterThan(0)); Map loadMetadata(File metadataFile) { - final Map metadata = - json.decode(metadataFile.readAsStringSync()) - as Map; + final Map metadata = json.decode( + metadataFile.readAsStringSync(), + ) as Map; final String baseDir = path.dirname(metadataFile.absolute.path); final List frameFiles = (metadata['frame_files']! as List) From ce2c0d4f812c66a8eb98e1fd0410949e0ada9c5d Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 18:29:03 -0700 Subject: [PATCH 4/7] format diagram_capture.dart --- packages/diagram_capture/lib/diagram_capture.dart | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/diagram_capture/lib/diagram_capture.dart b/packages/diagram_capture/lib/diagram_capture.dart index ba0715b0..c91ff344 100644 --- a/packages/diagram_capture/lib/diagram_capture.dart +++ b/packages/diagram_capture/lib/diagram_capture.dart @@ -341,12 +341,8 @@ typedef DiagramKeyframe = void Function(Duration duration); /// A callback given to drawAnimatedDiagramToFiles that is called for each /// frame. -typedef DiagramGestureCallback = void Function( - DiagramController diagram, - Duration now, -); - Duration now, -); +typedef DiagramGestureCallback = + void Function(DiagramController diagram, Duration now); /// A controller for creating diagrams generated by using Flutter widgets. /// From b3c2a57de382e5006f9b545afdcbb9d74c434cdd Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 18:33:50 -0700 Subject: [PATCH 5/7] format --- packages/diagram_capture/test/diagram_capture_test.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/diagram_capture/test/diagram_capture_test.dart b/packages/diagram_capture/test/diagram_capture_test.dart index 6d897c3c..c6edf92b 100644 --- a/packages/diagram_capture/test/diagram_capture_test.dart +++ b/packages/diagram_capture/test/diagram_capture_test.dart @@ -128,9 +128,9 @@ void main() { expect(outputFile.lengthSync(), greaterThan(0)); Map loadMetadata(File metadataFile) { - final Map metadata = json.decode( - metadataFile.readAsStringSync(), - ) as Map; + final Map metadata = + json.decode(metadataFile.readAsStringSync()) + as Map; final String baseDir = path.dirname(metadataFile.absolute.path); final List frameFiles = (metadata['frame_files']! as List) From fb172ba9475b423facaa0ec850fce7793f751e49 Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 18:43:44 -0700 Subject: [PATCH 6/7] Apply patch --- packages/diagram_capture/lib/diagram_capture.dart | 6 ++++-- packages/diagram_capture/test/diagram_capture_test.dart | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/diagram_capture/lib/diagram_capture.dart b/packages/diagram_capture/lib/diagram_capture.dart index c91ff344..329abb42 100644 --- a/packages/diagram_capture/lib/diagram_capture.dart +++ b/packages/diagram_capture/lib/diagram_capture.dart @@ -341,8 +341,10 @@ typedef DiagramKeyframe = void Function(Duration duration); /// A callback given to drawAnimatedDiagramToFiles that is called for each /// frame. -typedef DiagramGestureCallback = - void Function(DiagramController diagram, Duration now); +typedef DiagramGestureCallback = void Function( + DiagramController diagram, + Duration now, +); /// A controller for creating diagrams generated by using Flutter widgets. /// diff --git a/packages/diagram_capture/test/diagram_capture_test.dart b/packages/diagram_capture/test/diagram_capture_test.dart index c6edf92b..6d897c3c 100644 --- a/packages/diagram_capture/test/diagram_capture_test.dart +++ b/packages/diagram_capture/test/diagram_capture_test.dart @@ -128,9 +128,9 @@ void main() { expect(outputFile.lengthSync(), greaterThan(0)); Map loadMetadata(File metadataFile) { - final Map metadata = - json.decode(metadataFile.readAsStringSync()) - as Map; + final Map metadata = json.decode( + metadataFile.readAsStringSync(), + ) as Map; final String baseDir = path.dirname(metadataFile.absolute.path); final List frameFiles = (metadata['frame_files']! as List) From 65b09ab11de7720bd2126e573d5c5f693d1129d6 Mon Sep 17 00:00:00 2001 From: John Ryan Date: Mon, 4 May 2026 18:53:56 -0700 Subject: [PATCH 7/7] Hack CI to fix "extra analysis_options.yaml" error. --- .gitignore | 9 +++++++++ analysis_options.yaml | 4 ++++ ci/allowed_custom_analysis.yaml | 5 +++++ ci/check | 9 ++++++++- packages/diagram_viewer/.gitignore | 9 +++++++++ .../diagram_viewer/linux/flutter/generated_plugins.cmake | 1 + .../macos/Flutter/GeneratedPluginRegistrant.swift | 2 -- .../windows/flutter/generated_plugins.cmake | 1 + 8 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 ci/allowed_custom_analysis.yaml diff --git a/.gitignore b/.gitignore index 0e813521..f38af7cc 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,15 @@ unlinked_spec.ds **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* +# Linux related +**/linux/flutter/ephemeral/ + +# Windows related +**/windows/flutter/ephemeral/ + +# macOS related +**/macos/Flutter/ephemeral/ + # Exceptions to above rules. !**/ios/**/default.mode1v3 !**/ios/**/default.mode2v3 diff --git a/analysis_options.yaml b/analysis_options.yaml index 7c6617f2..ca51c373 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -5,6 +5,10 @@ # "DIFFERENT FROM FLUTTER/FLUTTER" below. analyzer: + exclude: + - "packages/**/linux/flutter/ephemeral/**" + - "packages/**/windows/flutter/ephemeral/**" + - "packages/**/macos/Flutter/ephemeral/**" language: strict-casts: true strict-raw-types: true diff --git a/ci/allowed_custom_analysis.yaml b/ci/allowed_custom_analysis.yaml new file mode 100644 index 00000000..39667265 --- /dev/null +++ b/ci/allowed_custom_analysis.yaml @@ -0,0 +1,5 @@ +- animation_metadata +- diagram_capture +- diagram_generator +- diagram_viewer +- diagrams diff --git a/ci/check b/ci/check index 81e998c8..8c3b99aa 100755 --- a/ci/check +++ b/ci/check @@ -62,5 +62,12 @@ fi for check in "${CHECKS[@]}"; do echo "Running $check" - dart pub global run flutter_plugin_tools "$check" --run-on-changed-packages + EXTRA_ARGS="" + if [[ "$check" == "analyze" ]]; then + # Remove ephemeral directories that may contain extra analysis_options.yaml files + # symlinked by plugins, which causes flutter_plugin_tools to fail. + find . -name "ephemeral" -type d -prune -exec rm -rf {} + + EXTRA_ARGS="--custom-analysis=ci/allowed_custom_analysis.yaml" + fi + dart pub global run flutter_plugin_tools "$check" --run-on-changed-packages $EXTRA_ARGS done diff --git a/packages/diagram_viewer/.gitignore b/packages/diagram_viewer/.gitignore index 7e2ead20..4cf67f7e 100644 --- a/packages/diagram_viewer/.gitignore +++ b/packages/diagram_viewer/.gitignore @@ -66,6 +66,15 @@ build/ **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* +# Linux related +**/linux/flutter/ephemeral/ + +# Windows related +**/windows/flutter/ephemeral/ + +# macOS related +**/macos/Flutter/ephemeral/ + # Exceptions to above rules. !**/ios/**/default.mode1v3 !**/ios/**/default.mode2v3 diff --git a/packages/diagram_viewer/linux/flutter/generated_plugins.cmake b/packages/diagram_viewer/linux/flutter/generated_plugins.cmake index 2e1de87a..be1ee3e5 100644 --- a/packages/diagram_viewer/linux/flutter/generated_plugins.cmake +++ b/packages/diagram_viewer/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/packages/diagram_viewer/macos/Flutter/GeneratedPluginRegistrant.swift b/packages/diagram_viewer/macos/Flutter/GeneratedPluginRegistrant.swift index b8e2b22f..724bb2ac 100644 --- a/packages/diagram_viewer/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/packages/diagram_viewer/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,10 +5,8 @@ import FlutterMacOS import Foundation -import path_provider_foundation import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/packages/diagram_viewer/windows/flutter/generated_plugins.cmake b/packages/diagram_viewer/windows/flutter/generated_plugins.cmake index b93c4c30..3ad69c61 100644 --- a/packages/diagram_viewer/windows/flutter/generated_plugins.cmake +++ b/packages/diagram_viewer/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES)