Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/stream_chat_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- Fixed `StreamMessageComposer` polling the audio recorder ten times a second while no recording is in progress, including when voice recording is disabled.
- Fixed `StreamMessageComposer`'s send button looking enabled on an empty message when voice recording is off, and showing the microphone instead of send for a staged poll.
- Fixed the attachment picker showing an empty commands tab in channels without commands.
- Fixed dialogs and bottom sheets opened below `StreamChat` keeping the old colors when the app switched between light and dark mode.

## 10.5.0

Expand Down
14 changes: 12 additions & 2 deletions packages/stream_chat_flutter/lib/src/stream_chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,18 @@ class StreamChatState extends State<StreamChat> {
final theme = widget.themeData ?? StreamChatThemeData();
child = StreamChatTheme(data: theme, child: child);

final streamTheme = StreamTheme.of(context);
child = Theme(data: Theme.of(context).withExtension(streamTheme), child: child);
// Only when the app has not registered a StreamTheme itself: dialogs and
// sheets opened below this point copy the Theme once and would stop
// following the app's brightness (flutter/flutter#106642).
//
// The key keeps the subtree's state when the Theme comes or goes, such as
// when only one of the app's light and dark themes registers a StreamTheme.
child = KeyedSubtree(key: GlobalObjectKey(this), child: child);
final materialTheme = Theme.of(context);
if (materialTheme.extension<StreamTheme>() == null) {
final streamTheme = StreamTheme.of(context);
child = Theme(data: materialTheme.withExtension(streamTheme), child: child);
}
Comment thread
renefloor marked this conversation as resolved.

if (widget.componentBuilders case final builders?) {
child = StreamComponentFactory(builders: builders, child: child);
Expand Down
73 changes: 73 additions & 0 deletions packages/stream_chat_flutter/test/src/stream_chat_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,79 @@ void main() {
expect(captured, same(sibling));
},
);

testWidgets(
'a dialog opened below StreamChat follows the app theme when the '
'brightness changes',
(tester) async {
tester.platformDispatcher.platformBrightnessTestValue = Brightness.light;
addTearDown(tester.platformDispatcher.clearPlatformBrightnessTestValue);

final mockClient = MockClient();
final light = StreamTheme.light();
final dark = StreamTheme.dark();
StreamTheme? captured;

await tester.pumpWidget(
MaterialApp(
theme: ThemeData(extensions: [light]),
darkTheme: ThemeData(brightness: Brightness.dark, extensions: [dark]),
home: StreamChat(
client: mockClient,
child: Builder(
builder: (context) => TextButton(
onPressed: () => showDialog<void>(
context: context,
builder: (context) {
captured = Theme.of(context).extension<StreamTheme>();
return const Text('Dialog');
},
),
child: const Text('Open'),
),
),
),
),
);

await tester.tap(find.text('Open'));
await tester.pumpAndSettle();
expect(captured, same(light));

tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark;
await tester.pumpAndSettle();
expect(captured, same(dark));
},
);

testWidgets(
'keeps the state below StreamChat when only one of the app themes '
'registers a StreamTheme',
(tester) async {
tester.platformDispatcher.platformBrightnessTestValue = Brightness.light;
addTearDown(tester.platformDispatcher.clearPlatformBrightnessTestValue);

final mockClient = MockClient();

await tester.pumpWidget(
MaterialApp(
theme: ThemeData(extensions: [StreamTheme.light()]),
darkTheme: ThemeData(brightness: Brightness.dark),
home: StreamChat(
client: mockClient,
child: const Material(child: TextField()),
),
),
);

await tester.enterText(find.byType(TextField), 'draft');

tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark;
await tester.pumpAndSettle();

expect(find.text('draft'), findsOneWidget);
},
);
});
Comment thread
renefloor marked this conversation as resolved.
}

Expand Down
Loading