Skip to content

Commit 822ca86

Browse files
committed
Merge remote-tracking branch 'origin/feat/message-polls-apis' into feat/polls-attachment-composer
# Conflicts: # packages/stream_chat/lib/src/core/models/poll.dart # packages/stream_chat/lib/src/core/models/poll.g.dart # packages/stream_chat/lib/src/core/models/poll_option.dart # packages/stream_chat/lib/src/core/models/poll_option.g.dart # packages/stream_chat/lib/src/core/models/poll_vote.dart # packages/stream_chat/lib/src/core/models/poll_vote.g.dart # packages/stream_chat/lib/src/event_type.dart
2 parents a5fd7f6 + f9e7664 commit 822ca86

35 files changed

+1055
-87
lines changed

packages/stream_chat/CHANGELOG.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
## Upcoming
1+
## 8.3.0
22

33
✅ Added
4+
5+
- Added support for AI assistant states and events.
6+
7+
## 8.2.0
8+
9+
✅ Added
10+
411
- Added user blocking to the client.
512

613
## 8.1.0
714

815
✅ Added
16+
917
- Added `httpClientAdapter` to `StreamHttpClient` that enables the use native http implementations
1018

1119
🔄 Changed
@@ -31,20 +39,24 @@
3139
## 7.2.1
3240

3341
✅ Added
42+
3443
- Added `voiceRecording` attachment type
3544

3645
## 7.2.0-hotfix.1
3746

38-
- Version to keep in sync with the rest of the packages
39-
47+
- Version to keep in sync with the rest of the packages
48+
4049
## 7.2.0
4150

4251
✅ Added
43-
- Added `markUnread` method to `Channel` that marks messages from the provided message id onwards as unread
52+
53+
- Added `markUnread` method to `Channel` that marks messages from the provided message id onwards as
54+
unread
4455

4556
## 7.1.0
4657

4758
🐞 Fixed
59+
4860
- Fixes a thread message causing reply messages on the main thread to be considered deleted
4961

5062
## 7.0.2
@@ -64,7 +76,7 @@
6476
**might** produce a **breaking change** if you your code depends in `UUID` `3.x.x` directly or indirectly.
6577

6678
## 7.0.0
67-
79+
6880
- 🛑️ Breaking
6981

7082
- Removed deprecated `channelQuery.sort` property. Use `channelStateSort` instead.

packages/stream_chat/lib/src/client/channel.dart

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,16 @@ class Channel {
11871187
}
11881188
}
11891189

1190+
/// Sends an event to stop AI response generation, leaving the message in
1191+
/// its current state.
1192+
Future<EmptyResponse> stopAIResponse() async {
1193+
return sendEvent(
1194+
Event(
1195+
type: EventType.aiIndicatorStop,
1196+
),
1197+
);
1198+
}
1199+
11901200
/// Update the channel's [name].
11911201
///
11921202
/// This is the same as calling [updatePartial] and providing a map with a
@@ -2008,8 +2018,8 @@ class ChannelClientState {
20082018
final existingWatchers = channelState.watchers;
20092019
updateChannelState(channelState.copyWith(
20102020
watchers: [
2011-
...?existingWatchers,
20122021
watcher,
2022+
...?existingWatchers?.where((user) => user.id != watcher.id),
20132023
],
20142024
));
20152025
}
@@ -2024,9 +2034,9 @@ class ChannelClientState {
20242034
if (watcher != null) {
20252035
final existingWatchers = channelState.watchers;
20262036
updateChannelState(channelState.copyWith(
2027-
watchers: existingWatchers
2028-
?.where((user) => user.id != watcher.id)
2029-
.toList(growable: false),
2037+
watchers: [
2038+
...?existingWatchers?.where((user) => user.id != watcher.id)
2039+
],
20302040
));
20312041
}
20322042
}),
@@ -2606,7 +2616,7 @@ class ChannelClientState {
26062616
channelStateStream.map((cs) => cs.members),
26072617
_channel.client.state.usersStream,
26082618
(members, users) =>
2609-
members!.map((e) => e!.copyWith(user: users[e.user!.id])).toList(),
2619+
[...?members?.map((e) => e!.copyWith(user: users[e.user!.id]))],
26102620
).distinct(const ListEquality().equals);
26112621

