Skip to content

Commit 5dfcda0

Browse files
authored
update migration docs (#2555)
1 parent 8000c79 commit 5dfcda0

File tree

6 files changed

+518
-4
lines changed

6 files changed

+518
-4
lines changed

migrations/redesign/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ class MyCustomButton extends StatelessWidget {
126126
| Reaction Picker / Reactions | [reaction_picker.md](reaction_picker.md) |
127127
| Image CDN & Thumbnails | [image_cdn.md](image_cdn.md) |
128128
| Message Widget & Message List | [message_widget.md](message_widget.md) |
129+
| Message Composer | [message_composer.md](message_composer.md) |
130+
| Unread Indicator | [unread_indicator.md](unread_indicator.md) |
131+
| Reaction List & Detail Sheet | [reaction_list.md](reaction_list.md) |
132+
| Audio Waveform Theme | [audio_theme.md](audio_theme.md) |
129133

130134
## Need Help?
131135

migrations/redesign/audio_theme.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Audio Waveform Theme Migration Guide
2+
3+
This guide covers the migration for the audio waveform theming changes in the Stream Chat Flutter SDK design refresh.
4+
5+
---
6+
7+
## Table of Contents
8+
9+
- [Overview](#overview)
10+
- [What Changed](#what-changed)
11+
- [New Theming Approach](#new-theming-approach)
12+
- [Migration Checklist](#migration-checklist)
13+
14+
---
15+
16+
## Overview
17+
18+
The audio waveform theme types and the `StreamAudioWaveform` / `StreamAudioWaveformSlider` widgets have moved from `stream_chat_flutter` to `stream_core_flutter`. The widgets are re-exported via `stream_chat_flutter` so import paths remain unchanged, but theming is no longer done through `StreamChatThemeData`.
19+
20+
---
21+
22+
## What Changed
23+
24+
| Item | Before | After |
25+
|------|--------|-------|
26+
| `StreamAudioWaveformTheme` | Defined in `stream_chat_flutter` | Moved to `stream_core_flutter`; no longer in `StreamChatThemeData` |
27+
| `StreamAudioWaveformSliderTheme` | Defined in `stream_chat_flutter` | Moved to `stream_core_flutter`; no longer in `StreamChatThemeData` |
28+
| `StreamAudioWaveform` widget | In `stream_chat_flutter` | Re-exported from `stream_core_flutter` via `stream_chat_flutter` |
29+
| `StreamAudioWaveformSlider` widget | In `stream_chat_flutter` | Re-exported from `stream_core_flutter` via `stream_chat_flutter` |
30+
| Theming entry point | `StreamChatThemeData.audioWaveformTheme` / `.audioWaveformSliderTheme` | `StreamTheme` (via `MaterialApp.theme.extensions`) |
31+
32+
---
33+
34+
## New Theming Approach
35+
36+
Audio waveform theming is now part of `StreamTheme` from `stream_core_flutter`. Configure it by adding `StreamTheme` as a theme extension to your `MaterialApp`:
37+
38+
**Before:**
39+
```dart
40+
StreamChat(
41+
client: client,
42+
streamChatThemeData: StreamChatThemeData(
43+
audioWaveformTheme: StreamAudioWaveformThemeData(
44+
waveColor: Colors.blue,
45+
playedWaveColor: Colors.blueAccent,
46+
),
47+
audioWaveformSliderTheme: StreamAudioWaveformSliderThemeData(
48+
thumbColor: Colors.blue,
49+
),
50+
),
51+
child: ...,
52+
)
53+
```
54+
55+
**After:**
56+
```dart
57+
MaterialApp(
58+
theme: ThemeData(
59+
extensions: [
60+
StreamTheme(
61+
brightness: Brightness.light,
62+
// Audio waveform theming is now part of StreamTheme's component themes.
63+
// Refer to StreamThemeData for available audio waveform properties.
64+
),
65+
],
66+
),
67+
home: StreamChat(client: client, child: ...),
68+
)
69+
```
70+
71+
> **Note:** If no `StreamTheme` extension is provided, a default theme is automatically derived from `Theme.of(context).brightness`.
72+
73+
---
74+
75+
## Migration Checklist
76+
77+
- [ ] Remove any `StreamChatThemeData.audioWaveformTheme` usages
78+
- [ ] Remove any `StreamChatThemeData.audioWaveformSliderTheme` usages
79+
- [ ] Move audio waveform color / style customizations into a `StreamTheme` extension on `MaterialApp`
80+
- [ ] Import paths for `StreamAudioWaveform` and `StreamAudioWaveformSlider` remain the same (`package:stream_chat_flutter/stream_chat_flutter.dart`)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Message Composer Migration Guide
2+
3+
This guide covers the migration for the message composer components in the Stream Chat Flutter SDK design refresh.
4+
5+
---
6+
7+
## Table of Contents
8+
9+
- [Overview](#overview)
10+
- [StreamMessageInput](#streammessageinput)
11+
- [StreamChatMessageComposer (new)](#streamchatmessagecomposer-new)
12+
- [Migration Checklist](#migration-checklist)
13+
14+
---
15+
16+
## Overview
17+
18+
There are two distinct composer components with different responsibilities:
19+
20+
| Component | Responsibility |
21+
|-----------|---------------|
22+
| `StreamMessageInput` | Full-featured widget: handles sending, editing, attachments, autocomplete, mentions, commands, OG previews, voice recording flow, etc. |
23+
| `StreamChatMessageComposer` | UI-only component: renders the composer layout using design system primitives. No business logic. |
24+
25+
`StreamMessageInput` wraps `StreamChatMessageComposer` for its visual layer. If you are using `StreamMessageInput` today, it remains the right choice — it is not deprecated. `StreamChatMessageComposer` exists for cases where you want to build your own message-sending logic and use the new design system UI.
26+
27+
---
28+
29+
## StreamMessageInput
30+
31+
`StreamMessageInput` handles all message composition logic. The only breaking change in this redesign is a parameter rename.
32+
33+
### Breaking Change: `hideSendAsDm` renamed to `canAlsoSendToChannelFromThread` (logic inverted)
34+
35+
| Old | New |
36+
|-----|-----|
37+
| `hideSendAsDm: true` | `canAlsoSendToChannelFromThread: false` |
38+
| `hideSendAsDm: false` (old default) | `canAlsoSendToChannelFromThread: true` (new default) |
39+
40+
The logic is **inverted**: the old parameter hid the "also send to channel" checkbox when `true`; the new parameter **shows** it when `true`.
41+
42+
**Before:**
43+
```dart
44+
StreamMessageInput(
45+
hideSendAsDm: true, // hide the "also send to channel" checkbox
46+
)
47+
```
48+
49+
**After:**
50+
```dart
51+
StreamMessageInput(
52+
canAlsoSendToChannelFromThread: false, // hide the checkbox
53+
)
54+
```
55+
56+
> **Note:** `canAlsoSendToChannelFromThread` defaults to `true`, matching the old default of showing the checkbox when inside a thread.
57+
58+
---
59+
60+
## StreamChatMessageComposer (new)
61+
62+
`StreamChatMessageComposer` is a pure UI component from the new design system. It renders the composer layout but contains no message-sending logic — your code is responsible for wiring up the controller and callbacks.
63+
64+
Use this when you want the new design system visuals with custom business logic. If you want the full out-of-the-box experience (send, edit, attachments, mentions, commands, etc.), use `StreamMessageInput` instead.
65+
66+
### Constructor Parameters
67+
68+
| Parameter | Type | Default | Description |
69+
|-----------|------|---------|-------------|
70+
| `onSendPressed` | `VoidCallback` | **required** | Called when the send button is pressed |
71+
| `controller` | `StreamMessageInputController?` | `null` | Controller for the input; created internally if not provided |
72+
| `onAttachmentButtonPressed` | `VoidCallback?` | `null` | Called when the attachment button is pressed |
73+
| `isPickerOpen` | `bool` | `false` | Whether the inline attachment picker is currently open |
74+
| `focusNode` | `FocusNode?` | `null` | Focus node for the text field |
75+
| `currentUserId` | `String?` | `null` | Current user's ID |
76+
| `placeholder` | `String` | `''` | Placeholder text for the input field |
77+
| `audioRecorderController` | `StreamAudioRecorderController?` | `null` | Enables the voice recording UI when provided |
78+
| `sendVoiceRecordingAutomatically` | `bool` | `false` | Sends the voice recording immediately on finish |
79+
| `feedback` | `AudioRecorderFeedback` | `const AudioRecorderFeedback()` | Haptic/audio feedback callbacks for the recording flow |
80+
| `canAlsoSendToChannel` | `bool` | `false` | Shows the "also send to channel" checkbox (used in threads) |
81+
82+
### Sub-components
83+
84+
The layout is composed of named default sub-widgets that can be replaced via the `StreamComponentFactory`:
85+
86+
| Sub-component | Description |
87+
|---------------|-------------|
88+
| `DefaultMessageComposerLeading` | Left side of the composer row (e.g., attachment button) |
89+
| `DefaultMessageComposerTrailing` | Right side of the composer row (e.g., send/mic button) |
90+
| `DefaultMessageComposerInputLeading` | Left side inside the input area |
91+
| `DefaultMessageComposerInputTrailing` | Right side inside the input area |
92+
| `DefaultMessageComposerInputHeader` | Header above the input (e.g., reply/edit preview) |
93+
94+
### Customization via Component Factory
95+
96+
To replace the entire composer UI, provide a builder for `MessageComposerProps` in your `StreamComponentFactory`:
97+
98+
```dart
99+
StreamComponentFactory(
100+
builders: StreamComponentBuilders(
101+
extensions: streamChatComponentBuilders(
102+
messageComposer: (context, props) => MyCustomComposer(props: props),
103+
),
104+
),
105+
child: ...,
106+
)
107+
```
108+
109+
---
110+
111+
## Migration Checklist
112+
113+
- [ ] Rename `hideSendAsDm` to `canAlsoSendToChannelFromThread` in all `StreamMessageInput` usages and invert the value
114+
- [ ] If adopting `StreamChatMessageComposer` directly, wire up your own send/attachment logic via `onSendPressed` and `onAttachmentButtonPressed`
115+
- [ ] Move any composer UI customizations to `StreamComponentFactory`
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Reaction List Migration Guide
2+
3+
This guide covers the new reaction list controller, view, and detail sheet introduced in the Stream Chat Flutter SDK design refresh.
4+
5+
---
6+
7+
## Table of Contents
8+
9+
- [StreamReactionListController](#streamreactionlistcontroller)
10+
- [StreamReactionListView](#streamreactionlistview)
11+
- [ReactionDetailSheet](#reactiondetailsheet)
12+
- [Migration Checklist](#migration-checklist)
13+
14+
---
15+
16+
## StreamReactionListController
17+
18+
`StreamReactionListController` is a new controller in `stream_chat_flutter_core` for fetching and paginating reactions for a message. It extends `PagedValueNotifier<String?, Reaction>`, following the same pattern as `StreamChannelListController` and other list controllers.
19+
20+
### Constructor
21+
22+
```dart
23+
StreamReactionListController({
24+
required StreamChatClient client,
25+
required String messageId,
26+
Filter? filter,
27+
SortOrder<Reaction>? sort,
28+
int limit = 25, // defaultReactionPagedLimit
29+
})
30+
```
31+
32+
| Parameter | Type | Default | Description |
33+
|-----------|------|---------|-------------|
34+
| `client` | `StreamChatClient` | **required** | The Stream chat client |
35+
| `messageId` | `String` | **required** | ID of the message to load reactions for |
36+
| `filter` | `Filter?` | `null` | Query filter; supports fields `type`, `user_id`, `created_at` |
37+
| `sort` | `SortOrder<Reaction>?` | `null` | Sort order; only `created_at` is backend-supported (`ReactionSortKey.createdAt`) |
38+
| `limit` | `int` | `25` | Page size |
39+
40+
### Methods
41+
42+
| Method | Description |
43+
|--------|-------------|
44+
| `doInitialLoad()` | Loads the first page of reactions |
45+
| `loadMore(String? nextPageKey)` | Loads the next page using cursor-based pagination |
46+
| `refresh({bool resetValue = true})` | Reloads from the beginning; resets active filter/sort to constructor values when `resetValue` is `true` |
47+
48+
### Runtime Filter / Sort Changes
49+
50+
You can update `filter` and `sort` at runtime (e.g., when the user taps a reaction-type tab) and then call `doInitialLoad()` to reload:
51+
52+
```dart
53+
controller.filter = Filter.equal('type', 'like');
54+
controller.doInitialLoad();
55+
```
56+
57+
### Basic Usage
58+
59+
```dart
60+
final controller = StreamReactionListController(
61+
client: StreamChat.of(context).client,
62+
messageId: message.id,
63+
sort: const [SortOption.desc(ReactionSortKey.createdAt)],
64+
);
65+
66+
await controller.doInitialLoad();
67+
```
68+
69+
---
70+
71+
## StreamReactionListView
72+
73+
`StreamReactionListView` is a new widget in `stream_chat_flutter` that renders a paginated list of reactions using a `StreamReactionListController`.
74+
75+
### Constructor
76+
77+
```dart
78+
StreamReactionListView({
79+
required StreamReactionListController controller,
80+
required StreamReactionListViewIndexedWidgetBuilder itemBuilder,
81+
PagedValueScrollViewIndexedWidgetBuilder<Reaction>? separatorBuilder,
82+
WidgetBuilder? emptyBuilder,
83+
WidgetBuilder? loadingBuilder,
84+
Widget Function(BuildContext, StreamChatError)? errorBuilder,
85+
int loadMoreTriggerIndex = 3,
86+
// Standard ListView params: scrollDirection, reverse, scrollController,
87+
// primary, physics, shrinkWrap, padding, cacheExtent, etc.
88+
})
89+
```
90+
91+
| Parameter | Type | Required | Description |
92+
|-----------|------|----------|-------------|
93+
| `controller` | `StreamReactionListController` | yes | Provides and paginates the reaction data |
94+
| `itemBuilder` | `StreamReactionListViewIndexedWidgetBuilder` | yes | Builds each reaction item |
95+
| `separatorBuilder` | `PagedValueScrollViewIndexedWidgetBuilder<Reaction>?` | no | Builds separators between items (defaults to `SizedBox.shrink`) |
96+
| `emptyBuilder` | `WidgetBuilder?` | no | Widget shown when there are no reactions |
97+
| `loadingBuilder` | `WidgetBuilder?` | no | Widget shown during initial load |
98+
| `errorBuilder` | `Widget Function(BuildContext, StreamChatError)?` | no | Widget shown on error |
99+
| `loadMoreTriggerIndex` | `int` | no | How many items from the end to trigger the next page load (default: 3) |
100+
101+
### Usage
102+
103+
```dart
104+
StreamReactionListView(
105+
controller: controller,
106+
itemBuilder: (context, reactions, index) {
107+
final reaction = reactions[index];
108+
return ListTile(
109+
leading: Text(reaction.type),
110+
title: Text(reaction.user?.name ?? ''),
111+
);
112+
},
113+
)
114+
```
115+
116+
---
117+
118+
## ReactionDetailSheet
119+
120+
`ReactionDetailSheet` replaces the old `MessageReactionsModal`. It shows a bottom sheet with the total reaction count, emoji filter chips per reaction type, and a scrollable list of reactors using `StreamReactionListController` internally.
121+
122+
### Showing the Sheet
123+
124+
Use the static `show` method — the constructor is private:
125+
126+
```dart
127+
final action = await ReactionDetailSheet.show(
128+
context: context,
129+
message: message,
130+
initialReactionType: 'like', // optional: pre-select a reaction type
131+
);
132+
```
133+
134+
`show` returns a `MessageAction?`:
135+
- `SelectReaction` — if the user picks or removes a reaction
136+
- `null` — if the sheet is dismissed without selection
137+
138+
### Parameters of `show`
139+
140+
| Parameter | Type | Required | Description |
141+
|-----------|------|----------|-------------|
142+
| `context` | `BuildContext` | yes | Build context |
143+
| `message` | `Message` | yes | The message whose reactions to display |
144+
| `initialReactionType` | `String?` | no | Pre-selects this reaction type chip when the sheet opens |
145+
146+
### Migration from `MessageReactionsModal`
147+
148+
**Before:**
149+
```dart
150+
showDialog(
151+
context: context,
152+
builder: (_) => MessageReactionsModal(message: message),
153+
);
154+
```
155+
156+
**After:**
157+
```dart
158+
await ReactionDetailSheet.show(
159+
context: context,
160+
message: message,
161+
);
162+
```
163+
164+
> **Note:** `ReactionDetailSheet` is displayed as a `DraggableScrollableSheet` (snapping between 50% and full height) and supports cursor-based pagination for large reaction lists.
165+
166+
---
167+
168+
## Migration Checklist
169+
170+
- [ ] Replace `MessageReactionsModal` with `ReactionDetailSheet.show()`
171+
- [ ] Use `StreamReactionListController` to load/paginate reactions programmatically
172+
- [ ] Use `StreamReactionListView` with a `StreamReactionListController` for custom reaction list UIs
173+
- [ ] For runtime reaction-type filtering, set `controller.filter` and call `controller.doInitialLoad()`

0 commit comments

Comments
 (0)