Skip to content

feat(thumb): update thumbnail plugin - #137

Open
renefloor wants to merge 12 commits into
mainfrom
feat/update-thumbnail-plugin
Open

feat(thumb): update thumbnail plugin#137
renefloor wants to merge 12 commits into
mainfrom
feat/update-thumbnail-plugin

Conversation

@renefloor

@renefloor renefloor commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Submit a pull request

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

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

WhatsApp Image 2026-07-23 at 11 59 39 WhatsApp Image 2026-07-23 at 12 05 32 WhatsApp Image 2026-07-23 at 12 07 15 WhatsApp Image 2026-07-23 at 13 20 02 WhatsApp Image 2026-07-23 at 13 24 31 image

Summary by CodeRabbit

  • New Features
    • Expanded thumbnail generation to macOS, Windows, and Linux with JPEG/PNG/WebP where supported.
    • Added authenticated remote video headers support where available (not on Windows).
  • Bug Fixes
    • Native errors now surface as typed platform exceptions with clearer failure details.
    • Fixed an iOS crash when thumbnail generation could return unexpected results.
  • Breaking Changes
    • thumbnailFiles now throws if any thumbnail fails.
    • thumbnailPath now throws ArgumentError when a file path is provided for multiple videos.
  • Documentation
    • Updated README with platform requirements and format/headers limitations.
  • Tests
    • Added/expanded plugin smoke and integration tests for thumbnail output validation.

renefloor and others added 9 commits July 22, 2026 13:34
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>
@renefloor
renefloor requested a review from a team as a code owner July 23, 2026 11:27
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This 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.

Changes

Stream thumbnail platform expansion

Layer / File(s) Summary
Typed messaging and Dart integration
packages/stream_thumbnail/pigeons/*, packages/stream_thumbnail/lib/src/*, packages/stream_thumbnail/test/*, melos.yaml, packages/stream_thumbnail/pubspec.yaml
Defines typed thumbnail requests and host APIs, replaces manual method-channel plumbing, and updates tests to mock generated APIs.
Android and iOS native migration
packages/stream_thumbnail/android/*, packages/stream_thumbnail/ios/*, packages/stream_thumbnail/macos/*
Adds generated messaging and native thumbnail generation with asynchronous data/file responses, format encoding, and structured errors.
Linux backend
packages/stream_thumbnail/linux/*
Adds FFmpeg-based decoding, scaling, JPEG/PNG/WebP encoding, file persistence, asynchronous responses, and plugin registration.
Windows backend and runners
packages/stream_thumbnail/windows/*, packages/stream_thumbnail/example/windows/*
Adds Media Foundation/WIC thumbnail processing, typed host API wiring, Windows plugin registration, and a Flutter Win32 runner.
Example projects and validation
packages/stream_thumbnail/example/*, .github/workflows/*, .github/actions/*, packages/stream_thumbnail/README.md, packages/stream_thumbnail/CHANGELOG.md
Adds native example projects, platform configuration, CI builds, integration smoke tests, bootstrap automation, and platform documentation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: xsahil03x

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
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning It covers CLA, change summary, and screenshots, but omits the required Linear ticket and the template's table format. Add the Linear ticket (FLU-...), optional GitHub issue, and format the screenshots section as the required Before/After table.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.87% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the thumbnail plugin refactor and platform expansion.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/update-thumbnail-plugin

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 51.12%. Comparing base (0abeef5) to head (89e619a).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...ges/stream_thumbnail/lib/src/stream_thumbnail.dart 83.33% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0abeef5 and 17e74e8.

⛔ Files ignored due to path filters (11)
  • packages/stream_thumbnail/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved is excluded by !**/Package.resolved
  • packages/stream_thumbnail/example/macos/Runner.xcworkspace/contents.xcworkspacedata is excluded by !**/*.xcworkspace/contents.xcworkspacedata
  • packages/stream_thumbnail/example/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved is excluded by !**/Package.resolved
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png is excluded by !**/*.png
  • packages/stream_thumbnail/example/windows/runner/resources/app_icon.ico is excluded by !**/*.ico