26122622
/// Channel watcher count.
@@ -2626,7 +2636,7 @@ class ChannelClientState {
26262636
List<User>?, Map<String?, User?>, List<User>>(
26272637
channelStateStream.map((cs) => cs.watchers),
26282638
_channel.client.state.usersStream,
2629-
(watchers, users) => watchers!.map((e) => users[e.id] ?? e).toList(),
2639+
(watchers, users) => [...?watchers?.map((e) => users[e.id] ?? e)],
26302640
).distinct(const ListEquality().equals);
26312641

26322642
/// Channel member for the current user.

packages/stream_chat/lib/src/core/error/stream_chat_error.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ class StreamChatNetworkError extends StreamChatError {
7676
ChatErrorCode errorCode, {
7777
int? statusCode,
7878
this.data,
79+
StackTrace? stacktrace,
7980
this.isRequestCancelledError = false,
8081
}) : code = errorCode.code,
8182
statusCode = statusCode ?? data?.statusCode,
83+
stackTrace = stacktrace ?? StackTrace.current,
8284
super(errorCode.message);
8385

8486
///
@@ -87,8 +89,10 @@ class StreamChatNetworkError extends StreamChatError {
8789
required String message,
8890
this.statusCode,
8991
this.data,
92+
StackTrace? stacktrace,
9093
this.isRequestCancelledError = false,
91-
}) : super(message);
94+
}) : stackTrace = stacktrace ?? StackTrace.current,
95+
super(message);
9296

9397
///
9498
factory StreamChatNetworkError.fromDioException(DioException exception) {
@@ -108,8 +112,9 @@ class StreamChatNetworkError extends StreamChatError {
108112
'',
109113
statusCode: errorResponse?.statusCode ?? response?.statusCode,
110114
data: errorResponse,
115+
stacktrace: exception.stackTrace,
111116
isRequestCancelledError: exception.type == DioExceptionType.cancel,
112-
)..stackTrace = exception.stackTrace;
117+
);
113118
}
114119

