Stream Chat Flutter SDK

repository·master·Indexed 21 days ago

https://github.com/getstream/stream-chat-flutter

Official Flutter packages for Stream Chat, providing a layered SDK for building real-time chat applications. It includes stream_chat_flutter for customizable UI widgets and theming via StreamTheme, and stream_chat_flutter_core for business logic, controllers (such as StreamChannelListController), and state management without UI. The SDK supports offline capabilities, rich media, and platform-specific UI builders for mobile, web, and desktop.

Tokens
88.6K
Snippets
250
Records
353
Agent score
77%

What's inside stream-chat-flutter

  1. Summary of breaking changes in Stream Chat Flutter SDK v10.0.0

    master

    The v10.0.0 release introduces several breaking changes across multiple feature areas. Key changes include:

    • StreamChat Widget: streamChatThemeData is now themeData.
    • Attachment Picker: Transitioned to a sealed class hierarchy, a builder pattern for options, and typed result handling.
    • Reactions: New Reaction object API and requirement for explicit onReactionPicked callbacks.
    • Message UI: Updated StreamAttachmentWidgetTapCallback signature and a new sealed MessageAction hierarchy using actionsBuilder.
    • Message State & Deletion: MessageDeleteScope replaces the bool hard parameter, adding support for 'delete-for-me'.
    • File Upload: AttachmentFileUploader now requires implementing four new abstract methods.
    • Unread Threads Banner: Moved to a wrapper pattern using child, enabled, and onRefresh; onTap and minHeight have been removed.
  2. Handle slow mode behavior in the Message Composer

    master

    In the redesigned composer, slow mode is a highly visible state. When slow mode is active for the user:

    • The text input is disabled (enabled: false).
    • The trailing send button is replaced by a disabled countdown button showing the remaining seconds.
    • The placeholder displays a live countdown (e.g., Slow mode, wait 9s…).

    Precedence Note: Slow mode now has the highest precedence. If slow mode is active, its placeholder will be shown even if a command or attachment is present.

    To restore the old behavior (where the input remained editable during slow mode), you must override placeholderBuilder and provide a custom trailing component via streamChatComponentBuilders(messageComposerInputTrailing: ...).

    Localization: The default countdown text uses Translations.slowModeOnLabel(int cooldownTimeOut).

  3. Understand the MessageInputPlaceholder sealed class states

    master

    The MessageInputPlaceholder sealed class provides contextual data for different input states. When implementing placeholderBuilder, you can pattern-match on these cases to access specific metadata:

    CaseField(s)Description
    WriteMessagePlaceholderisEditing (bool)true when editing an existing message.
    SlowModePlaceholdercooldownTimeOut (int), cooldown (Duration)Remaining slow-mode cooldown.
    CommandPlaceholdercommand (String)The active command name (e.g., 'giphy', 'mute').
    AttachmentsPlaceholderattachments (List<Attachment>)The list of pending attachments.

    Note: Using a switch expression on this sealed class ensures compile-time safety; if the SDK adds new placeholder types, your code will fail to compile until you handle the new case.

  4. Handle connection recovery for manually watched channels

    master

    When StreamChatCore mounts, it sets client.recoverStateOnReconnect = false. While the SDK's built-in list controllers (like StreamChannelListController) handle their own refreshes automatically, any Channel you watch manually (outside of a list controller) will not automatically refresh on reconnection.

    To ensure manually watched channels stay up to date, you must subscribe to EventType.connectionRecovered and call channel.watch() manually.

    If you need to restore the old behavior where the client automatically recovers state, set client.recoverStateOnReconnect = true after mounting.

    late final StreamSubscription _sub;
    
    @override
    void initState() {
      super.initState();
      _sub = client.on(EventType.connectionRecovered).listen((_) {
        channel.watch();
      });
    }
    
    @override
    void dispose() {
      _sub.cancel();
      super.dispose();
    }
  5. How attachment widgets and component factories work together

    master

    The SDK uses a Props + Component Factory pattern for all attachment widgets. This architecture decouples the public widget from its rendering logic, allowing for global customization.

    1. Public Widget (e.g., StreamImageAttachment): A thin wrapper that uses a StreamComponentFactory to render the attachment.
    2. Props Class (e.g., StreamImageAttachmentProps): A configuration object that holds all parameters. Most constructor parameters are now internally forwarded to this object.
    3. Default Implementation (e.g., DefaultStreamImageAttachment): The standard built-in UI.

    You can globally replace the rendering of specific attachment types by providing custom builders to the StreamComponentFactory via StreamComponentBuilders.

    StreamComponentFactory(
      builders: StreamComponentBuilders(
        extensions: streamChatComponentBuilders(
          imageAttachment: (context, props) => MyCustomImageAttachment(props: props),
          fileAttachment: (context, props) => MyCustomFileAttachment(props: props),
        ),
      ),
      child: ...
    )
  6. Understand the Stream Chat Flutter Package Architecture

    master

    The redesigned UI components are split into two distinct layers to separate product-agnostic UI primitives from chat-specific logic:

    1. stream_core_flutter: Contains product-agnostic primitives like avatars, badges, buttons, sheets, app bars, and theming tokens. These classes do not depend on chat-domain models like Channel, Message, or User.
    2. stream_chat_flutter: Contains chat-domain wrappers. These components take chat models and delegate the actual visual rendering to the primitives in the core layer.

    Note on Imports: Most core types are re-exported from stream_chat_flutter. You can usually continue using package:stream_chat_flutter/stream_chat_flutter.dart for most imports, even if a type has been moved to the core layer.

  7. Understand the difference between StreamMessageComposer and StreamChatMessageInput

    master

    The SDK provides two distinct composer components with different responsibilities:

    1. StreamMessageComposer: A full-featured widget that handles all business logic, including sending, editing, attachments, autocomplete, mentions, commands, OG previews, and the voice recording flow. Use this for standard chat implementations.
    2. StreamChatMessageInput: A UI-only component that renders the composer layout using design system primitives. It contains no business logic. Use this if you want to implement your own custom message-sending logic while maintaining the new design system's visual style.

    StreamMessageComposer wraps StreamChatMessageInput for its visual layer and is not deprecated.

  8. Understand the SDK architecture and layers

    master

    The Stream Chat Flutter SDK is organized into distinct layers. Higher-level packages build upon lower-level ones. Understanding this hierarchy helps you choose the right package for your needs:

    1. stream_chat: The Low-Level Client (LLC). A pure Dart package with no Flutter dependencies. It handles core logic like Message, Channel, and User. It is suitable for CLIs, servers, or non-Flutter clients.
    2. stream_chat_persistence: An optional sibling layer that provides Drift-backed disk caching.
    3. stream_chat_flutter_core: Contains Flutter-specific business logic but does not include UI components.
    4. stream_chat_flutter: The full UI component library for Flutter.
    5. stream_chat_localizations: Provides internationalization (i18n) support for the UI components.

    Key Principle: Convenience APIs should reside in the layer they are simplifying. Do not push high-level convenience methods down into lower layers.

    stream_chat                        # Pure Dart, no Flutter dependency
    ├── stream_chat_persistence        # Optional Drift-backed disk cache
    └── stream_chat_flutter_core       # Flutter business logic, no UI
        └── stream_chat_flutter        # Full UI component library
            └── stream_chat_localizations   # i18n for UI
  9. Customize StreamMessageComposerInput using the split API

    master

    In v10.0.0, StreamMessageComposerInput was split into two distinct roles. If you want to customize only the text field area (the center content), you must now target StreamMessageComposerInputCenter using the messageComposerInputCenter builder key. Targeting StreamMessageComposerInput will replace the entire input row (including leading/trailing elements).

    // To replace only the text field area:
    // Use StreamMessageComposerInputCenter and the 'messageComposerInputCenter' builder key.
    
    // To replace the entire input row:
    // Use StreamMessageComposerInput and the 'messageComposerInput' builder key.
  10. Manage list state with Controllers

    master

    List-view state (pagination, filtering, refreshing) is managed by controllers that extend PagedValueNotifier<Key, Value> from stream_chat_flutter_core.

    Lifecycle Rule: Callers (the users of the widgets) own the controller lifecycle. You are responsible for creating, passing, and disposing of the controller. Widgets should generally not construct controllers internally unless they are strictly internal to the widget's logic.

    // Examples of available controllers:
    // - StreamChannelListController
    // - StreamMessageListController
    // - StreamUserListController
    // - StreamMemberListController
    // - StreamThreadListController
    // - StreamDraftListController
    // - StreamPollController
    // - StreamMessageReminderListController