Skip to content

Commit

Permalink
Merge pull request #1295 from GetStream/3rd-party-video-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
xsahil03x authored Sep 9, 2022
2 parents 4532a0d + 3f5e179 commit 2cef380
Show file tree
Hide file tree
Showing 13 changed files with 396 additions and 2 deletions.
4 changes: 2 additions & 2 deletions melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ scripts:
description: Build all generated files for Dart & Flutter packages in this project.

generate:dart:
run: melos exec -c 1 --depends-on="build_runner" --no-flutter -- "dart run build_runner build --delete-conflicting-outputs"
run: melos exec -c 1 --depends-on="build_runner" --no-flutter -- "dart run build_runner build --delete-conflicting-outputs --enable-experiment=super-parameters,enhanced-enums"
description: Build all generated files for Dart packages in this project.

generate:flutter:
run: melos exec -c 1 --depends-on="build_runner" --flutter -- "flutter pub run build_runner build --delete-conflicting-outputs"
run: melos exec -c 1 --depends-on="build_runner" --flutter -- "flutter run build_runner build --delete-conflicting-outputs --enable-experiment=super-parameters,enhanced-enums"
description: Build all generated files for Flutter packages in this project.

test:all:
Expand Down
4 changes: 4 additions & 0 deletions packages/stream_chat/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Upcoming

✅ Added

- Added `StreamChatClient.getCallToken` and `StreamChatClient.createCall` methods.

🐞 Fixed

- Only listen to client events when the user is connected to the websocket.
Expand Down
19 changes: 19 additions & 0 deletions packages/stream_chat/lib/src/client/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,25 @@ class StreamChatClient {
}
}

/// Returns a token associated with the [callId].
Future<CallTokenPayload> getCallToken(String callId) async =>
_chatApi.call.getCallToken(callId);

/// Creates a new call.
Future<CreateCallPayload> createCall({
required String callId,
required String callType,
required String channelType,
required String channelId,
}) {
return _chatApi.call.createCall(
callId: callId,
callType: callType,
channelType: channelType,
channelId: channelId,
);
}

/// Requests channels with a given query from the API.
Future<List<Channel>> queryChannelsOnline({
Filter? filter,
Expand Down
41 changes: 41 additions & 0 deletions packages/stream_chat/lib/src/core/api/call_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:stream_chat/src/core/api/responses.dart';
import 'package:stream_chat/src/core/http/stream_http_client.dart';

/// Defines the api dedicated to call operations.
class CallApi {
/// Initialize a new call api
CallApi(this._client);

final StreamHttpClient _client;

/// Returns a token dedicated to the [callId]
Future<CallTokenPayload> getCallToken(String callId) async {
final response = await _client.post(
'/calls/$callId',
data: {},
);
// return response.data;
return CallTokenPayload.fromJson(response.data);
}

/// Creates a new call
Future<CreateCallPayload> createCall({
required String callId,
required String callType,
required String channelType,
required String channelId,
}) async {
final response = await _client.post(
_getChannelUrl(channelId, channelType),
data: {
'id': callId,
'type': callType,
},
);
// return response.data;
return CreateCallPayload.fromJson(response.data);
}

String _getChannelUrl(String channelId, String channelType) =>
'/channels/$channelType/$channelId/call';
}
30 changes: 30 additions & 0 deletions packages/stream_chat/lib/src/core/api/responses.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/client/client.dart';
import 'package:stream_chat/src/core/api/call_api.dart';
import 'package:stream_chat/src/core/error/error.dart';
import 'package:stream_chat/src/core/models/banned_user.dart';
import 'package:stream_chat/src/core/models/call_payload.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/channel_state.dart';
import 'package:stream_chat/src/core/models/device.dart';
Expand Down Expand Up @@ -495,3 +497,31 @@ class OGAttachmentResponse extends _BaseResponse {
static OGAttachmentResponse fromJson(Map<String, dynamic> json) =>
_$OGAttachmentResponseFromJson(json);
}

/// The response to [CallApi.getCallToken]
@JsonSerializable(createToJson: false)
class CallTokenPayload extends _BaseResponse {
/// Create a new instance from a [json].
static CallTokenPayload fromJson(Map<String, dynamic> json) =>
_$CallTokenPayloadFromJson(json);

/// The token to use for the call.
String? token;

/// The user id specific to Agora.
int? agoraUid;

/// The appId specific to Agora.
String? agoraAppId;
}

/// The response to [CallApi.createCall]
@JsonSerializable(createToJson: false)
class CreateCallPayload extends _BaseResponse {
/// Create a new instance from a [json].
static CreateCallPayload fromJson(Map<String, dynamic> json) =>
_$CreateCallPayloadFromJson(json);

/// The call object.
CallPayload? call;
}
14 changes: 14 additions & 0 deletions packages/stream_chat/lib/src/core/api/responses.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions packages/stream_chat/lib/src/core/api/stream_chat_api.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:logging/logging.dart';
import 'package:stream_chat/src/core/api/attachment_file_uploader.dart';
import 'package:stream_chat/src/core/api/call_api.dart';
import 'package:stream_chat/src/core/api/channel_api.dart';
import 'package:stream_chat/src/core/api/device_api.dart';
import 'package:stream_chat/src/core/api/general_api.dart';
Expand Down Expand Up @@ -53,6 +54,11 @@ class StreamChatApi {
/// Api dedicated to message operations
MessageApi get message => _message ??= MessageApi(_client);

CallApi? _call;

/// Api dedicated to call operations
CallApi get call => _call ??= CallApi(_client);

ChannelApi? _channel;

/// Api dedicated to channel operations
Expand Down
72 changes: 72 additions & 0 deletions packages/stream_chat/lib/src/core/models/call_payload.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';

part 'call_payload.g.dart';

/// Model containing the information about a call.
@JsonSerializable(createToJson: false)
class CallPayload extends Equatable {
/// Create a new instance.
const CallPayload({
required this.id,
required this.provider,
this.agora,
this.hms,
});

/// Create a new instance from a [json].
factory CallPayload.fromJson(Map<String, dynamic> json) =>
_$CallPayloadFromJson(json);

/// The call id.
final String id;

/// The call provider.
final String provider;

/// The payload specific to Agora.
final AgoraPayload? agora;

/// The payload specific to 100ms.
final HMSPayload? hms;

@override
List<Object?> get props => [id, provider, agora, hms];
}

/// Payload for Agora call.
@JsonSerializable(createToJson: false)
class AgoraPayload extends Equatable {
/// Create a new instance.
const AgoraPayload({required this.channel});

/// Create a new instance from a [json].
factory AgoraPayload.fromJson(Map<String, dynamic> json) =>
_$AgoraPayloadFromJson(json);

/// The Agora channel.
final String channel;

@override
List<Object?> get props => [channel];
}

/// Payload for 100ms call.
@JsonSerializable(createToJson: false)
class HMSPayload extends Equatable {
/// Create a new instance.
const HMSPayload({required this.roomId, required this.roomName});

/// Create a new instance from a [json].
factory HMSPayload.fromJson(Map<String, dynamic> json) =>
_$HMSPayloadFromJson(json);

/// The id of the 100ms room.
final String roomId;

/// The name of the 100ms room.
final String roomName;

@override
List<Object?> get props => [roomId, roomName];
}
27 changes: 27 additions & 0 deletions packages/stream_chat/lib/src/core/models/call_payload.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 66 additions & 0 deletions packages/stream_chat/test/src/core/api/call_api_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/call_api.dart';
import 'package:test/test.dart';

import '../../mocks.dart';

void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);

late final client = MockHttpClient();
late CallApi callApi;

setUp(() {
callApi = CallApi(client);
});

test('getCallToken should work', () async {
const callId = 'test-call-id';
const path = '/calls/$callId';

when(() => client.post(path, data: {})).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));

final res = await callApi.getCallToken(callId);

expect(res, isNotNull);

verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});

