NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #1139 most downloaded on pub.dev
Stream Design System for Flutter and cross-SDK utilities that depend on Flutter.
Last release 8 days ago
30 Sep 2026
Ships fairly regularly
a new release about every 4 weeks
Nearly every release is documented
notes for 8 of 8 stable releases
Nothing withdrawn
no release was ever pulled
6 months old
8 releases · first in 2026
One column per month.
Added the lowBandwidthFill icon.
lowBandwidthFill icon.StreamErrorBadge.style, taking a StreamErrorBadgeStyle — .error.warning — and StreamErrorBadge.showBorder.StreamErrorBadgeTheme and StreamErrorBadgeThemeData, carrying aStreamColorScheme.backgroundOnElevation and borderOnElevation, forStreamAvatarSize.xlPlus (64px), StreamAvatarSize.xxxl (104px), StreamAvatarGroupSize.xxxl (104px), StreamOnlineIndicatorSize.xxxl (24px) and StreamBadgeCountSize.xl (56px).StreamTextTheme.numericXxl, used by StreamBadgeCountSize.xl.lerp on theme styles carrying a WidgetStateBorderSide throwing a castlerp on a theme style whose border side is set on one end only. It nowStreamBadgeNotification with a child swallowing taps on the badge;StreamColorScheme.accentWarning — and borderWarning, which defaults to it —#F26D10 → #F6BF57 light, #FA922B → #FCD579Published to pub.dev: https://pub.dev/packages/stream_core_flutter/versions/0.5.2
Added a fix_data.yaml , so deprecated members can be migrated with dart fix --apply .
StreamColorScheme.backgroundOverlayDarkStrong, the design system's background/core/overlay-dark-strong token. A heavier version of backgroundOverlayDark, for content that has to stay legible on top of arbitrary imagery or video.StreamReactions.onReactionLongPressed, reporting the long-pressed StreamReactionsItem — or null for the cluster/overflow chip. When null, the chips register no long-press gesture, leaving it to an ancestor.StreamSplitButton, in the two variants the design covers —StreamSplitButtonVariant.regular and .destructive. Each variant carriesStreamSplitButtonStyle on StreamSplitButtonThemeData, so the twoblurFill, boltFill,cameraFlipFill, captionFill, caretDown, caretUp, copyFill,darkMode, emojiAddFill, fullBlurFill, fullscreenFill, gridFill,gridPixelFill, language, leftToRight, lightMode, menu,messageBubblesFill, moreHorizontal, moreVerticalFill, noSignFill,phoneDownFill, pinFill, pipFill, presentDesktopFill,presentMobileFill, questionCircleFill, raiseHandFill,recordLibraryFill, recordingFill, recordingStopFill, settings,settingsFill, slidersFill, starFill, statsFill, unpinFill,userAddFill, userRemoveFill, usersFill, verifiedFill, videoOffFill,voiceOffFill, and xmarkSmall.gridDefaultFill,livestreamFill, phoneFill, speakerBottomFill, speakerLeftFill,speakerRightFill, and speakerTopFill.fix_data.yaml, so deprecated members can be migrated withdart fix --apply.>=3.44.0 and the Dart SDK to ^3.12.0.StreamIcons.more / StreamIconData.more in favour ofmoreHorizontal, which keeps the original artwork. A vertical variant is nowmoreVerticalFill. Run dart fix --apply to migrate.Published to pub.dev: https://pub.dev/packages/stream_core_flutter/versions/0.5.1
CurrentPlatform.debugCurrentPlatformOverride, which points CurrentPlatform at a chosen PlatformType in testsFilter.raw, a last resort for a query this package does not model. It serializes verbatim, is not validated, and cannot be evaluated locally, so matches throws for itFilterField.collectionEquality, which declares whether Filter.equal asks a collection field to hold every given element, or to hold nothing else eithernormalizeStringForSort, which folds diacritics, ligatures and case so a locally sorted list of names matches the order a query returnssortedUpsertAt, which upserts at an index the caller already has instead of searching for onesortedMerge, an O(n + m) merge for a receiver that is already sorted, which skips sorting other when it already arrives in order. Unlike merge it never re-sorts the whole result, so it stays flat as the receiver growssortedWith, a stable sort: elements the comparator calls equal keep the order they arrived in, where sorted reorders them once the list is longer than 32merge now accepts a nullable other, so a list straight off a response needs no null checkStreamWebSocketClient.optionsProvider, which builds the options asynchronously and is given the error that closed the previous attempt, within defaultOptionsTimeoutConnectionStateEmitter.settled, which completes once the connection is no longer in transitioncloseReason, cause and isReconnectable moved onto the DisconnectionSourceReads extension, which adds exception and stackTrace. cause is now StreamException?StreamWebSocketClient.optionsBuilder and WebSocketOptionsBuilder, in favour of optionsProvider and WebSocketOptionsProvider. A builder takes no arguments, so it cannot be told what closed the last attemptSystemInitiated, carrying the error, rather than ServerInitiated; both reconnectconnect awaiting a provider that never answersStreamLogHandler.console now prefixes every line of a message that spans severalFilter.equal and Filter.in_ now ask whether a collection field holds the values given, rather than comparing it with order-sensitive deep equality that no query can produceLocationCoordinate equality is now exact, where == matched within ~1.1cm and so disagreed with hashCode, Set and Map. distanceTo no longer reports 0m for points closer than that; for proximity, ask a.distanceTo(b) <= 1.meterssortedUpsert now leaves a replacement in place when it sorts to the same position, instead of moving it after the elements it ties withupdateWhere now returns the receiver when nothing matches, so an unchanged list keeps its identitysortedInsert, sortedUpsert, sortedUpsertAt and sortedMerge now assert in debug that the receiver is sorted by compare. Breaking that never threw, it quietly misplaced elementsupdateWhere and sortedMerge sorted through sorted, which reorders elements the comparator calls equal once a list is longer than 32. Both are stable nowPublished to pub.dev: https://pub.dev/packages/stream_core/versions/0.5.1
StreamColorScheme.backgroundOverlayDarkStrong, the design system's background/core/overlay-dark-strong token. A heavier version of backgroundOverlayDark, for content that has to stay legible on top of arbitrary imagery or video.StreamReactions.onReactionLongPressed, reporting the long-pressed StreamReactionsItem — or null for the cluster/overflow chip. When null, the chips register no long-press gesture, leaving it to an ancestor.StreamSplitButton, in the two variants the design covers —
StreamSplitButtonVariant.regular and .destructive. Each variant carries
its own StreamSplitButtonStyle on StreamSplitButtonThemeData, so the two
can be themed independently.blurFill, boltFill,
cameraFlipFill, captionFill, caretDown, caretUp, copyFill,
darkMode, emojiAddFill, fullBlurFill, fullscreenFill, gridFill,
gridPixelFill, language, leftToRight, lightMode, menu,
messageBubblesFill, moreHorizontal, moreVerticalFill, noSignFill,
phoneDownFill, pinFill, pipFill, presentDesktopFill,
presentMobileFill, questionCircleFill, raiseHandFill,
recordLibraryFill, recordingFill, recordingStopFill, settings,
settingsFill, slidersFill, starFill, statsFill, unpinFill,
userAddFill, userRemoveFill, usersFill, verifiedFill, videoOffFill,
voiceOffFill, and xmarkSmall.gridDefaultFill,
livestreamFill, phoneFill, speakerBottomFill, speakerLeftFill,
speakerRightFill, and speakerTopFill.fix_data.yaml, so deprecated members can be migrated with
dart fix --apply.StreamMessageAnnotation.separator, a slot between label and trailing for a punctuation mark, along with a ready-made middle dot to pass to it.StreamMessageAnnotation no longer wraps its label mid-sentence when the row is too narrow, stranding the trailing action beside the label's last line. The trailing slot now moves below the label as a whole, and the separator — which separates nothing once the two are on different lines — is dropped. A label too wide even on its own still wraps across as many lines as it needs.>=3.44.0 and the Dart SDK to ^3.12.0.StreamIcons.more / StreamIconData.more in favour of
moreHorizontal, which keeps the original artwork. A vertical variant is now
available as moreVerticalFill. Run dart fix --apply to migrate.Raised the minimum Dart SDK to ^3.12.0
^3.12.0userId parameter from UserToken.anonymous, anonymous tokens always use User.anonymousUserIdTokenManager.tokenProvider setter, use setTokenProvider insteadTokenManager.userId is now nullable, and is null until an identity is configuredUser now requires a user of type UserType.anonymous to carry User.anonymousUserId as its id. A mismatch fails to compile in a const context, and throws in debug mode otherwiseStreamWebSocketClient now takes an optionsBuilder instead of options, called once per connection attemptWebSocketOptions.connectTimeout is now a non-nullable Duration, 30 seconds by default, and is honoured: a connection that does not come up is given up on instead of waited on indefinitely. A connection that drops later is retried for you; a connect that times out is not, so call it againStreamWebSocketClient.onConnectionEstablished to onAuthenticate, now a WebSocketAuthenticator. It is handed a WsRequestSender and the StreamApiException the server closed the previous attempt with, and throws to say the credentials did not go outStreamException of four kinds — StreamApiException, StreamNetworkException, StreamAuthenticationException or StreamClientExceptionStreamException no longer takes or carries a stackTrace. A trace records where a failure was raised rather than what it was, so it travels beside the failure: on Failure, or on ServerInitiated and AuthenticationFailed for a connection that closed. Where the exception is built at the throw site, throw captures itClientException, HttpClientException and WebSocketEngineException, replaced by the kinds above. StreamDioException.exception is a StreamException, and the StreamDioExceptionExtension extension is now DioExceptionMapping, with toClientException() renamed to toStreamException()StreamWebSocketClient.send now fails with a StreamException rather than passing the engine's own error through, so a Failure that carried a StateError or a codec error now carries a StreamNetworkException or StreamClientException. The WsRequestSender handed to a WebSocketAuthenticator changed the same way, which matters where its error is propagated into AuthenticationFailedStreamWebSocketClient.send throws a StateError when nothing has connected yet, rather than reporting it through the returned ResultStreamDioException no longer defaults its stackTrace to StackTrace.current, leaving Dio to substitute the stack captured where the request was madeServerInitiated.error is typed StreamException? rather than WebSocketEngineException?TokenManager.getToken fails with a StreamAuthenticationException rather than raw errors; a failed provider's own error is preserved as cause. A provider failure that is already a StreamException, or a TimeoutException, keeps its own kind, so a load that failed at the moment stays retriableStreamApiError.isTokenExpiredError, isClientError and isRateLimitError: the conditions live on StreamErrorCode and StreamApiException as isTokenExpired, isTokenNotYetValid, isTokenSignatureInvalid, isApiKeyInvalid and isRateLimited; StreamApiError keeps only isRateLimitedStreamApiError.code is typed StreamErrorCode rather than int; construction takes StreamErrorCode(40) in place of 40, reads are unchangedAuthInterceptor extends Interceptor rather than QueuedInterceptor, so requests are no longer serialised against one anotherWebSocketConnectionState.isAutomaticReconnectionEnabled reads the error's facts: token conditions that heal, rate limits and transient network failures reconnect; refused signatures or API keys, other 4xx and unrecoverable verdicts do notResult.getOrElse, getOrDefault, recover and recoverCatching return the result's own type and no longer take a type parameter. To widen, widen the result (Result<num> widened = intResult) or use foldStreamLogger is the handle you write with and a StreamLogHandler is where records go, so Priority, MessageBuilder, Tag, IsLoggableValidator and Finder are renamed or goneLoggingInterceptor writes through the logger rather than printing, so it is silent until an app asks for records. Its logPrint is now optional, and it takes a tagAttachmentUploadTask: StreamAttachmentUploader.upload returns the running task rather than a Future, and uploadBatch returns an AttachmentUploadBatch. CancelToken and progress callbacks are gone from the public APIStreamAttachment.uploadState. Where an upload has got to lives on the task running it, not on the attachmentUploadState* classes with UploadQueued, UploadPreparing, UploadInProgress, UploadSuccess, UploadFailed and UploadCancelled, constructed directly rather than through named constructors. UploadInProgress.progress is an UploadProgress in bytes rather than a double, and UploadFailed.error is a StreamExceptionAttachmentUploadException. A failed upload carries the StreamException that stopped it, and a cancelled one a StreamNetworkException with isCancelled setOnUploadProgress and OnBatchUploadProgress callbacks along with the StreamAttachmentUploaderBatch extension. Progress arrives on AttachmentUploadTask.state and AttachmentUploadBatch.state, so it can never disagree with the lifecycleuploadBatch's maxConcurrent now defaults to 3 rather than 5UploadedAttachment compares by value rather than by identityStreamLogger, or hands a product client a StreamLogConfig carrying bothTokenManager.setTokenProvider, which points an existing manager at another user and expires the cached token; handed the identity it already has, it does nothingonTokenUpdated callback to TokenManager, invoked after every successful token loadrawValue to UserToken.anonymous, so an anonymous token can carry a JWT granting restricted access; its user_id claim must be !anonUserToken.expiresAt, from the token's exp claim, and UserToken.isExpired, which takes an optional leewayUser.anonymousUserId, the id every anonymous user hasUser.guest takes an image, which it previously droppedTokenManager.unconfigured, for a client that exists before its user does, and TokenManager.reset, which drops the configured identity and its cached tokenteams field to User classStreamDateTimeConverter, a JsonConverter for the API's DateTime fields. Accepts either an RFC3339 string (v1) or epoch nanoseconds (v2) when deserializing, and always serializes to RFC3339. Values are normalized to UTC with microsecond precisionDioException.toStreamException(), mapping a Dio failure to the StreamException it representsStreamApiException.retryAfter, the wait the server asked for, read from the Retry-After header on any error response carrying one — a 503 populates it as readily as a 429. Only the delta-seconds form is readStreamErrorCode, the API's error-code registry as named constants over int, tolerant of codes the SDK does not know yetrunApiSafely, which runs an API call and reports every failure as a StreamExceptionDisconnectionSource.connectTimeout and authenticationFailed, and isReconnectable, whether a connection closed for that reason is worth opening againDisconnectionSource.cause, the error that closed the connection, or null when the source carries nonestackTrace to ServerInitiated and AuthenticationFailed, where the failure was raised; null for a closure the server reported, which arrives as data rather than as something raisedConnectUserDetailsRequest.fromUser, which builds the details a client may send from a UserStreamWebSocketClient.dispose, which closes the connection along with events and connectionState; the client is now Disposable, and connect throws a StateError afterwardsInFlightCache, which hands concurrent callers asking for the same key the one call already in flight, and its outcome, success or failure alikeAttachmentUploadTask, one upload as an object: state carries the whole lifecycle including byte progress, result settles once and never throws, and cancel calls it off at onceAttachmentUploadBatch, which uploads several attachments under a concurrency limit, aggregates byte-weighted progress, and finishes as a sealed BatchUploadResult — BatchUploadCompleted, BatchUploadStoppedOnError or BatchUploadCancelled — carrying one outcome per attachment in input orderStreamApiError failing to decode when details is not a list of numbers, as a moderation rejection's is; such values read as emptyduration or more_info failing to decode, which lost the code with it and silently stopped the token refresh a code would have triggered. Both read as empty nowTokenManager's token cache: getToken contacted the provider on every call instead of returning the cached token, handed out a token that had already expired rather than replacing it, and cached one that finished loading after expireToken or setTokenProvider had invalidated it. A static provider is left alone, having nothing fresher to giveDynamicTokenProvider accepting a token issued for a different user than the one requestedStreamWebSocketClient no longer prints to the consoleconnect leaked the socket of a failed handshake, disconnect completed before the socket had closed, and a close that failed or found no socket reported no closure at allConnectionRecoveryHandler retrying a first connection attempt, which reconnected behind the caller of connect; only established connections are recovered nowConnectUserDetailsRequest leaves its unset fields out of the JSON it serialises, rather than sending them as nullsuser_id=!anon, rather than whatever id the TokenManager was configured withDynamicTokenProvider checks the token type before its user id, so a token of the wrong type is reported as such instead of as a mismatched userTokenManager.getToken fails when reset runs while the token is loading, and rejects a token whose user_id is not the user it was loading for; a setTokenProvider during a load still serves the caller that started itAuthInterceptor no longer refreshes a token when the manager has no identity, so the original error is surfaced, and no longer retries a request signed for a user it has since been pointed away from, which would have performed one user's request as anotherStreamWebSocketEngine.open fails when a connection is already open, rather than closing it to make roomSystemEnvironmentManager.updateEnvironment now sanitizes the passed SystemEnvironment, so an integrator can enrich the Stream client header without changing the SDK identity it reportsPublished to pub.dev: https://pub.dev/packages/stream_core/versions/0.5.0
StreamReactions.onReactionPressed, which reports the pressed StreamReactionsItem — or null for the cluster/overflow chip, which represents no single reaction. Added an optional StreamReactionsItem.key so callers can identify the pressed item.semanticsLabel to StreamAvatar, StreamAvatarGroup, and StreamAvatarStack. On StreamAvatar, null (default) drops the placeholder's initials from the semantics tree via ExcludeSemantics; a non-null value exposes it as a labeled image node. On StreamAvatarGroup / StreamAvatarStack, null composes through — each child's own semanticsLabel applies — while a non-null value collapses the group into a single labeled image node and hides children and the "+N" overflow badge.StreamColorScheme.fromSeed — builds a complete light or dark color scheme from a single brand color, optionally with a custom chrome color. When chrome is omitted it is derived from the brand hue at StreamColorScheme.neutralChroma.StreamColorSwatch.fromColor now generates shades in the HCT color space instead of HSL. Each shade takes its tone from a fixed ladder measured from the Stream design tokens, so a shade's contrast is predictable regardless of the seed's hue — seeding a light color such as yellow now yields an accent that can carry white text. Two consequences: the seed is no longer reproduced verbatim at shade 500 (it is normalized onto the ladder), and dark scales now mirror the ladder so the seed's tone lands on shade 300, matching the default dark palette.StreamScaffold — a full-page scaffold for regular or floating bars; a floating bar enlarges the body's MediaQuery.padding so scrollables inset themselves.StreamBottomNavBar and StreamBottomNavBarItem — a bottom navigation bar rendering as a docked bar or a floating pill, themeable via StreamBottomNavBarTheme. Its height is kStreamBottomNavBarHeight.StreamSafeArea — a SafeArea that insets by max(systemInset, minimum) + margin, so a pinned surface keeps a gap from the system bars. StreamSafeArea.driven animates the inset; resolveInsets returns it as a value.StreamAppBar and StreamBottomAppBar via StreamAppBarStyle.surfaceStyle / StreamBottomAppBarStyle.surfaceStyle, plus StreamBottomAppBarStyle.floatingBackgroundColor for the upward fade.StreamToolbarScope for its slots, and reports it through a resolveSurfaceStyle static so a container can match its layout.StreamToolbarButton — a toolbar action, labelled or icon-only, that takes its look from the enclosing StreamToolbarScope; pass type to override the resolved shape.StreamMediaViewer chrome now follows the ambient StreamSurfaceStyle — floating over full-bleed media, or docked with the media inset between the bars.isFloating to StreamAvatar, StreamAvatarGroup, and StreamAvatarStack, rendering a Material elevation (StreamAvatarThemeData.floatingElevation) instead of a hand-painted shadow.streamFloatingFade helper — a shared LinearGradient factory (alpha stops 0xE8/0xA8/0x40/0x00 with solid-fraction support for safe-area zones) used internally by StreamAppBar, StreamBottomNavBar, and StreamMessageComposer floating fade effects.isFloating to the default StreamButton constructor — the floating (elevated) appearance was previously reachable only through StreamButton.icon. Labelled buttons now get the same treatment: elevation for every type, plus a backgroundElevation1 fill for outline and ghost.StreamElevation — the four elevation levels of the design system as logical pixels, for passing to Material.elevation or a component theme's elevation field. Like StreamRadius and StreamSpacing it is a theme primitive: reachable as StreamTheme.elevation or context.streamElevation, overridable per theme through the StreamTheme constructor, and lerped on theme transitions. StreamElevation.none is a fixed 0 rather than a themeable level, so "flat" cannot be redefined as elevated. StreamAvatar and StreamButton now resolve their elevations from it instead of hard-coded numbers; the rendered values are unchanged.chipStyle to StreamReactionsThemeData for overriding the per-reaction chip appearance (background, size, etc.); it is merged over the default reaction chip style.StreamMessagePresentation and StreamMessageLayoutData.presentation, describing whether a message is drawn inline in the list (standard) or as a preview above a scrim (preview, e.g. the long-press message-actions modal). Read it with StreamMessageLayout.presentationOf(context), or resolve per-presentation styling through StreamMessageLayoutProperty.resolveWith. For preview, the default metadata (username, timestamp, edited, status), annotation (text, icon, trailing) and replies-label colors now resolve to StreamColorScheme.textOnAccent so they stay legible against StreamColorScheme.backgroundScrim. Also added StreamMessageLayoutData.copyWith.StreamNetworkImage now caches through a shared cache manager which, on IO platforms, is stored in its own app-scoped directory (isolated from the host app's image cache) with LRU eviction, while other platforms fall back to the library defaults.isFloating: true) now retain their pill surface (backgroundElevation1) when disabled, across all style/type combinations. Previously, outline and ghost variants fell back to transparent when disabled, losing the floating visual.StreamReactions.onPressed in favor of onReactionPressed.StreamTheme.brightness. Read colorScheme.brightness instead. The property, and the brightness parameter on copyWith and StreamTheme.raw, all keep working — for a theme built through the StreamTheme factory the value still mirrors colorScheme.brightness.Published to pub.dev: https://pub.dev/packages/stream_core_flutter/versions/0.5.0
feat(ui): composer & design-system a11y pass by @xsahil03x in #126
Full Changelog: stream_core_flutter-v0.4.0...stream_core_flutter-v0.4.1
StreamAccessibilityAutofocus — behavior-only wrapper that requests screen-reader focus on its child shortly after mount; useful for redirecting focus on route entry.StreamSemanticsAnnouncer — imperative one-shot screen-reader announcement helper.StreamSemanticsTransitionAnnouncer — observes a Listenable and dispatches transition announcements to the screen reader.labelText and helperAffinity to StreamTextInput for a floating label above the field and helper text positioned inside or outside the bordered chassis.focusNode and autofocus pass-through on StreamListTile.semanticLabel to StreamBadgeNotification, StreamFileTypeIcon, StreamStepper, StreamMessageComposerAttachment, and StreamMessageComposerMediaAttachment.excludeHeaderSemantics to StreamAppBar and StreamSheetHeader for opting out of the default heading role and route naming on the title.onVisible callback to StreamSnackbar — fires after the entrance animation completes (or synchronously when a screen reader is active).StreamButton icons picking up the host app's ElevatedButtonThemeData.iconColor instead of the button's own foregroundColor.refactor(llc)!: update Emitter architecture and implement Stream directly by @xsahil03x in #26
Full Changelog: v0.3.3...v0.4.0
Full Changelog: stream_core_flutter-v0.3.0...stream_core_flutter-v0.4.0
package:stream_core_flutter/core.dart (shared primitives for any Stream SDK) and package:stream_core_flutter/chat.dart (chat-only widgets; re-exports core.dart); the convenience barrel package:stream_core_flutter/stream_core_flutter.dart is now deprecated.StreamSnackbar and StreamSnackbarTheme — Stream-styled transient feedback snackbars with a messenger-driven queue.StreamIcons.megaphone and StreamIcons.shield (20px) to the icon set.StreamMentionType identifier for supported mention types and options for mention text customisation per type.feat(ui): Simplify icon set by @renefloor in #103
Full Changelog: stream_core_flutter-v0.2.0...stream_core_flutter-v0.3.0
StreamCoreMessageComposer, StreamMessageComposerInput, StreamMessageComposerInputField, StreamCoreMessageComposerInputTrailing, StreamVoiceRecordingButton, VoiceRecordingCallback, StreamMessageComposerInputTrailingState, and InputThemeDefaults. These composer-flow widgets now live entirely in stream_chat_flutter. The attachment widgets (StreamMessageComposerAttachment and variants) remain in this package.StreamOnlineIndicatorSize.xxl (20px) to pair with StreamAvatarSize.xxl.StreamJumpToUnreadButton component and StreamJumpToUnreadButtonTheme.StreamVideoPlayIndicator component with StreamVideoPlayIndicatorSize variants.StreamFileTypeIconSize.md and StreamFileTypeIconSize.sm variants.trailing slot to StreamMessageAnnotation, with matching trailingTextStyle/trailingTextColor on StreamMessageAnnotationStyle.StreamIntrinsicFlex, StreamIntrinsicRow, and StreamIntrinsicColumn layout primitives, extending StreamFlex with full main-axis flex behavior (Expanded, Flexible, MainAxisAlignment, MainAxisSize) and CrossAxisAlignment.baseline support while retaining cross-axis shrink-wrapping.StreamTapTargetPadding, a reusable primitive that grows a child's layout and hit-test area to a configurable minSize without changing its visual size, with a directional alignment that controls which direction the extra tap area extends into.StreamSheetHeader component and StreamSheetHeaderTheme for bottom-sheet and modal headers, with platform-aware auto-implied dismissal based on the enclosing route.StreamToolbar, a three-slot layout primitive shared by StreamAppBar, StreamBottomAppBar, and StreamSheetHeader that keeps the title geometrically centred even when leading and trailing widths differ.StreamBottomAppBar and StreamBottomAppBarTheme, the bottom counterpart to StreamAppBar with the same three-slot (leading/heading/trailing) layout, optional title + subtitle, top hairline border, SafeArea(top: false) when primary, and per-slot button style propagation.StreamMediaViewer and StreamMediaViewerTheme, a full-screen media chrome controller that composes optional header/footer chrome over an edge-to-edge child, animates the chrome in/out via showChrome, and fades to an immersive background when hidden. The theme exposes scoped appBarStyle/bottomAppBarStyle so descendant chrome bars can be tinted (e.g. light-on-dark over dark media) without touching app-wide themes.StreamSheet, StreamSheetDragHandle, StreamSheetRoute, StreamSheetTransition and the showStreamSheet helper — Stream-styled modal bottom sheets with scroll-aware drag-to-dismiss and stacking support. StreamSheet can also be used standalone outside the modal route.StreamSheetTheme and StreamSheetThemeData (StreamTheme.sheetTheme) for theming StreamSheet and modal sheets opened with showStreamSheet.StreamEmojiPickerSheet.show now resolves its background color and border radius from the ambient StreamSheetTheme so the picker visually matches other Stream-styled sheets by default.StreamLoadingSpinner now supports determinate progress via a value parameter (0.0–1.0), and renders a completion checkmark when value reaches 1.0. Omit value for the existing indeterminate spinning state.StreamCommandChip is now tappable across its whole surface, not just the × icon.StreamRemoveControl now meets the 48 dp minimum tap target by default while keeping its 20 dp visible badge anchored to the top-end corner. Exposes tapTargetSize, visualDensity, and semanticLabel, announces itself as a button to screen readers, and shows a click cursor on web/desktop when hovered.textAlignVertical to StreamTextInput (and StreamTextInputProps) for controlling the vertical alignment of the text within the input.cursorColor, cursorErrorColor, cursorWidth, cursorHeight, and cursorRadius to StreamTextInputStyle for customizing the text input cursor. cursorErrorColor is applied automatically when helperState is StreamHelperState.error. StreamMessageComposerInputField also honors these cursor properties from the theme.DefaultStreamEmoji so consumers can compose with or wrap the default emoji rendering when overriding via StreamComponentFactory.StreamMessageComposerEditMessageAttachment, a preview shown above the composer input while editing a message.StreamMessageComposerUnsupportedAttachment, a placeholder shown for attachments the client cannot render.thumbnail slot to StreamMessageComposerReplyAttachment and StreamMessageComposerEditMessageAttachment, with matching thumbnailSize/thumbnailShape/thumbnailSide theme fields.StreamMessageComposerAttachmentTheme, StreamMessageComposerEditMessageAttachmentTheme, StreamMessageComposerFileAttachmentTheme, StreamMessageComposerLinkPreviewAttachmentTheme, StreamMessageComposerMediaAttachmentTheme, StreamMessageComposerReplyAttachmentTheme, and StreamMessageComposerUnsupportedAttachmentTheme. All seven are wired into StreamTheme with matching BuildContext extensions.StreamMessageComposerAttachment, StreamMessageComposerEditMessageAttachment, StreamMessageComposerFileAttachment, StreamMessageComposerLinkPreviewAttachment, StreamMessageComposerMediaAttachment, StreamMessageComposerReplyAttachment, StreamMessageComposerUnsupportedAttachment) can now be customized via StreamComponentFactory — each exposes a matching builder slot taking its *Props configuration object.StreamTextInput stretching vertically when placed inside a parent with bounded maxHeight (e.g. AlertDialog.content, Flexible). The input now always hugs its intrinsic height.StreamTextInput content alignment so text and prefix/suffix slots are centered vertically.StreamTextInput default textCapitalization to TextCapitalization.sentences.StreamReactionPicker spacing to match the Figma specification.StreamStepper button style to match the Figma specification.StreamEmoji now pins its primary fontFamily to the platform's native emoji font (Apple Color Emoji on iOS/macOS, Segoe UI Emoji on Windows, Noto Color Emoji elsewhere) so the existing per-platform fontSize correction lines up with the font that actually renders the glyph. fontFamilyFallback is unchanged.StreamFileTypeIcon now centers its SVG inside the icon's render box, so it stays centered when given larger constraints.StreamRadius across platforms; removed platform factory, .raw(), .ios, and .android.StreamFileTypeIconSize variants: s48 → xl, s40 → lg.StreamFlex, StreamRow, and StreamColumn now default mainAxisSize to MainAxisSize.min (was MainAxisSize.max). Callers that relied on the widget expanding to fill available space must now pass mainAxisSize: MainAxisSize.max explicitly.StreamMessageAnnotation.rich and spanTextStyle/spanTextColor; use the new trailing slot instead.StreamButton API with Flutter's built-in buttons: renamed label (String?) to required child (Widget), changed icon/iconLeft/iconRight from IconData to Widget, and renamed onTap to onPressed. StreamButtonProps mirrors the same renames.StreamAppBar with a slots-based API (leading/title/subtitle/trailing) and platform-aware auto-implied leading; replaces the previous Material AppBar wrapper. Adds StreamAppBarStyle, StreamAppBarTheme, and StreamAppBarThemeData.placeholder on StreamCoreMessageComposer, StreamMessageComposerInput, and StreamMessageComposerInputField is now an optional String? (was String defaulting to '', and required on StreamMessageComposerInputField).StreamMessageTheme, StreamMessageThemeData, and StreamMessageStyle; MessageComposerReplyAttachment and MessageComposerLinkPreviewAttachment now read colors directly from StreamColorScheme.StreamMessageComposerAttachmentContainer to StreamMessageComposerAttachment to mirror the existing StreamMessageAttachment naming.StreamMessageComposerAttachment now uses shape: OutlinedBorder? and side: BorderSide? (matching StreamMessageAttachmentStyle) in place of the previous borderColor / borderRadius fields and constructor params. Added a style: constructor param taking StreamMessageComposerAttachmentThemeData? for per-instance overrides; the old backgroundColor and borderColor widget params are gone.style: per-instance override params to MessageComposerFileAttachment, MessageComposerMediaFileAttachment, MessageComposerLinkPreviewAttachment, and MessageComposerReplyAttachment. Renamed MessageComposerReplyAttachment.style (the ReplyStyle enum slot) to direction: so style: is free for the theme-data override.Stream prefix: MessageComposerFileAttachment → StreamMessageComposerFileAttachment, MessageComposerMediaFileAttachment → StreamMessageComposerMediaAttachment (also dropped the redundant "File" segment), MessageComposerLinkPreviewAttachment → StreamMessageComposerLinkPreviewAttachment, MessageComposerReplyAttachment → StreamMessageComposerReplyAttachment.ReplyStyle with StreamReplyDirection (same incoming / outgoing values) used by StreamMessageComposerReplyAttachment.direction.StreamMessageComposerLinkPreviewAttachment.media to thumbnail, and StreamMessageComposerReplyAttachment.trailing to thumbnail.StreamMessageComposerLinkPreviewAttachmentThemeData fields: mediaSize → thumbnailSize, mediaShape → thumbnailShape, mediaSide → thumbnailSide.Added macOS, Windows and Linux support, alongside the existing Android, iOS and web. macOS requires 10.15 or later. Linux needs FFmpeg and libwebp dev
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libwebp-dev.StreamThumbnailFormat.webp is not supported yet and fails with anUNSUPPORTED_FORMAT error, and headers is ignored — a remote video needingthumbnailFile and thumbnailFiles no longer take a thumbnailPath, and no longerXFile. Use XFile.saveTo to copy itXFile.readAsBytes on web.thumbnailFiles now throws if any video fails, instead of dropping it from thePlatformException with a code and message on everyException. On iOS, a failed thumbnailData used tofile:// video now resolves to the right file:file:///tmp/a%20b.mp4 used to look for a literal a%20b.mp4. macOS behaves theXFile now carries a file name, so XFile.saveTo savesclip.png instead of an unnamed file.Published to pub.dev: https://pub.dev/packages/stream_thumbnail/versions/0.2.0
Full Changelog: stream_core_flutter-v0.1.0...stream_core_flutter-v0.2.0
StreamInputTheme/StreamInputThemeData to StreamTextInputTheme/StreamTextInputThemeData with a redesigned APIStreamTheme.inputTheme to StreamTheme.textInputThemealignment and offset from StreamOnlineIndicatorThemeData (these are layout concerns, not theme)child, alignment, and offset parameters to StreamBadgeNotification for badge-over-child positioningchild, alignment, and offset parameters to StreamBadgeCount for badge-over-child positioningStreamSwitch component with platform-aware styling and style propStreamTextInput component with configurable helper text, icons, and validation statesStreamStepper component for numeric value adjustment with customizable bounds and style propStreamButtonThemeStyle with sizing, alignment, padding, and shape optionsStreamListTile with contentPadding and text style customizationchore(repo): Add workflow to publish design system gallery by @renefloor in #32
Your coding agent can read these notes before it upgrades. Set up the MCP server →