r/FlutterDev • • 2h ago

Discussion Animated GIFs/WebPs ignore cacheWidth in Flutter. Here’s why, and an engine PR to fix it

Thumbnail
github.com
4 Upvotes

If you display animated GIFs or WebPs with cacheWidth, cacheHeight or ResizeImage, the resize is silently ignored: every frame is still decoded and uploaded at full size. A 1000×1000 GIF shown at 200×200 costs about 4 MB per uploaded frame; with the resize honored it would be about 160 KB. This is #90804 (open since 2021), and #137668 for animated WebP.
Why it happens
In the engine, ImageDescriptor::instantiateCodec passes the target size only to the single-frame codec. Images with more than one frame go to MultiFrameCodec, which never receives it.
Why it’s not a one-line fix
Animated frames aren’t independent images. Most frames are drawn on top of earlier ones, each with its own rect, blending and disposal (keep, clear to background, restore previous), all in full-canvas coordinates. Skia can decode GIF/WebP frames directly at a smaller size, but an emulation of the engine’s frame logic on top of Skia’s real decoders showed that doing so with the engine’s single cached frame gives wrong pixels at frame edges in some files (1px transparent slivers).
The fix
Composite at full size exactly as today, then resize only the finished frame, with the same bilinear filter Flutter already uses for still images, before uploading it. Every frame you get is today’s frame, downscaled. It applies to GIF, animated WebP and APNG on the native backends (Skia and Impeller), with no API changes: cacheWidth and ResizeImage simply start working. The CPU buffer used for compositing stays full size, as today.
Status
PR: https://github.com/flutter/flutter/pull/194615. It’s waiting for review, and CI hasn’t run yet. Web (CanvasKit/Skwasm) isn’t covered.
Until it lands
Resize animated images before they reach the app, on your server or by converting them to animated WebP or video at the size you display.
Feedback on the approach or the C++ is very welcome. If this affects your app, a 👍 on #90804 is more helpful than “+1” comments on the PR.


r/FlutterDev • • 3h ago

3rd Party Service Stackyard: See every SDK and toolchain on your machine, which projects use each version, and what's safe to remove.Free and open source, for Windows and macOS.

2 Upvotes

Version managers like FVM, nvm, pyenv and SDKMAN are great at installing versions. None of them tells you that you have six Flutter SDKs, three Android NDKs and a 13 GB emulator you haven't started in a year. Stackyard does.

It shows every SDK, toolchain and framework version on your computer, which projects use each one, and what's safe to remove. Then it fixes what's wrong with one click, and nothing is deleted without you seeing it first.

Features

  • Set up in a minute. On first launch Stackyard finds the folders where your projects live, shows how many projects each holds, and lets you add more.
  • One window for every tech. A sidebar entry appears only for techs found on your machine.
  • Get tools. A marketplace of SDKs and CLIs (Flutter, Android command-line tools, Node.js, Python, Java, .NET, Go, Rust, Deno, Bun, Gradle, and the Angular, Expo, NestJS, Firebase, Vercel, Ionic, Nx, TypeScript, pnpm and Yarn CLIs). Every version is listed from the publisher's own release feed. Downloads come straight from the publisher and are checked against their published hash. Before installing, you choose the folder and which environment variables to set (PATH, JAVA_HOME, GOROOT…): your user variables or everyone's on Windows, a marked block in ~/.zprofile on macOS. Installed versions can be made the default or removed later, which cleans up their variables too.
  • Knows who uses what. It reads .fvmrc, .nvmrc, package.json, gradle-wrapper.properties, build.gradle, local.properties, .python-version, global.json and more across your project folders.
  • Problems come with a fix button. Missing versions a project needs, two setups fighting over a folder, a broken JAVA_HOME: each is explained in plain words, with a button that fixes it. You never type a command.
  • Environment doctor. Finds JAVA_HOME / ANDROID_HOME pointing at folders that are gone, dead and duplicate PATH entries (it saves a backup first), and a Java that's too new or too old for a Flutter app's Gradle and Android Gradle Plugin.
  • Project cleanup. Shows the node_modules, build, .dart_tool, .gradle, Pods and other rebuildable folders in your projects, with a one-click clean for projects you haven't touched in months.
  • Emulator manager. Start, cold boot, wipe data, delete snapshots or delete each Android emulator, with its size and when it last ran.
  • Simulators (macOS). Every iOS, watchOS, tvOS and visionOS simulator with its size and last start: start, shut down, erase or delete it. The Xcode page shows each simulator runtime (often 8 GB each), which simulators use it, and Xcode's rebuildable caches.
  • Progress you can see. Every install, removal and fix runs in Activity with its live output and a real progress bar. Cancel stops it cleanly, without leaving half a download behind.
  • Safe removal. Things go to the Recycle Bin / Trash by default, or you can choose to delete permanently. Installed programs are removed with their own uninstaller. Links are removed as links; what they point to is never touched. You see every step before it runs, and a spinner wherever work is happening.
  • Runs in the background. Closing the window keeps Stackyard in the system tray (Windows) or menu bar (macOS). It checks your setup daily or weekly and notifies you only when there's something new. It can start at sign-in.
  • Move your setup. Export your toolchain versions to a file and import it on another computer to install what's missing.
  • Never edits your projects. It doesn't change a project's pinned versions, because that can break builds.
  • Native feel. Windows 11 Fluent design with Mica and your accent color; on macOS, the glass sidebar and motion of a Mac app. A Glass slider sets how much of your desktop shows through.

