Skip to content

Commit 74f3610

Browse files
authored
feat(llc): kick user feature (#1058)
* kick user feature * fixed removed manual edit * added option to also block user
1 parent 9645b43 commit 74f3610

37 files changed

+2355
-10
lines changed

packages/stream_video/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## Unreleased
22

3+
✅ Added
4+
* Added capability to remove a participant from a call via `call.kickUser()`. Requires the `kick-user` permission.
5+
36
🐞 Fixed
47
* Multitasking camera on iOS is now enabled only once and kept enabled. This fixes potential errors when quickly toggling camera.
58

packages/stream_video/lib/globals.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:meta/meta.dart';
22

33
const String streamSdkName = 'stream-flutter';
44
const String streamVideoVersion = '0.10.3';
5-
const String openapiModelsVersion = '180.1.0';
5+
const String openapiModelsVersion = '190.7.0';
66
const String protocolModelsVersion = '1.38.0';
77
const String androidWebRTCVersion = '1.3.8';
88
const String iosWebRTCVersion = '125.6422.65';

packages/stream_video/lib/open_api/video/coordinator/api.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,19 @@ part 'model/hls_settings_request.dart';
153153
part 'model/hls_settings_response.dart';
154154
part 'model/health_check_event.dart';
155155
part 'model/ice_server.dart';
156+
part 'model/ingress_audio_encoding_options_request.dart';
157+
part 'model/ingress_audio_encoding_response.dart';
158+
part 'model/ingress_settings_request.dart';
159+
part 'model/ingress_settings_response.dart';
160+
part 'model/ingress_video_encoding_options_request.dart';
161+
part 'model/ingress_video_encoding_response.dart';
162+
part 'model/ingress_video_layer_request.dart';
163+
part 'model/ingress_video_layer_response.dart';
156164
part 'model/join_call_request.dart';
157165
part 'model/join_call_response.dart';
166+
part 'model/kick_user_request.dart';
167+
part 'model/kick_user_response.dart';
168+
part 'model/kicked_user_event.dart';
158169
part 'model/layout_settings_request.dart';
159170
part 'model/limits_settings_request.dart';
160171
part 'model/limits_settings_response.dart';

packages/stream_video/lib/open_api/video/coordinator/api/productvideo_api.dart

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,88 @@ class ProductvideoApi {
13081308
return null;
13091309
}
13101310

1311+
/// Kick user from a call
1312+
///
1313+
/// Kicks a user from the call. Optionally block the user from rejoining by setting block=true. Sends events: - call.blocked_user - call.kicked_user
1314+
///
1315+
/// Note: This method returns the HTTP [Response].
1316+
///
1317+
/// Parameters:
1318+
///
1319+
/// * [String] type (required):
1320+
///
1321+
/// * [String] id (required):
1322+
///
1323+
/// * [KickUserRequest] kickUserRequest (required):
1324+
/// KickUserRequest
1325+
Future<Response> kickUserWithHttpInfo(
1326+
String type,
1327+
String id,
1328+
KickUserRequest kickUserRequest,
1329+
) async {
1330+
// ignore: prefer_const_declarations
1331+
final path = r'/video/call/{type}/{id}/kick'
1332+
.replaceAll('{type}', type)
1333+
.replaceAll('{id}', id);
1334+
1335+
// ignore: prefer_final_locals
1336+
Object? postBody = kickUserRequest;
1337+
1338+
final queryParams = <QueryParam>[];
1339+
final headerParams = <String, String>{};
1340+
final formParams = <String, String>{};
1341+
1342+
const contentTypes = <String>['application/json'];
1343+
1344+
return apiClient.invokeAPI(
1345+
path,
1346+
'POST',
1347+
queryParams,
1348+
postBody,
1349+
headerParams,
1350+
formParams,
1351+
contentTypes.isEmpty ? null : contentTypes.first,
1352+
);
1353+
}
1354+
1355+
/// Kick user from a call
1356+
///
1357+
/// Kicks a user from the call. Optionally block the user from rejoining by setting block=true. Sends events: - call.blocked_user - call.kicked_user
1358+
///
1359+
/// Parameters:
1360+
///
1361+
/// * [String] type (required):
1362+
///
1363+
/// * [String] id (required):
1364+
///
1365+
/// * [KickUserRequest] kickUserRequest (required):
1366+
/// KickUserRequest
1367+
Future<KickUserResponse?> kickUser(
1368+
String type,
1369+
String id,
1370+
KickUserRequest kickUserRequest,
1371+
) async {
1372+
final response = await kickUserWithHttpInfo(
1373+
type,
1374+
id,
1375+
kickUserRequest,
1376+
);
1377+
if (response.statusCode >= HttpStatus.badRequest) {
1378+
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
1379+
}
1380+
// When a remote server returns no body with a status of 204, we shall not decode it.
1381+
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
1382+
// FormatException when trying to decode an empty string.
1383+
if (response.body.isNotEmpty &&
1384+
response.statusCode != HttpStatus.noContent) {
1385+
return await apiClient.deserializeAsync(
1386+
await _decodeBodyBytes(response),
1387+
'KickUserResponse',
1388+
) as KickUserResponse;
1389+
}
1390+
return null;
1391+
}
1392+
13111393
/// List devices
13121394
///
13131395
/// Returns all available devices

packages/stream_video/lib/open_api/video/coordinator/api_client.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,10 +476,32 @@ class ApiClient {
476476
return HealthCheckEvent.fromJson(value);
477477
case 'ICEServer':
478478
return ICEServer.fromJson(value);
479+
case 'IngressAudioEncodingOptionsRequest':
480+
return IngressAudioEncodingOptionsRequest.fromJson(value);
481+
case 'IngressAudioEncodingResponse':
482+
return IngressAudioEncodingResponse.fromJson(value);
483+
case 'IngressSettingsRequest':
484+
return IngressSettingsRequest.fromJson(value);
485+
case 'IngressSettingsResponse':
486+
return IngressSettingsResponse.fromJson(value);
487+
case 'IngressVideoEncodingOptionsRequest':
488+
return IngressVideoEncodingOptionsRequest.fromJson(value);
489+
case 'IngressVideoEncodingResponse':
490+
return IngressVideoEncodingResponse.fromJson(value);
491+
case 'IngressVideoLayerRequest':
492+
return IngressVideoLayerRequest.fromJson(value);
493+
case 'IngressVideoLayerResponse':
494+
return IngressVideoLayerResponse.fromJson(value);
479495
case 'JoinCallRequest':
480496
return JoinCallRequest.fromJson(value);
481497
case 'JoinCallResponse':
482498
return JoinCallResponse.fromJson(value);
499+
case 'KickUserRequest':
500+
return KickUserRequest.fromJson(value);
501+
case 'KickUserResponse':
502+
return KickUserResponse.fromJson(value);
503+
case 'KickedUserEvent':
504+
return KickedUserEvent.fromJson(value);
483505
case 'LayoutSettingsRequest':
484506
return LayoutSettingsRequest.fromJson(value);
485507
case 'LimitsSettingsRequest':

packages/stream_video/lib/open_api/video/coordinator/model/call_settings_request.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class CallSettingsRequest {
1818
this.broadcasting,
1919
this.frameRecording,
2020
this.geofencing,
21+
this.ingress,
2122
this.limits,
2223
this.recording,
2324
this.ring,
@@ -68,6 +69,14 @@ class CallSettingsRequest {
6869
///
6970
GeofenceSettingsRequest? geofencing;
7071

72+
///
73+
/// Please note: This property should have been non-nullable! Since the specification file
74+
/// does not include a default value (using the "default:" property), however, the generated
75+
/// source code must fall back to having a nullable type.
76+
/// Consider adding a "default:" property in the specification file to hide this note.
77+
///
78+
IngressSettingsRequest? ingress;
79+
7180
///
7281
/// Please note: This property should have been non-nullable! Since the specification file
7382
/// does not include a default value (using the "default:" property), however, the generated
@@ -141,6 +150,7 @@ class CallSettingsRequest {
141150
other.broadcasting == broadcasting &&
142151
other.frameRecording == frameRecording &&
143152
other.geofencing == geofencing &&
153+
other.ingress == ingress &&
144154
other.limits == limits &&
145155
other.recording == recording &&
146156
other.ring == ring &&
@@ -158,6 +168,7 @@ class CallSettingsRequest {
158168
(broadcasting == null ? 0 : broadcasting!.hashCode) +
159169
(frameRecording == null ? 0 : frameRecording!.hashCode) +
160170
(geofencing == null ? 0 : geofencing!.hashCode) +
171+
(ingress == null ? 0 : ingress!.hashCode) +
161172
(limits == null ? 0 : limits!.hashCode) +
162173
(recording == null ? 0 : recording!.hashCode) +
163174
(ring == null ? 0 : ring!.hashCode) +
@@ -169,7 +180,7 @@ class CallSettingsRequest {
169180

170181
@override
171182
String toString() =>
172-
'CallSettingsRequest[audio=$audio, backstage=$backstage, broadcasting=$broadcasting, frameRecording=$frameRecording, geofencing=$geofencing, limits=$limits, recording=$recording, ring=$ring, screensharing=$screensharing, session=$session, thumbnails=$thumbnails, transcription=$transcription, video=$video]';
183+
'CallSettingsRequest[audio=$audio, backstage=$backstage, broadcasting=$broadcasting, frameRecording=$frameRecording, geofencing=$geofencing, ingress=$ingress, limits=$limits, recording=$recording, ring=$ring, screensharing=$screensharing, session=$session, thumbnails=$thumbnails, transcription=$transcription, video=$video]';
173184

174185
Map<String, dynamic> toJson() {
175186
final json = <String, dynamic>{};
@@ -198,6 +209,11 @@ class CallSettingsRequest {
198209
} else {
199210
json[r'geofencing'] = null;
200211
}
212+
if (this.ingress != null) {
213+
json[r'ingress'] = this.ingress;
214+
} else {
215+
json[r'ingress'] = null;
216+
}
201217
if (this.limits != null) {
202218
json[r'limits'] = this.limits;
203219
} else {
@@ -268,6 +284,7 @@ class CallSettingsRequest {
268284
frameRecording:
269285
FrameRecordingSettingsRequest.fromJson(json[r'frame_recording']),
270286
geofencing: GeofenceSettingsRequest.fromJson(json[r'geofencing']),
287+
ingress: IngressSettingsRequest.fromJson(json[r'ingress']),
271288
limits: LimitsSettingsRequest.fromJson(json[r'limits']),
272289
recording: RecordSettingsRequest.fromJson(json[r'recording']),
273290
ring: RingSettingsRequest.fromJson(json[r'ring']),

packages/stream_video/lib/open_api/video/coordinator/model/call_settings_response.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class CallSettingsResponse {
1818
required this.broadcasting,
1919
required this.frameRecording,
2020
required this.geofencing,
21+
this.ingress,
2122
required this.limits,
2223
required this.recording,
2324
required this.ring,
@@ -38,6 +39,14 @@ class CallSettingsResponse {
3839

3940
GeofenceSettingsResponse geofencing;
4041

42+
///
43+
/// Please note: This property should have been non-nullable! Since the specification file
44+
/// does not include a default value (using the "default:" property), however, the generated
45+
/// source code must fall back to having a nullable type.
46+
/// Consider adding a "default:" property in the specification file to hide this note.
47+
///
48+
IngressSettingsResponse? ingress;
49+
4150
LimitsSettingsResponse limits;
4251

4352
RecordSettingsResponse recording;
@@ -63,6 +72,7 @@ class CallSettingsResponse {
6372
other.broadcasting == broadcasting &&
6473
other.frameRecording == frameRecording &&
6574
other.geofencing == geofencing &&
75+
other.ingress == ingress &&
6676
other.limits == limits &&
6777
other.recording == recording &&
6878
other.ring == ring &&
@@ -80,6 +90,7 @@ class CallSettingsResponse {
8090
(broadcasting.hashCode) +
8191
(frameRecording.hashCode) +
8292
(geofencing.hashCode) +
93+
(ingress == null ? 0 : ingress!.hashCode) +
8394
(limits.hashCode) +
8495
(recording.hashCode) +
8596
(ring.hashCode) +
@@ -91,7 +102,7 @@ class CallSettingsResponse {
91102

92103
@override
93104
String toString() =>
94-
'CallSettingsResponse[audio=$audio, backstage=$backstage, broadcasting=$broadcasting, frameRecording=$frameRecording, geofencing=$geofencing, limits=$limits, recording=$recording, ring=$ring, screensharing=$screensharing, session=$session, thumbnails=$thumbnails, transcription=$transcription, video=$video]';
105+
'CallSettingsResponse[audio=$audio, backstage=$backstage, broadcasting=$broadcasting, frameRecording=$frameRecording, geofencing=$geofencing, ingress=$ingress, limits=$limits, recording=$recording, ring=$ring, screensharing=$screensharing, session=$session, thumbnails=$thumbnails, transcription=$transcription, video=$video]';
95106

96107
Map<String, dynamic> toJson() {
97108
final json = <String, dynamic>{};
@@ -100,6 +111,11 @@ class CallSettingsResponse {
100111
json[r'broadcasting'] = this.broadcasting;
101112
json[r'frame_recording'] = this.frameRecording;
102113
json[r'geofencing'] = this.geofencing;
114+
if (this.ingress != null) {
115+
json[r'ingress'] = this.ingress;
116+
} else {
117+
json[r'ingress'] = null;
118+
}
103119
json[r'limits'] = this.limits;
104120
json[r'recording'] = this.recording;
105121
json[r'ring'] = this.ring;
@@ -139,6 +155,7 @@ class CallSettingsResponse {
139155
frameRecording:
140156
FrameRecordingSettingsResponse.fromJson(json[r'frame_recording'])!,
141157
geofencing: GeofenceSettingsResponse.fromJson(json[r'geofencing'])!,
158+
ingress: IngressSettingsResponse.fromJson(json[r'ingress']),
142159
limits: LimitsSettingsResponse.fromJson(json[r'limits'])!,
143160
recording: RecordSettingsResponse.fromJson(json[r'recording'])!,
144161
ring: RingSettingsResponse.fromJson(json[r'ring'])!,

0 commit comments

Comments
 (0)