test('createCall should work', () async {
const callId = 'test-call-id';
const callType = 'test-call-type';
const channelType = 'test-channel-type';
const channelId = 'test-channel-id';
const path = '/channels/$channelType/$channelId/call';

when(() => client.post(
path,
data: {
'id': callId,
'type': callType,
},
))
.thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));

final res = await callApi.createCall(
callId: callId,
callType: callType,
channelType: channelType,
channelId: channelId,
);

expect(res, isNotNull);

verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
}
50 changes: 50 additions & 0 deletions packages/stream_chat/test/src/core/api/requests_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,56 @@ void main() {
}
},
);

test('copyWith', () {
final params = PaginationParams(
offset: 10,
limit: 20,
createdAtAfter: DateTime.now(),
createdAtAfterOrEqual: DateTime.now(),
createdAtAround: DateTime.now(),
createdAtBefore: DateTime.now(),
createdAtBeforeOrEqual: DateTime.now(),
greaterThan: 'greater-than',
greaterThanOrEqual: 'greater-than-or-equal',
lessThan: 'less-than',
lessThanOrEqual: 'less-than-or-equal',
idAround: 'id-around',
);

final sameOld = params.copyWith();
expect(sameOld, equals(params));

final newDateTime = DateTime.now().add(const Duration(days: 2));
const newTestString = 'test';
final newParams = params.copyWith(
limit: 2,
offset: 2,
createdAtAfter: newDateTime,
createdAtAfterOrEqual: newDateTime,
createdAtAround: newDateTime,
createdAtBefore: newDateTime,
createdAtBeforeOrEqual: newDateTime,
greaterThan: newTestString,
greaterThanOrEqual: newTestString,
lessThan: newTestString,
lessThanOrEqual: newTestString,
idAround: newTestString,
);

expect(newParams.limit, 2);
expect(newParams.offset, 2);
expect(newParams.createdAtAfter, newDateTime);
expect(newParams.createdAtAfterOrEqual, newDateTime);
expect(newParams.createdAtAround, newDateTime);
expect(newParams.createdAtBefore, newDateTime);
expect(newParams.createdAtBeforeOrEqual, newDateTime);
expect(newParams.greaterThan, newTestString);
expect(newParams.greaterThanOrEqual, newTestString);
expect(newParams.lessThan, newTestString);
expect(newParams.lessThanOrEqual, newTestString);
expect(newParams.idAround, newTestString);
});
});
});
}
Loading

0 comments on commit 2cef380

Please sign in to comment.