Merge branch 'develop' into message-input-controller
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
## Upcoming
|
||||||
|
|
||||||
|
✅ Added
|
||||||
|
|
||||||
|
- Added `client.enrichUrl` endpoint for enriching URLs with metadata.
|
||||||
|
|
||||||
## 3.3.1
|
## 3.3.1
|
||||||
|
|
||||||
🐞 Fixed
|
🐞 Fixed
|
||||||
|
|||||||
@@ -1316,6 +1316,10 @@ class StreamChatClient {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Get OpenGraph data of the given [url].
|
||||||
|
Future<OGAttachmentResponse> enrichUrl(String url) =>
|
||||||
|
_chatApi.general.enrichUrl(url);
|
||||||
|
|
||||||
/// Closes the [_ws] connection and resets the [state]
|
/// Closes the [_ws] connection and resets the [state]
|
||||||
/// If [flushChatPersistence] is true the client deletes all offline
|
/// If [flushChatPersistence] is true the client deletes all offline
|
||||||
/// user's data.
|
/// user's data.
|
||||||
|
|||||||
@@ -96,4 +96,16 @@ class GeneralApi {
|
|||||||
|
|
||||||
return QueryMembersResponse.fromJson(response.data);
|
return QueryMembersResponse.fromJson(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get OpenGraph data of the given [url].
|
||||||
|
Future<OGAttachmentResponse> enrichUrl(String url) async {
|
||||||
|
final response = await _client.get(
|
||||||
|
'/og',
|
||||||
|
queryParameters: {
|
||||||
|
'url': url,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return OGAttachmentResponse.fromJson(response.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -442,3 +442,43 @@ class ChannelStateResponse extends _BaseResponse {
|
|||||||
static ChannelStateResponse fromJson(Map<String, dynamic> json) =>
|
static ChannelStateResponse fromJson(Map<String, dynamic> json) =>
|
||||||
_$ChannelStateResponseFromJson(json);
|
_$ChannelStateResponseFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Model response for [Client.enrichUrl] api call.
|
||||||
|
@JsonSerializable(createToJson: false)
|
||||||
|
class OGAttachmentResponse extends _BaseResponse {
|
||||||
|
/// The URL of the page that was scraped.
|
||||||
|
late String ogScrapeUrl;
|
||||||
|
|
||||||
|
/// The URL of the asset.
|
||||||
|
String? assetUrl;
|
||||||
|
|
||||||
|
/// The URL of the author.
|
||||||
|
String? authorLink;
|
||||||
|
|
||||||
|
/// The name of the author.
|
||||||
|
String? authorName;
|
||||||
|
|
||||||
|
/// The URL of the image.
|
||||||
|
String? imageUrl;
|
||||||
|
|
||||||
|
/// The text of the attachment.
|
||||||
|
String? text;
|
||||||
|
|
||||||
|
/// The URL of the thumbnail.
|
||||||
|
String? thumbUrl;
|
||||||
|
|
||||||
|
/// The title of the attachment.
|
||||||
|
String? title;
|
||||||
|
|
||||||
|
/// The URL of the title.
|
||||||
|
String? titleLink;
|
||||||
|
|
||||||
|
/// The type of the attachment.
|
||||||
|
///
|
||||||
|
/// 'video' | 'audio' | 'image'
|
||||||
|
String? type;
|
||||||
|
|
||||||
|
/// Create a new instance from a [json].
|
||||||
|
static OGAttachmentResponse fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$OGAttachmentResponseFromJson(json);
|
||||||
|
}
|
||||||
|
|||||||
@@ -273,3 +273,18 @@ ChannelStateResponse _$ChannelStateResponseFromJson(
|
|||||||
?.map((e) => Read.fromJson(e as Map<String, dynamic>))
|
?.map((e) => Read.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[];
|
[];
|
||||||
|
|
||||||
|
OGAttachmentResponse _$OGAttachmentResponseFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
OGAttachmentResponse()
|
||||||
|
..duration = json['duration'] as String?
|
||||||
|
..ogScrapeUrl = json['og_scrape_url'] as String
|
||||||
|
..assetUrl = json['asset_url'] as String?
|
||||||
|
..authorLink = json['author_link'] as String?
|
||||||
|
..authorName = json['author_name'] as String?
|
||||||
|
..imageUrl = json['image_url'] as String?
|
||||||
|
..text = json['text'] as String?
|
||||||
|
..thumbUrl = json['thumb_url'] as String?
|
||||||
|
..title = json['title'] as String?
|
||||||
|
..titleLink = json['title_link'] as String?
|
||||||
|
..type = json['type'] as String?;
|
||||||
|
|||||||
@@ -1,20 +1,7 @@
|
|||||||
import 'package:mocktail/mocktail.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat/src/client/client.dart';
|
|
||||||
import 'package:stream_chat/src/core/api/device_api.dart';
|
import 'package:stream_chat/src/core/api/device_api.dart';
|
||||||
import 'package:stream_chat/src/core/api/requests.dart';
|
|
||||||
import 'package:stream_chat/src/core/api/responses.dart';
|
|
||||||
import 'package:stream_chat/src/core/error/error.dart';
|
|
||||||
import 'package:stream_chat/src/core/http/token.dart';
|
import 'package:stream_chat/src/core/http/token.dart';
|
||||||
import 'package:stream_chat/src/core/models/channel_model.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/event.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/filter.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/message.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/own_user.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/user.dart';
|
|
||||||
import 'package:stream_chat/src/event_type.dart';
|
|
||||||
import 'package:stream_chat/src/ws/connection_status.dart';
|
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:test/scaffolding.dart';
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import '../fakes.dart';
|
import '../fakes.dart';
|
||||||
@@ -2314,6 +2301,33 @@ void main() {
|
|||||||
verifyNoMoreInteractions(api.message);
|
verifyNoMoreInteractions(api.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('`.enrichUrl`', () async {
|
||||||
|
const url =
|
||||||
|
'https://www.techyourchance.com/finite-state-machine-with-unit-tests-real-world-example';
|
||||||
|
|
||||||
|
when(() => api.general.enrichUrl(url)).thenAnswer(
|
||||||
|
(_) async => OGAttachmentResponse()
|
||||||
|
..type = 'image'
|
||||||
|
..ogScrapeUrl = url
|
||||||
|
..authorName = 'TechYourChance'
|
||||||
|
..title = 'Finite State Machine with Unit Tests: Real World Example',
|
||||||
|
);
|
||||||
|
|
||||||
|
final res = await client.enrichUrl(url);
|
||||||
|
|
||||||
|
expect(res, isNotNull);
|
||||||
|
expect(res.type, 'image');
|
||||||
|
expect(res.ogScrapeUrl, url);
|
||||||
|
expect(res.authorName, 'TechYourChance');
|
||||||
|
expect(
|
||||||
|
res.title,
|
||||||
|
'Finite State Machine with Unit Tests: Real World Example',
|
||||||
|
);
|
||||||
|
|
||||||
|
verify(() => api.general.enrichUrl(url)).called(1);
|
||||||
|
verifyNoMoreInteractions(api.general);
|
||||||
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'''setting the `currentUser` should also compute and update the unreadCounts''',
|
'''setting the `currentUser` should also compute and update the unreadCounts''',
|
||||||
() {
|
() {
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ import 'dart:convert';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:mocktail/mocktail.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat/src/core/api/general_api.dart';
|
import 'package:stream_chat/src/core/api/general_api.dart';
|
||||||
import 'package:stream_chat/src/core/api/requests.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/channel_model.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/event.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/filter.dart';
|
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
@@ -281,4 +277,39 @@ void main() {
|
|||||||
verifyNoMoreInteractions(client);
|
verifyNoMoreInteractions(client);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('enrichUrl', () async {
|
||||||
|
const path = '/og';
|
||||||
|
const url =
|
||||||
|
'https://www.techyourchance.com/finite-state-machine-with-unit-tests-real-world-example';
|
||||||
|
|
||||||
|
when(() => client.get(
|
||||||
|
path,
|
||||||
|
queryParameters: {'url': url},
|
||||||
|
)).thenAnswer((_) async => successResponse(path, data: {
|
||||||
|
'type': 'image',
|
||||||
|
'og_scrape_url': url,
|
||||||
|
'author_name': 'TechYourChance',
|
||||||
|
'title': 'Finite State Machine with Unit Tests: Real World Example',
|
||||||
|
}));
|
||||||
|
|
||||||
|
final res = await generalApi.enrichUrl(url);
|
||||||
|
|
||||||
|
expect(res, isNotNull);
|
||||||
|
expect(res.type, 'image');
|
||||||
|
expect(res.ogScrapeUrl, url);
|
||||||
|
expect(res.authorName, 'TechYourChance');
|
||||||
|
expect(
|
||||||
|
res.title,
|
||||||
|
'Finite State Machine with Unit Tests: Real World Example',
|
||||||
|
);
|
||||||
|
|
||||||
|
verify(
|
||||||
|
() => client.get(
|
||||||
|
path,
|
||||||
|
queryParameters: {'url': url},
|
||||||
|
),
|
||||||
|
).called(1);
|
||||||
|
verifyNoMoreInteractions(client);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user