feat(thumb): update thumbnail plugin - #137
Conversation
Android acknowledged method calls immediately with result.success(true) and delivered the real result later via a separate reverse invocation correlated by a callId, while iOS returned results directly. Align Android to the standard held-Result pattern used by iOS and web, and delete the callId/reverse-invoke machinery from both the Kotlin and Dart sides. Also fixes two bugs surfaced by this cleanup: iOS returned nil instead of an error when thumbnail generation failed, crashing the Dart side on a null cast; and Android's batch thumbnailFiles silently dropped videos that failed instead of surfacing an error. Native batch generation is removed in favor of a single Dart-side loop (used by all platforms), which now fails fast on the first error. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n Swift Replace the hand-rolled MethodChannel with Pigeon-generated, type-safe messaging (pigeons/messages.dart), and rewrite the iOS plugin in Swift (previously Objective-C). - Android and iOS now implement the generated StreamThumbnailHostApi interface/protocol instead of dispatching on raw method names and stringly-typed argument maps. Android keeps Phase 1's executor + main-thread-callback pattern; iOS keeps its AVAssetImageGenerator frame extraction and endian-aware libwebp encoding. - StreamThumbnailFormat now travels the wire as a real Pigeon enum instead of a magic .index int. - Web is untouched, since Pigeon doesn't support it. - The public Dart API (StreamThumbnail.thumbnailData/thumbnailFile/ thumbnailFiles) is unchanged. - Tests now mock the generated host API directly via mocktail. - Added a generate:pigeon melos script (wired into generate:all), following the existing --file-exists convention used for icons/barrels. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add macOS as a supported platform alongside Android/iOS/web, reusing the same AVAssetImageGenerator + libwebp approach as iOS. - Pigeon can't share one generated Swift file between iOS and macOS packages: SwiftPM rejects a target whose source path escapes its own package root, so `pigeons/messages.dart` no longer fixes `swiftOut` in its ConfigurePigeon annotation. melos.yaml's generate:pigeon now runs pigeon twice (once per Darwin platform) with an explicit --swift_out override instead. - macOS gets its own StreamThumbnailPlugin.swift (adapted from iOS's: Cocoa/FlutterMacOS instead of UIKit/Flutter, NSBitmapImageRep instead of UIImage for jpeg/png) rather than sharing source across platform folders, since Flutter's plugin loader hardcodes each platform's SPM package to live under its own <platform>/<name>/ directory anyway. - Fixed a real, unrelated pre-existing bug found while getting this working: SwiftPM resolution was broken for iOS too (not just macOS) due to this machine's Flutter config and stale Xcode caches; fixed globally and verified both platforms' SPM builds now succeed. - Added a permanent integration_test suite that actually launches the built macOS app and generates real jpeg/png/webp thumbnails from a remote video, verified via magic-byte assertions. Running it surfaced a genuine bug: the default macOS entitlements only grant outbound network *server* access, not *client*, so the sandboxed app couldn't fetch remote video URLs at all. Added com.apple.security.network.client to both entitlements files. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add Windows as a supported platform, decoding via Media Foundation (IMFSourceReader, forcing RGB32 output so MF's own video processor handles YUV->RGB conversion) and encoding JPEG/PNG via WIC — both are part of the Windows SDK, no external dependency needed for this phase. - WebP is not yet supported on Windows: it throws a typed UNSUPPORTED_FORMAT error instead of silently producing the wrong format or crashing. Windows has no OS-native WebP encoder, and thumblr (the reference implementation) doesn't solve this either. Revisit with vcpkg manifest mode if it's actually needed later. - `headers` (custom HTTP headers for authenticated remote videos) aren't applied on Windows either: IMFSourceReader has no simple equivalent to AVFoundation's header options or Android's setDataSource(uri, headers). Documented as a known limitation. - pigeons/messages.dart now also generates a C++ HostApi (stream_thumbnail_windows namespace) alongside the existing Dart/Kotlin/Swift outputs, from the same schema. - Async work runs on a detached std::thread per call, with CoInitializeEx/CoUninitialize scoped to that thread (COM apartment state is per-thread) — MFStartup/MFShutdown stay in the plugin constructor/destructor since Media Foundation only needs one process-wide init. IMPORTANT: this sandbox has no Windows toolchain (MSVC/Windows SDK), so unlike the Kotlin/Swift work in prior commits, this C++ has not been compiled. It was written carefully against Pigeon's actual generated C++ interface, a working reference decode implementation (thumblr, fetched from GitHub), and standard WIC encode APIs, but it needs a real build on Windows (or future CI) before being trusted in production. Dart-side verification (analyze/format/test) passes clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add Linux as a supported platform, decoding via FFmpeg (avformat_open_input/avcodec) and encoding JPEG/PNG via FFmpeg's own image encoders (mjpeg/png) and WebP via libwebp. Unlike Windows, Linux supports both StreamThumbnailFormat.webp and headers (FFmpeg's http(s) protocol has a simple "headers" AVDictionary option), so it has full parity with Android/iOS/macOS. - pigeons/messages.dart now also generates a GObject HostApi (module: '' to avoid Pigeon's default doubled-prefix naming, e.g. StreamThumbnailStreamThumbnailHostApi) alongside the Dart/Kotlin/ Swift/C++ outputs, from the same schema. - Async work runs via GLib's GTask (g_task_run_in_thread + g_task_return_pointer/g_task_propagate_pointer), the standard GObject pattern for background work whose result needs to make it back to a reply that must happen through FlBasicMessageChannel. - linux/CMakeLists.txt links libavcodec/libavformat/libavutil/ libswscale/libwebp via pkg-config; building requires the corresponding "-dev" packages on the build machine. Verification: this sandbox is macOS, but unlike the Windows work, Homebrew already had ffmpeg and libwebp installed here, and both are real cross-platform C libraries with headers available on this machine (unlike Windows' Win32/COM/WIC headers, which don't exist outside Windows). So the core decode/encode logic and the GLib/GObject/ GTask async plumbing were both compiled and *run* standalone against real headers before being wired into the actual plugin: - The decode/encode core was compiled with clang++ against Homebrew's ffmpeg/webp and actually run against a real remote video, producing genuine, valid JPEG/PNG/WebP files (verified with `file`/`sips`) at the correct scaled dimensions. Also confirmed FFmpeg's custom-headers option works. - The GTask async plumbing was compiled and run against Homebrew's glib, and this caught a real bug: g_autoptr() on the Pigeon-generated response-handle type doesn't compile, since Pigeon doesn't declare a G_DEFINE_AUTOPTR_CLEANUP_FUNC for it. Fixed by using a plain pointer with an explicit g_object_unref() instead. Only the thin flutter_linux.h/GTK-specific registration glue (message channel wiring, FlValue header-map extraction) remains unverified here, since that API only exists on a real Linux build — everything else was verified more thoroughly than the Windows work in the prior commit. Dart-side verification (analyze/format/test) passes clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a workflow building packages/stream_thumbnail/example on every platform the plugin supports: android, ios, macos, windows, linux, and web. This repo's existing CI only ever ran Dart-level analyze/test on ubuntu-latest, so none of the native platform code (especially the Windows/Linux work from the last few commits, and macOS) has ever actually built in CI. - Path-filtered to packages/stream_thumbnail/** (and the workflow file itself), unlike this repo's other workflows which run unconditionally on every PR — native builds are slow and costly enough, especially on macOS/Windows runners, to justify scoping this one. - linux installs the FFmpeg/GTK/libwebp dev packages via apt before building. - macos/windows/linux explicitly enable desktop support via `flutter config` first. Validated with actionlint and a plain YAML parse; an actual GitHub Actions run is the only way to confirm the builds themselves succeed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Xcode 27 beta enforces a macOS deployment target floor of 12.0, rejecting the example app's Flutter-default 10.15 with: "The macOS deployment target 'MACOSX_DEPLOYMENT_TARGET' is set to 10.15, but the range of supported deployment target versions is 12.0 to 27.0.x." This isn't sandbox-specific: hit this on a real machine too, so it's worth fixing rather than working around locally. Only the example app's own target changes — the plugin's declared minimum stays at 10.15 in macos/stream_thumbnail.podspec and macos/stream_thumbnail/Package.swift, since a consuming app's deployment target can always be higher than what the plugin requires. Verified with a real `flutter build macos --debug` (succeeds, no CLI override needed now) and the integration_test suite (all 3 still pass: real jpeg/png/webp thumbnails generated from a live video). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same class of issue as the macOS deployment target fix: Xcode 27 beta enforces a higher minimum than the Flutter-default 13.0 the example's iOS project was scaffolded with. Confirmed fixed on a real machine hitting this directly. Only the example app's own target changes — the plugin's declared minimum stays at 13.0 in ios/stream_thumbnail.podspec and ios/stream_thumbnail/Package.swift, since a consuming app's deployment target can always be higher than what the plugin requires. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR adds typed Pigeon messaging, native thumbnail generation for Linux, macOS, and Windows, Android/iOS channel migration, cross-platform example runners, integration tests, documentation updates, and CI builds for all Flutter targets. ChangesStream thumbnail platform expansion
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Dart
participant PigeonHostApi
participant NativeBackend
participant PlatformEncoder
Dart->>PigeonHostApi: Send typed ThumbnailRequest
PigeonHostApi->>NativeBackend: Dispatch thumbnailData or thumbnailFile
NativeBackend->>PlatformEncoder: Decode, scale, and encode frame
PlatformEncoder-->>NativeBackend: Encoded bytes
NativeBackend-->>PigeonHostApi: Return bytes, file path, or error
PigeonHostApi-->>Dart: Resolve result or throw PlatformException
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #137 +/- ##
==========================================
+ Coverage 44.59% 51.12% +6.53%
==========================================
Files 179 185 +6
Lines 7252 7579 +327
==========================================
+ Hits 3234 3875 +641
+ Misses 4018 3704 -314 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/stream_thumbnail/example/integration_test/plugin_smoke_test.dart`:
- Around line 8-45: Update the three thumbnailData format tests to use a bundled
local video fixture instead of the externally hosted bee.mp4 URL, preserving
their JPEG, PNG, and WebP byte-header assertions. Add or retain a separate
opt-in test for remote URL coverage rather than requiring network access in the
hermetic tests.
- Around line 33-44: Update the thumbnailData WebP integration test to avoid
running on Windows unless WebP encoding is supported there. Gate or otherwise
conditionally skip the test based on the platform capabilities, while preserving
the existing WebP byte and header assertions on supported platforms.
In `@packages/stream_thumbnail/linux/stream_thumbnail_plugin.cc`:
- Around line 380-424: Add a catch-all exception handler to both
ThumbnailDataThread and ThumbnailFileThread after their existing
ThumbnailException handlers, converting any unexpected std::exception into the
result’s error fields so the worker returns a Flutter-side error instead of
terminating the process. Preserve the existing ThumbnailException code/message
handling.
- Around line 92-107: Update DecodeFrame before avformat_open_input to set the
FFmpeg protocol_whitelist option to http,https, adding file only when video
starts with file:// or /. Preserve the existing headers option and ensure the
whitelist is passed through options so unsupported protocols and subprotocols
are rejected.
In `@packages/stream_thumbnail/windows/stream_thumbnail_plugin.cpp`:
- Around line 370-394: Update ThumbnailData and ThumbnailFile to avoid detached
threads: track each in-flight request, synchronize plugin teardown before
StreamThumbnailPlugin::~StreamThumbnailPlugin() calls MFShutdown(), and join all
worker threads. Dispatch each result callback through Flutter’s platform-thread
task runner rather than invoking the Pigeon result directly from the worker
thread, while preserving existing success and ThumbnailException handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2bf43bec-f265-4a44-9de3-b9a47bf408d0
⛔ Files ignored due to path filters (11)
packages/stream_thumbnail/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedis excluded by!**/Package.resolvedpackages/stream_thumbnail/example/macos/Runner.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedatapackages/stream_thumbnail/example/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolvedis excluded by!**/Package.resolvedpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.pngis excluded by!**/*.pngpackages/stream_thumbnail/example/windows/runner/resources/app_icon.icois excluded by!**/*.ico
📒 Files selected for processing (82)
.github/workflows/stream_thumbnail_native_builds.ymlmelos.yamlpackages/stream_thumbnail/CHANGELOG.mdpackages/stream_thumbnail/README.mdpackages/stream_thumbnail/android/src/main/kotlin/io/getstream/stream_thumbnail/Messages.g.ktpackages/stream_thumbnail/android/src/main/kotlin/io/getstream/stream_thumbnail/StreamThumbnailPlugin.ktpackages/stream_thumbnail/example/.metadatapackages/stream_thumbnail/example/integration_test/plugin_smoke_test.dartpackages/stream_thumbnail/example/ios/Runner.xcodeproj/project.pbxprojpackages/stream_thumbnail/example/linux/.gitignorepackages/stream_thumbnail/example/linux/CMakeLists.txtpackages/stream_thumbnail/example/linux/flutter/CMakeLists.txtpackages/stream_thumbnail/example/linux/flutter/generated_plugin_registrant.ccpackages/stream_thumbnail/example/linux/flutter/generated_plugin_registrant.hpackages/stream_thumbnail/example/linux/flutter/generated_plugins.cmakepackages/stream_thumbnail/example/linux/runner/CMakeLists.txtpackages/stream_thumbnail/example/linux/runner/main.ccpackages/stream_thumbnail/example/linux/runner/my_application.ccpackages/stream_thumbnail/example/linux/runner/my_application.hpackages/stream_thumbnail/example/macos/.gitignorepackages/stream_thumbnail/example/macos/Flutter/Flutter-Debug.xcconfigpackages/stream_thumbnail/example/macos/Flutter/Flutter-Release.xcconfigpackages/stream_thumbnail/example/macos/Runner.xcodeproj/project.pbxprojpackages/stream_thumbnail/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plistpackages/stream_thumbnail/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcschemepackages/stream_thumbnail/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plistpackages/stream_thumbnail/example/macos/Runner/AppDelegate.swiftpackages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.jsonpackages/stream_thumbnail/example/macos/Runner/Base.lproj/MainMenu.xibpackages/stream_thumbnail/example/macos/Runner/Configs/AppInfo.xcconfigpackages/stream_thumbnail/example/macos/Runner/Configs/Debug.xcconfigpackages/stream_thumbnail/example/macos/Runner/Configs/Release.xcconfigpackages/stream_thumbnail/example/macos/Runner/Configs/Warnings.xcconfigpackages/stream_thumbnail/example/macos/Runner/DebugProfile.entitlementspackages/stream_thumbnail/example/macos/Runner/Info.plistpackages/stream_thumbnail/example/macos/Runner/MainFlutterWindow.swiftpackages/stream_thumbnail/example/macos/Runner/Release.entitlementspackages/stream_thumbnail/example/macos/RunnerTests/RunnerTests.swiftpackages/stream_thumbnail/example/pubspec.yamlpackages/stream_thumbnail/example/windows/.gitignorepackages/stream_thumbnail/example/windows/CMakeLists.txtpackages/stream_thumbnail/example/windows/flutter/CMakeLists.txtpackages/stream_thumbnail/example/windows/flutter/generated_plugins.cmakepackages/stream_thumbnail/example/windows/runner/CMakeLists.txtpackages/stream_thumbnail/example/windows/runner/Runner.rcpackages/stream_thumbnail/example/windows/runner/flutter_window.cpppackages/stream_thumbnail/example/windows/runner/flutter_window.hpackages/stream_thumbnail/example/windows/runner/main.cpppackages/stream_thumbnail/example/windows/runner/resource.hpackages/stream_thumbnail/example/windows/runner/runner.exe.manifestpackages/stream_thumbnail/example/windows/runner/utils.cpppackages/stream_thumbnail/example/windows/runner/utils.hpackages/stream_thumbnail/example/windows/runner/win32_window.cpppackages/stream_thumbnail/example/windows/runner/win32_window.hpackages/stream_thumbnail/ios/stream_thumbnail.podspecpackages/stream_thumbnail/ios/stream_thumbnail/Package.swiftpackages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/Messages.g.swiftpackages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.mpackages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.swiftpackages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/include/stream_thumbnail/StreamThumbnailPlugin.hpackages/stream_thumbnail/lib/src/messages.g.dartpackages/stream_thumbnail/lib/src/stream_thumbnail_method_channel.dartpackages/stream_thumbnail/linux/CMakeLists.txtpackages/stream_thumbnail/linux/include/stream_thumbnail/stream_thumbnail_plugin.hpackages/stream_thumbnail/linux/pigeon/messages.g.ccpackages/stream_thumbnail/linux/pigeon/messages.g.hpackages/stream_thumbnail/linux/stream_thumbnail_plugin.ccpackages/stream_thumbnail/macos/stream_thumbnail.podspecpackages/stream_thumbnail/macos/stream_thumbnail/Package.swiftpackages/stream_thumbnail/macos/stream_thumbnail/Sources/stream_thumbnail/Messages.g.swiftpackages/stream_thumbnail/macos/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.swiftpackages/stream_thumbnail/pigeons/messages.dartpackages/stream_thumbnail/pubspec.yamlpackages/stream_thumbnail/test/stream_thumbnail_test.dartpackages/stream_thumbnail/windows/.gitignorepackages/stream_thumbnail/windows/CMakeLists.txtpackages/stream_thumbnail/windows/include/stream_thumbnail/stream_thumbnail_plugin_c_api.hpackages/stream_thumbnail/windows/pigeon/messages.g.cpppackages/stream_thumbnail/windows/pigeon/messages.g.hpackages/stream_thumbnail/windows/stream_thumbnail_plugin.cpppackages/stream_thumbnail/windows/stream_thumbnail_plugin.hpackages/stream_thumbnail/windows/stream_thumbnail_plugin_c_api.cpp
💤 Files with no reviewable changes (3)
- packages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/include/stream_thumbnail/StreamThumbnailPlugin.h
- packages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.m
- packages/stream_thumbnail/ios/stream_thumbnail/Package.swift
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/actions/bootstrap/action.yml:
- Around line 18-23: Update the “Install Flutter” step’s subosito/flutter-action
reference from the mutable v2 tag to a reviewed, immutable full commit SHA,
while preserving its existing inputs and enabling dependency automation to
manage future updates.
In @.github/workflows/stream_thumbnail_native_builds.yml:
- Around line 20-22: Update the push path filter in the stream thumbnail native
builds workflow to include .github/workflows/stream_thumbnail_native_builds.yml,
matching the existing pull-request path filter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ace2fcbf-cb87-4545-ae96-fcf01732b478
⛔ Files ignored due to path filters (1)
packages/stream_thumbnail/example/assets/sample_video.mp4is excluded by!**/*.mp4
📒 Files selected for processing (7)
.github/actions/bootstrap/action.yml.github/workflows/stream_thumbnail_native_builds.ymlpackages/stream_thumbnail/example/integration_test/plugin_smoke_test.dartpackages/stream_thumbnail/example/pubspec.yamlpackages/stream_thumbnail/linux/stream_thumbnail_plugin.ccpackages/stream_thumbnail/windows/stream_thumbnail_plugin.cpppackages/stream_thumbnail/windows/stream_thumbnail_plugin.h
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/stream_thumbnail/windows/stream_thumbnail_plugin.h
- packages/stream_thumbnail/windows/stream_thumbnail_plugin.cpp
- packages/stream_thumbnail/linux/stream_thumbnail_plugin.cc
| - name: Install Flutter | ||
| uses: subosito/flutter-action@v2 | ||
| with: | ||
| cache: true | ||
| cache-key: flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }} | ||
| channel: ${{ inputs.flutter-channel }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== action.yml target =="
cat -n .github/actions/bootstrap/action.yml
echo
echo "== workflow/action references in repo (short summary) =="
rg -n "uses:\s*[^#]+@[A-Za-z0-9./_-]+" .github -g '*.yml' -g '*.yaml' || true
echo
echo "== existing full SHA usage in .github =="
python3 - <<'PY'
import pathlib, re
patterns = []
for p in pathlib.Path('.github').glob('**/*.yml'):
for p2 in pathlib.Path('.github').glob('**/*.yaml'):
pass
for p in list(pathlib.Path('.github').glob('**/*.yml')) + list(pathlib.Path('.github').glob('**/*.yaml')):
for i,line in enumerate(p.read_text(errors='replace').splitlines(),1):
m = re.search(r"\b([0-9a-fA-F]{40})\b", line)
if m:
print(f"{p}:{i}:{line.strip()}")
PYRepository: GetStream/stream-core-flutter
Length of output: 4565
Pin the third-party action to a full commit SHA.
subosito/flutter-action@v2 is a mutable tag, so this workflow can execute unreviewed or compromised code if the tag is moved. Pin an immutable full commit SHA and update it through dependency automation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/actions/bootstrap/action.yml around lines 18 - 23, Update the
“Install Flutter” step’s subosito/flutter-action reference from the mutable v2
tag to a reviewed, immutable full commit SHA, while preserving its existing
inputs and enabling dependency automation to manage future updates.
| _futures[callId]?.completeError(value); | ||
| } else { | ||
| _futures[callId]?.complete(value); | ||
| ThumbnailFormat _wireFormat(StreamThumbnailFormat format) { |
There was a problem hiding this comment.
Should we remove the StreamThumbnailFormat enum? or maybe rename the generated one?
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/stream_thumbnail/lib/src/stream_thumbnail.dart`:
- Around line 46-50: Standardize the exact-file detection around thumbnailPath
so every platform uses the same dot-aware extension rule: require the path
extension to equal the target extension, not merely a suffix match. Update the
Dart check and the corresponding Android, iOS, and macOS native implementations,
preserving the existing multi-video overwrite prevention behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: bb50635e-4d53-4d45-a646-44f073ce96fa
📒 Files selected for processing (3)
packages/stream_thumbnail/CHANGELOG.mdpackages/stream_thumbnail/lib/src/stream_thumbnail.dartpackages/stream_thumbnail/test/stream_thumbnail_test.dart
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/stream_thumbnail/CHANGELOG.md
- packages/stream_thumbnail/test/stream_thumbnail_test.dart
| // Every platform treats a `thumbnailPath` that already ends in the target | ||
| // extension as the exact file to write to. With more than one video that | ||
| // points the whole batch at a single path, so the requests overwrite each | ||
| // other and the returned files all describe the same bytes. | ||
| if (videos.length > 1 && thumbnailPath != null && thumbnailPath.endsWith(_extensionFor(imageFormat))) { |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Standardize file-extension detection across platforms.
This check is not actually cross-platform consistent: Android uses endsWith(ext), while iOS/macOS use URL.pathExtension == ext. For example, /tmp/cachejpg is treated as an exact file on Android but as a directory on iOS/macOS, while Dart rejects it for every platform. Use one dot-aware extension rule in Dart and all native implementations to avoid platform-dependent batch behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/stream_thumbnail/lib/src/stream_thumbnail.dart` around lines 46 -
50, Standardize the exact-file detection around thumbnailPath so every platform
uses the same dot-aware extension rule: require the path extension to equal the
target extension, not merely a suffix match. Update the Dart check and the
corresponding Android, iOS, and macOS native implementations, preserving the
existing multi-video overwrite prevention behavior.
Submit a pull request
CLA
Description of the pull request
This PR updates the existing iOS and android logic and also adds macos, windows and linux platforms.
Noticeable change:
On Android previously it was able to fetch a list of thumbnails, but on iOS and web it looped through the list on the dart side. Now on Android it has the same behaviour.
It adds pigeon to make sure the methodchannels don't break.
Tested on all platforms.
Screenshots / Videos
Summary by CodeRabbit
headerssupport where available (not on Windows).thumbnailFilesnow throws if any thumbnail fails.thumbnailPathnow throwsArgumentErrorwhen a file path is provided for multiple videos.