Skip to content

Commit fdf7a6d

Browse files
authored
feat: add extendBody option for CallContent (#979)
* feat: add extendBody option for CallContent * feat: adding snapshot tests
1 parent cf4cefe commit fdf7a6d

File tree

8 files changed

+148
-0
lines changed

8 files changed

+148
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,8 @@ env.g.dart
137137
/.fvm/version
138138
/.fvm/versions/3.16.0
139139
/.fvmrc
140+
141+
# Non-CI golden files and failures
142+
**/test/**/goldens/**/*.*
143+
**/test/**/failures/**/*.*
144+
!**/test/**/goldens/ci/*.*

melos.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ scripts:
121121
flutter: true
122122
dirExists: test
123123

124+
update:goldens:
125+
run: melos exec -c 1 --depends-on="alchemist" -- "flutter test --tags golden --update-goldens"
126+
description: Update golden files for all packages in this project.
127+
124128
clean:flutter:
125129
run: melos exec -c 4 --fail-fast -- "flutter clean"
126130
description: Run Flutter clean for a specific package in this project.

packages/stream_video_flutter/lib/src/call_screen/call_content/call_content.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class StreamCallContent extends StatefulWidget {
4141
this.callParticipantsBuilder,
4242
this.callControlsBuilder,
4343
this.layoutMode = ParticipantLayoutMode.grid,
44+
this.extendBody = false,
4445
this.pictureInPictureConfiguration = const PictureInPictureConfiguration(),
4546
});
4647

@@ -68,6 +69,12 @@ class StreamCallContent extends StatefulWidget {
6869
/// The layout mode used to display the participants.
6970
final ParticipantLayoutMode layoutMode;
7071

72+
/// If true participants view will be shown all the way to the bottom of the scaffold,
73+
/// meaning that the call controls for the local participants will be on top of the camera view.
74+
///
75+
/// See also [Scaffold.extendBody].
76+
final bool extendBody;
77+
7178
/// Configuration for picture-in-picture mode.
7279
final PictureInPictureConfiguration pictureInPictureConfiguration;
7380

@@ -256,6 +263,7 @@ class _StreamCallContentState extends State<StreamCallContent>
256263
),
257264
],
258265
),
266+
extendBody: widget.extendBody,
259267
bottomNavigationBar: localParticipant != null
260268
? widget.callControlsBuilder?.call(context, call, callState) ??
261269
StreamCallControls.withDefaultOptions(

packages/stream_video_flutter/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies:
2727
visibility_detector: ^0.4.0+2
2828

2929
dev_dependencies:
30+
alchemist: '>=0.11.0 <0.13.0'
3031
flutter_test:
3132
sdk: flutter
3233
mocktail: ^1.0.0
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'dart:async';
2+
import 'dart:io';
3+
4+
import 'package:alchemist/alchemist.dart';
5+
6+
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
7+
final isRunningInCi = Platform.environment.containsKey('CI') ||
8+
Platform.environment.containsKey('GITHUB_ACTIONS');
9+
10+
return AlchemistConfig.runWithConfig(
11+
config: AlchemistConfig(
12+
platformGoldensConfig: PlatformGoldensConfig(
13+
enabled: !isRunningInCi,
14+
),
15+
),
16+
run: testMain,
17+
);
18+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// ignore_for_file: avoid_redundant_argument_values
2+
3+
import 'package:alchemist/alchemist.dart';
4+
import 'package:flutter/material.dart';
5+
import 'package:flutter_test/flutter_test.dart';
6+
import 'package:mocktail/mocktail.dart';
7+
import 'package:stream_video_flutter/stream_video_flutter.dart';
8+
9+
import '../../../test_utils/test_wrapper.dart';
10+
11+
void main() {
12+
group('StreamCallContent', () {
13+
late MockCall mockCall;
14+
late MockCallState mockCallState;
15+
late MockCallParticipantState mockLocalParticipant;
16+
17+
setUp(() {
18+
mockCall = MockCall();
19+
mockCallState = MockCallState();
20+
mockLocalParticipant = MockCallParticipantState();
21+
22+
when(() => mockCallState.localParticipant)
23+
.thenReturn(mockLocalParticipant);
24+
when(() => mockCallState.status).thenReturn(CallStatus.connected());
25+
when(() => mockCallState.callParticipants).thenReturn([]);
26+
});
27+
28+
goldenTest(
29+
'renders correctly with extendBody true',
30+
fileName: 'stream_call_content_extend_body_true',
31+
builder: () => GoldenTestGroup(
32+
children: [
33+
GoldenTestScenario(
34+
name: 'default',
35+
child: _CallContentExample(
36+
mockCall,
37+
mockCallState,
38+
extendBody: true,
39+
),
40+
),
41+
],
42+
),
43+
);
44+
45+
goldenTest(
46+
'renders correctly with extendBody false',
47+
fileName: 'stream_call_content_extend_body_false',
48+
builder: () => GoldenTestGroup(
49+
children: [
50+
GoldenTestScenario(
51+
name: 'default',
52+
child: _CallContentExample(
53+
mockCall,
54+
mockCallState,
55+
extendBody: false,
56+
),
57+
),
58+
],
59+
),
60+
);
61+
});
62+
}
63+
64+
class _CallContentExample extends StatelessWidget {
65+
const _CallContentExample(this.mockCall, this.mockCallState,
66+
{this.extendBody = false});
67+
68+
final MockCall mockCall;
69+
final MockCallState mockCallState;
70+
final bool extendBody;
71+
72+
@override
73+
Widget build(BuildContext context) {
74+
return SizedBox(
75+
width: 300,
76+
height: 300,
77+
child: TestWrapper(
78+
child: StreamCallContent(
79+
call: mockCall,
80+
callState: mockCallState,
81+
extendBody: extendBody,
82+
callAppBarBuilder: (context, call, callState) => AppBar(
83+
title: const Text('Custom App Bar'),
84+
),
85+
callParticipantsBuilder: (context, call, callState) =>
86+
const ColoredBox(
87+
color: Colors.green,
88+
child: Center(
89+
child: Text('Custom Participants View'),
90+
),
91+
),
92+
callControlsBuilder: (context, call, callState) => Row(
93+
mainAxisAlignment: MainAxisAlignment.center,
94+
children: [
95+
IconButton(
96+
onPressed: () {},
97+
icon: const Icon(Icons.call),
98+
),
99+
IconButton(onPressed: () {}, icon: const Icon(Icons.mic)),
100+
],
101+
),
102+
),
103+
),
104+
);
105+
}
106+
}
107+
108+
class MockCall extends Mock implements Call {}
109+
110+
class MockCallState extends Mock implements CallState {}
111+
112+
class MockCallParticipantState extends Mock implements CallParticipantState {}
1.99 KB
Loading
1.98 KB
Loading

0 commit comments

Comments
 (0)