📒 Files selected for processing (82)
  • .github/workflows/stream_thumbnail_native_builds.yml
  • melos.yaml
  • packages/stream_thumbnail/CHANGELOG.md
  • packages/stream_thumbnail/README.md
  • packages/stream_thumbnail/android/src/main/kotlin/io/getstream/stream_thumbnail/Messages.g.kt
  • packages/stream_thumbnail/android/src/main/kotlin/io/getstream/stream_thumbnail/StreamThumbnailPlugin.kt
  • packages/stream_thumbnail/example/.metadata
  • packages/stream_thumbnail/example/integration_test/plugin_smoke_test.dart
  • packages/stream_thumbnail/example/ios/Runner.xcodeproj/project.pbxproj
  • packages/stream_thumbnail/example/linux/.gitignore
  • packages/stream_thumbnail/example/linux/CMakeLists.txt
  • packages/stream_thumbnail/example/linux/flutter/CMakeLists.txt
  • packages/stream_thumbnail/example/linux/flutter/generated_plugin_registrant.cc
  • packages/stream_thumbnail/example/linux/flutter/generated_plugin_registrant.h
  • packages/stream_thumbnail/example/linux/flutter/generated_plugins.cmake
  • packages/stream_thumbnail/example/linux/runner/CMakeLists.txt
  • packages/stream_thumbnail/example/linux/runner/main.cc
  • packages/stream_thumbnail/example/linux/runner/my_application.cc
  • packages/stream_thumbnail/example/linux/runner/my_application.h
  • packages/stream_thumbnail/example/macos/.gitignore
  • packages/stream_thumbnail/example/macos/Flutter/Flutter-Debug.xcconfig
  • packages/stream_thumbnail/example/macos/Flutter/Flutter-Release.xcconfig
  • packages/stream_thumbnail/example/macos/Runner.xcodeproj/project.pbxproj
  • packages/stream_thumbnail/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • packages/stream_thumbnail/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  • packages/stream_thumbnail/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • packages/stream_thumbnail/example/macos/Runner/AppDelegate.swift
  • packages/stream_thumbnail/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
  • packages/stream_thumbnail/example/macos/Runner/Base.lproj/MainMenu.xib
  • packages/stream_thumbnail/example/macos/Runner/Configs/AppInfo.xcconfig
  • packages/stream_thumbnail/example/macos/Runner/Configs/Debug.xcconfig
  • packages/stream_thumbnail/example/macos/Runner/Configs/Release.xcconfig
  • packages/stream_thumbnail/example/macos/Runner/Configs/Warnings.xcconfig
  • packages/stream_thumbnail/example/macos/Runner/DebugProfile.entitlements
  • packages/stream_thumbnail/example/macos/Runner/Info.plist
  • packages/stream_thumbnail/example/macos/Runner/MainFlutterWindow.swift
  • packages/stream_thumbnail/example/macos/Runner/Release.entitlements
  • packages/stream_thumbnail/example/macos/RunnerTests/RunnerTests.swift
  • packages/stream_thumbnail/example/pubspec.yaml
  • packages/stream_thumbnail/example/windows/.gitignore
  • packages/stream_thumbnail/example/windows/CMakeLists.txt
  • packages/stream_thumbnail/example/windows/flutter/CMakeLists.txt
  • packages/stream_thumbnail/example/windows/flutter/generated_plugins.cmake
  • packages/stream_thumbnail/example/windows/runner/CMakeLists.txt
  • packages/stream_thumbnail/example/windows/runner/Runner.rc
  • packages/stream_thumbnail/example/windows/runner/flutter_window.cpp
  • packages/stream_thumbnail/example/windows/runner/flutter_window.h
  • packages/stream_thumbnail/example/windows/runner/main.cpp
  • packages/stream_thumbnail/example/windows/runner/resource.h
  • packages/stream_thumbnail/example/windows/runner/runner.exe.manifest
  • packages/stream_thumbnail/example/windows/runner/utils.cpp
  • packages/stream_thumbnail/example/windows/runner/utils.h
  • packages/stream_thumbnail/example/windows/runner/win32_window.cpp
  • packages/stream_thumbnail/example/windows/runner/win32_window.h
  • packages/stream_thumbnail/ios/stream_thumbnail.podspec
  • packages/stream_thumbnail/ios/stream_thumbnail/Package.swift
  • packages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/Messages.g.swift
  • packages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.m
  • packages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.swift
  • packages/stream_thumbnail/ios/stream_thumbnail/Sources/stream_thumbnail/include/stream_thumbnail/StreamThumbnailPlugin.h
  • packages/stream_thumbnail/lib/src/messages.g.dart
  • packages/stream_thumbnail/lib/src/stream_thumbnail_method_channel.dart
  • packages/stream_thumbnail/linux/CMakeLists.txt
  • packages/stream_thumbnail/linux/include/stream_thumbnail/stream_thumbnail_plugin.h
  • packages/stream_thumbnail/linux/pigeon/messages.g.cc
  • packages/stream_thumbnail/linux/pigeon/messages.g.h
  • packages/stream_thumbnail/linux/stream_thumbnail_plugin.cc
  • packages/stream_thumbnail/macos/stream_thumbnail.podspec
  • packages/stream_thumbnail/macos/stream_thumbnail/Package.swift
  • packages/stream_thumbnail/macos/stream_thumbnail/Sources/stream_thumbnail/Messages.g.swift
  • packages/stream_thumbnail/macos/stream_thumbnail/Sources/stream_thumbnail/StreamThumbnailPlugin.swift
  • packages/stream_thumbnail/pigeons/messages.dart
  • packages/stream_thumbnail/pubspec.yaml
  • packages/stream_thumbnail/test/stream_thumbnail_test.dart
  • packages/stream_thumbnail/windows/.gitignore
  • packages/stream_thumbnail/windows/CMakeLists.txt
  • packages/stream_thumbnail/windows/include/stream_thumbnail/stream_thumbnail_plugin_c_api.h
  • packages/stream_thumbnail/windows/pigeon/messages.g.cpp
  • packages/stream_thumbnail/windows/pigeon/messages.g.h
  • packages/stream_thumbnail/windows/stream_thumbnail_plugin.cpp
  • packages/stream_thumbnail/windows/stream_thumbnail_plugin.h
  • packages/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