r/FlutterDev • • 11h ago

Article Two devices disagreeing caused most of my Flutter app's bugs (Drift + Supabase, local-first)

1 Upvotes

Sync was the hardest part of my Flutter app by far. Most of my bugs were around auth, migrations, reconnecting, offline changes and getting two devices to agree.

The app is Personal Planner, a free planner for Linux, Android, Windows and macOS: hour-by-hour Day view with timers, daily and weekly reviews, a consistency heatmap, Experiments and an Inbox. First Flutter project for me.

How it's put together:

- **Local first.** Drift on SQLite is the everyday store. Moving a block, finishing a task, starting a timer or opening an old day never waits on a server

- **A local outbox.** Anything that still needs to sync waits there until the connection is back, and a sync engine pushes it to Supabase PostgreSQL

- **Supabase Auth** for sign-in, Riverpod for state

- **Provisioning.** A usable Supabase project needs the right schema, migrations, access rules and client config, and doing that by hand is painful. So a Cloudflare Worker does it from inside the app: connects your Supabase account, reuses a compatible project or creates one, applies the migrations and verifies the schema. Setup has several steps, so Durable Objects keep its state in between. After that the Worker is out of the picture and the app talks to Supabase directly

Two things I hit on desktop:

- On Windows, setup failed with CERTIFICATE_VERIFY_FAILED. Windows didn't trust the root certificate needed to reach Supabase, and updating Windows plus \certutil -generateSSTFromWU roots.sst` fixed it`

- The \com.personalplanner.personalplanner://` link scheme isn't registered on Windows and macOS yet, so the sign-up confirmation email and the provisioning authorization links can't open the app there. Email and password sign-in works fine`

Windows and macOS are built and smoke-tested on GitHub Actions. Both are unsigned, and macOS is CI-only because I don't own a Mac.

Download: https://github.com/Karthikshabari/PersonalPlanner/releases

Code: https://github.com/Karthikshabari/PersonalPlanner (the README has the architecture diagram). Dev here.


r/FlutterDev • • 13h ago

Plugin I got tired of trying different ways to run GGUF models on Android, so I built Kiln

1 Upvotes

I tried quite a few libraries to run GGUF models on Android, but none really matched my expectations.

Apple's ecosystem feels more unified for on-device ML, with Core ML and MLX. On Android, the options and guidelines feel more scattered, and getting different models running without extra hassle isn't always straightforward.

So I decided to build Kiln, which is a C inference layer built on top of llama.cpp, with language bindings for Flutter, Kotlin, React Native, and more. It's too easy now to run a model with kiln.

The goal is simple: make running local AI models on mobile less painful.

It's open source, and I'd love to hear what other developers think or what could be improved.

It's available in pub dev too: kiln_flutter

GitHub: https://github.com/RaihanulHaque/kiln