115120
/// Error code
@@ -124,10 +129,8 @@ class StreamChatNetworkError extends StreamChatError {
124129
/// True, in case the error is due to a cancelled network request.
125130
final bool isRequestCancelledError;
126131

127-
StackTrace? _stackTrace;
128-
129-
///
130-
set stackTrace(StackTrace? stack) => _stackTrace = stack;
132+
/// The optional stack trace attached to the error.
133+
final StackTrace? stackTrace;
131134

132135
///
133136
ChatErrorCode? get errorCode => chatErrorCodeFromCode(code);
@@ -145,8 +148,8 @@ class StreamChatNetworkError extends StreamChatError {
145148
if (data != null) params += ', data: $data';
146149
var msg = 'StreamChatNetworkError($params)';
147150

148-
if (printStackTrace && _stackTrace != null) {
149-
msg += '\n$_stackTrace';
151+
if (printStackTrace && stackTrace != null) {
152+
msg += '\n$stackTrace';
150153
}
151154
return msg;
152155
}

packages/stream_chat/lib/src/core/http/interceptor/auth_interceptor.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class AuthInterceptor extends QueuedInterceptor {
3030
final dioError = StreamChatDioError(
3131
error: error,
3232
requestOptions: options,
33+
stackTrace: StackTrace.current,
3334
);
3435
return handler.reject(dioError, true);
3536
}

packages/stream_chat/lib/src/core/http/stream_chat_dio_error.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ class StreamChatDioError extends DioException {
99
required super.requestOptions,
1010
super.response,
1111
super.type,
12+
StackTrace? stackTrace,
13+
super.message,
1214
}) : super(
1315
error: error,
16+
stackTrace: stackTrace ?? StackTrace.current,
1417
);
1518

1619
@override

packages/stream_chat/lib/src/core/http/stream_http_client.dart

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,10 @@ class StreamHttpClient {
9797
void close({bool force = false}) => httpClient.close(force: force);
9898

9999
StreamChatNetworkError _parseError(DioException exception) {
100-
StreamChatNetworkError error;
101100
// locally thrown dio error
102-
if (exception is StreamChatDioError) {
103-
error = exception.error;
104-
} else {
105-
// real network request dio error
106-
error = StreamChatNetworkError.fromDioException(exception);
107-
}
108-
return error..stackTrace = exception.stackTrace;
101+
if (exception is StreamChatDioError) return exception.error;
102+
// real network request dio error
103+
return StreamChatNetworkError.fromDioException(exception);
109104
}
110105

111106
/// Handy method to make http GET request with error parsing.

packages/stream_chat/lib/src/core/models/event.dart

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class Event {
2828
this.channelType,
2929
this.parentId,
3030
this.hardDelete,
31+
this.aiState,
32+
this.aiMessage,
33+
this.messageId,
3134
this.extraData = const {},
3235
this.isLocal = true,
3336
}) : createdAt = createdAt?.toUtc() ?? DateTime.now().toUtc();
@@ -102,6 +105,16 @@ class Event {
102105
@JsonKey(includeIfNull: false)
103106
final bool? hardDelete;
104107

108+
/// The current state of the AI assistant.
109+
@JsonKey(unknownEnumValue: AITypingState.idle)
110+
final AITypingState? aiState;
111+
112+
/// Additional message from the AI assistant.
113+
final String? aiMessage;
114+
115+
/// The message id to which the event belongs.
116+
final String? messageId;
117+
105118
/// Map of custom channel extraData
106119
final Map<String, Object?> extraData;
107120

@@ -146,6 +159,9 @@ class Event {
146159
'parent_id',
147160
'hard_delete',
148161
'is_local',
162+
'ai_state',
163+
'ai_message',
164+
'message_id',
149165
];
150166

151167
/// Serialize to json
@@ -174,6 +190,9 @@ class Event {
174190
bool? online,
175191
String? parentId,
176192
bool? hardDelete,
193+
AITypingState? aiState,
194+
String? aiMessage,
195+
String? messageId,
177196
Map<String, Object?>? extraData,
178197
}) =>
179198
Event(
@@ -197,14 +216,15 @@ class Event {
197216
parentId: parentId ?? this.parentId,
198217
hardDelete: hardDelete ?? this.hardDelete,
199218
extraData: extraData ?? this.extraData,
219+
aiState: aiState ?? this.aiState,
220+
aiMessage: aiMessage ?? this.aiMessage,
221+
messageId: messageId ?? this.messageId,
200222
isLocal: isLocal,
201223
);
202224
}
203225

204226
/// The channel embedded in the event object
205-
@JsonSerializable(
206-
createToJson: false,
207-
)
227+
@JsonSerializable(createToJson: false)
208228
class EventChannel extends ChannelModel {
209229
/// Constructor used for json serialization
210230
EventChannel({
@@ -221,12 +241,12 @@ class EventChannel extends ChannelModel {
221241
required DateTime super.updatedAt,
222242
super.deletedAt,
223243
super.memberCount,
224-
Map<String, Object?>? extraData,
225244
super.cooldown,
226245
super.team,
227246
super.disabled,
228247
super.hidden,
229248
super.truncatedAt,
249+
Map<String, Object?>? extraData,
230250
}) : super(extraData: extraData ?? {});
231251

232252
/// Create a new instance from a json
@@ -246,3 +266,31 @@ class EventChannel extends ChannelModel {
246266
...ChannelModel.topLevelFields,
247267
];
248268
}
269+
270+
/// {@template aiState}
271+
/// The current typing state of the AI assistant.
272+
///
273+
/// This is used to determine the state of the AI assistant when it's generating
274+
/// a response for the provided query.
275+
/// {@endtemplate}
276+
enum AITypingState {
277+
/// The AI assistant is idle.
278+
@JsonValue('AI_STATE_IDLE')
279+
idle,
280+
281+
/// The AI assistant is in an error state.
282+
@JsonValue('AI_STATE_ERROR')
283+
error,
284+
285+
/// The AI assistant is checking external sources.
286+
@JsonValue('AI_STATE_CHECKING_SOURCES')
287+
checkingSources,
288+
289+
/// The AI assistant is thinking.
290+
@JsonValue('AI_STATE_THINKING')
291+
thinking,
292+
293+
/// The AI assistant is generating a response.
294+
@JsonValue('AI_STATE_GENERATING')
295+
generating,
296+
}

packages/stream_chat/lib/src/core/models/event.g.dart

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/stream_chat/lib/src/event_type.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ class EventType {
113113
/// Event sent when the user's mutes list is updated
114114
static const String notificationMutesUpdated = 'notification.mutes_updated';
115115

116+
/// Event sent when the AI indicator is updated
117+
static const String aiIndicatorUpdate = 'ai_indicator.update';
118+
119+
/// Event sent when the AI indicator is stopped
120+
static const String aiIndicatorStop = 'ai_indicator.stop';
121+
122+
/// Event sent when the AI indicator is cleared
123+
static const String aiIndicatorClear = 'ai_indicator.clear';
124+
116125
/// Event sent when a poll is updated.
117126
static const String pollUpdated = 'poll.updated';
118127

packages/stream_chat/lib/version.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ import 'package:stream_chat/src/client/client.dart';
33
/// Current package version
44
/// Used in [StreamChatClient] to build the `x-stream-client` header
55
// ignore: constant_identifier_names
6-
const PACKAGE_VERSION = '8.1.0';
6+
const PACKAGE_VERSION = '8.3.0';

0 commit comments

Comments
 (0)