Comment thread packages/stream_thumbnail/example/integration_test/plugin_smoke_test.dart Outdated
Comment thread packages/stream_thumbnail/example/integration_test/plugin_smoke_test.dart Outdated
Comment thread packages/stream_thumbnail/linux/stream_thumbnail_plugin.cc
Comment thread packages/stream_thumbnail/linux/stream_thumbnail_plugin.cc
Comment thread packages/stream_thumbnail/windows/stream_thumbnail_plugin.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 17e74e8 and 70b8b52.

⛔ Files ignored due to path filters (1)
  • packages/stream_thumbnail/example/assets/sample_video.mp4 is excluded by !**/*.mp4
📒 Files selected for processing (7)
  • .github/actions/bootstrap/action.yml
  • .github/workflows/stream_thumbnail_native_builds.yml
  • packages/stream_thumbnail/example/integration_test/plugin_smoke_test.dart
  • packages/stream_thumbnail/example/pubspec.yaml
  • packages/stream_thumbnail/linux/stream_thumbnail_plugin.cc
  • packages/stream_thumbnail/windows/stream_thumbnail_plugin.cpp
  • packages/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

Comment on lines +18 to +23
- 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 }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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()}")
PY

Repository: 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.

Comment thread .github/workflows/stream_thumbnail_native_builds.yml
_futures[callId]?.completeError(value);
} else {
_futures[callId]?.complete(value);
ThumbnailFormat _wireFormat(StreamThumbnailFormat format) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove the StreamThumbnailFormat enum? or maybe rename the generated one?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 70b8b52 and 89e619a.

📒 Files selected for processing (3)
  • packages/stream_thumbnail/CHANGELOG.md
  • packages/stream_thumbnail/lib/src/stream_thumbnail.dart
  • packages/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

Comment on lines +46 to +50
// 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))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants