Skip to content

Commit a71f914

Browse files
committed
Merge remote-tracking branch 'origin/feat/poll-message-widget' into feat/poll-persistence
# Conflicts: # packages/stream_chat_persistence/CHANGELOG.md # packages/stream_chat_persistence/pubspec.yaml
2 parents b027e0a + 611560e commit a71f914

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1861
-102
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
@@ -1285,6 +1285,16 @@ class Channel {
12851285
}
12861286
}
12871287

1288+
/// Sends an event to stop AI response generation, leaving the message in
1289+
/// its current state.
1290+
Future<EmptyResponse> stopAIResponse() async {
1291+
return sendEvent(
1292+
Event(
1293+
type: EventType.aiIndicatorStop,
1294+
),
1295+
);
1296+
}
1297+
12881298
/// Update the channel's [name].
12891299
///
12901300
/// This is the same as calling [updatePartial] and providing a map with a
@@ -2106,8 +2116,8 @@ class ChannelClientState {
21062116
final existingWatchers = channelState.watchers;
21072117
updateChannelState(channelState.copyWith(
21082118
watchers: [
2109-
...?existingWatchers,
21102119
watcher,
2120+
...?existingWatchers?.where((user) => user.id != watcher.id),
21112121
],
21122122
));
21132123
}
@@ -2122,9 +2132,9 @@ class ChannelClientState {
21222132
if (watcher != null) {
21232133
final existingWatchers = channelState.watchers;
21242134
updateChannelState(channelState.copyWith(
2125-
watchers: existingWatchers
2126-
?.where((user) => user.id != watcher.id)
2127-
.toList(growable: false),
2135+
watchers: [
2136+
...?existingWatchers?.where((user) => user.id != watcher.id)
2137+
],
21282138
));
21292139
}
21302140
}),
@@ -2706,7 +2716,7 @@ class ChannelClientState {
27062716
channelStateStream.map((cs) => cs.members),
27072717
_channel.client.state.usersStream,
27082718
(members, users) =>
2709-
members!.map((e) => e!.copyWith(user: users[e.user!.id])).toList(),
2719+
[...?members?.map((e) => e!.copyWith(user: users[e.user!.id]))],
27102720
).distinct(const ListEquality().equals);
27112721

27122722
/// Channel watcher count.
@@ -2726,7 +2736,7 @@ class ChannelClientState {
27262736
List<User>?, Map<String?, User?>, List<User>>(
27272737
channelStateStream.map((cs) => cs.watchers),
27282738
_channel.client.state.usersStream,
2729-
(watchers, users) => watchers!.map((e) => users[e.id] ?? e).toList(),
2739+
(watchers, users) => [...?watchers?.map((e) => users[e.id] ?? e)],
27302740
).distinct(const ListEquality().equals);
27312741

27322742
/// 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)