Merge branch 'develop' into perf
This commit is contained in:
@@ -354,9 +354,13 @@ class Channel {
|
||||
}
|
||||
|
||||
/// Send a [message] to this channel.
|
||||
/// If [skipPush] is true the message will not send a push notification
|
||||
/// Waits for a [_messageAttachmentsUploadCompleter] to complete
|
||||
/// before actually sending the message.
|
||||
Future<SendMessageResponse> sendMessage(Message message) async {
|
||||
Future<SendMessageResponse> sendMessage(
|
||||
Message message, {
|
||||
bool skipPush = false,
|
||||
}) async {
|
||||
_checkInitialized();
|
||||
// Cancelling previous completer in case it's called again in the process
|
||||
// Eg. Updating the message while the previous call is in progress.
|
||||
@@ -399,7 +403,12 @@ class Channel {
|
||||
message = await attachmentsUploadCompleter.future;
|
||||
}
|
||||
|
||||
final response = await _client.sendMessage(message, id!, type);
|
||||
final response = await _client.sendMessage(
|
||||
message,
|
||||
id!,
|
||||
type,
|
||||
skipPush: skipPush,
|
||||
);
|
||||
state!.addMessage(response.message);
|
||||
return response;
|
||||
} catch (error) {
|
||||
@@ -414,6 +423,9 @@ class Channel {
|
||||
/// Waits for a [_messageAttachmentsUploadCompleter] to complete
|
||||
/// before actually updating the message.
|
||||
Future<UpdateMessageResponse> updateMessage(Message message) async {
|
||||
final currentMessage =
|
||||
state?.messages.firstWhere((e) => e.id == message.id);
|
||||
|
||||
// Cancelling previous completer in case it's called again in the process
|
||||
// Eg. Updating the message while the previous call is in progress.
|
||||
_messageAttachmentsUploadCompleter
|
||||
@@ -458,6 +470,31 @@ class Channel {
|
||||
|
||||
state?.addMessage(m);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
if (error is DioError && error.type != DioErrorType.response) {
|
||||
state?.retryQueue?.add([message]);
|
||||
} else if (error is ApiError) {
|
||||
if (currentMessage != null) {
|
||||
state?.addMessage(currentMessage);
|
||||
}
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Partially updates the [message] in this channel.
|
||||
Future<UpdateMessageResponse> partiallyUpdateMessage(
|
||||
Message message, Map data) async {
|
||||
try {
|
||||
final response = await _client.partiallyUpdateMessage(message.id, data);
|
||||
|
||||
final m = response.message.copyWith(
|
||||
ownReactions: message.ownReactions,
|
||||
);
|
||||
|
||||
state?.addMessage(m);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
if (error is DioError && error.type != DioErrorType.response) {
|
||||
@@ -530,17 +567,21 @@ class Channel {
|
||||
Duration(seconds: timeoutOrExpirationDate.toInt()),
|
||||
);
|
||||
}
|
||||
return updateMessage(
|
||||
message.copyWith(
|
||||
pinned: true,
|
||||
pinExpires: pinExpires,
|
||||
),
|
||||
);
|
||||
return partiallyUpdateMessage(message, {
|
||||
'set': {
|
||||
'pinned': true,
|
||||
if (pinExpires != null) 'pin_expires': pinExpires.toIso8601String(),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Unpins provided message
|
||||
Future<UpdateMessageResponse> unpinMessage(Message message) =>
|
||||
updateMessage(message.copyWith(pinned: false));
|
||||
partiallyUpdateMessage(message, {
|
||||
'set': {
|
||||
'pinned': false,
|
||||
}
|
||||
});
|
||||
|
||||
/// Send a file to this channel
|
||||
Future<SendFileResponse> sendFile(
|
||||
|
||||
@@ -315,7 +315,7 @@ class StreamChatClient {
|
||||
await connectUser(User(id: userId), newToken);
|
||||
|
||||
try {
|
||||
handler.resolve(
|
||||
return handler.resolve(
|
||||
await httpClient.request(
|
||||
err.requestOptions.path,
|
||||
cancelToken: err.requestOptions.cancelToken,
|
||||
@@ -343,10 +343,12 @@ class StreamChatClient {
|
||||
),
|
||||
);
|
||||
} on DioError {
|
||||
handler.reject(err);
|
||||
return handler.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handler.next(err);
|
||||
}
|
||||
|
||||
LogHandlerFunction _getDefaultLogHandler() {
|
||||
@@ -1327,11 +1329,15 @@ class StreamChatClient {
|
||||
Future<SendMessageResponse> sendMessage(
|
||||
Message message,
|
||||
String channelId,
|
||||
String channelType,
|
||||
) async {
|
||||
String channelType, {
|
||||
bool skipPush = false,
|
||||
}) async {
|
||||
final response = await post(
|
||||
'/channels/$channelType/$channelId/message',
|
||||
data: {'message': message.toJson()},
|
||||
data: {
|
||||
'message': message.toJson(),
|
||||
'skip_push': skipPush,
|
||||
},
|
||||
);
|
||||
return decode(response.data, SendMessageResponse.fromJson);
|
||||
}
|
||||
@@ -1345,6 +1351,20 @@ class StreamChatClient {
|
||||
return decode(response.data, UpdateMessageResponse.fromJson);
|
||||
}
|
||||
|
||||
/// Partially update the given message
|
||||
/// Use 'set' in map to set values
|
||||
/// User 'unset' in map to unset values
|
||||
Future<UpdateMessageResponse> partiallyUpdateMessage(
|
||||
String id,
|
||||
Map data,
|
||||
) async {
|
||||
final response = await put(
|
||||
'/messages/$id',
|
||||
data: data,
|
||||
);
|
||||
return decode(response.data, UpdateMessageResponse.fromJson);
|
||||
}
|
||||
|
||||
/// Deletes the given message
|
||||
Future<EmptyResponse> deleteMessage(Message message) async {
|
||||
final response = await delete('/messages/${message.id}');
|
||||
@@ -1383,20 +1403,21 @@ class StreamChatClient {
|
||||
)
|
||||
.toUtc();
|
||||
}
|
||||
return updateMessage(
|
||||
message.copyWith(
|
||||
pinned: true,
|
||||
pinExpires: pinExpires,
|
||||
),
|
||||
);
|
||||
return partiallyUpdateMessage(message.id, {
|
||||
'set': {
|
||||
'pinned': true,
|
||||
if (pinExpires != null) 'pin_expires': pinExpires.toIso8601String(),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Unpins provided message
|
||||
Future<UpdateMessageResponse> unpinMessage(Message message) => updateMessage(
|
||||
message.copyWith(
|
||||
pinned: false,
|
||||
),
|
||||
);
|
||||
Future<UpdateMessageResponse> unpinMessage(Message message) =>
|
||||
partiallyUpdateMessage(message.id, {
|
||||
'set': {
|
||||
'pinned': false,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// The class that handles the state of the channel listening to the events
|
||||
|
||||
@@ -73,7 +73,6 @@ class Message extends Equatable {
|
||||
this.extraData = const {},
|
||||
this.deletedAt,
|
||||
this.status = MessageSendingStatus.sent,
|
||||
this.skipPush = false,
|
||||
}) : id = id ?? const Uuid().v4(),
|
||||
pinExpires = pinExpires?.toUtc(),
|
||||
createdAt = createdAt ?? DateTime.now(),
|
||||
@@ -158,10 +157,6 @@ class Message extends Equatable {
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool silent;
|
||||
|
||||
/// If true the message will not send a push notification
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool skipPush;
|
||||
|
||||
/// If true the message is shadowed
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
@@ -253,7 +248,6 @@ class Message extends Equatable {
|
||||
'pinned_at',
|
||||
'pin_expires',
|
||||
'pinned_by',
|
||||
'skip_push',
|
||||
];
|
||||
|
||||
/// Serialize to json
|
||||
@@ -291,7 +285,6 @@ class Message extends Equatable {
|
||||
User? pinnedBy,
|
||||
Map<String, Object?>? extraData,
|
||||
MessageSendingStatus? status,
|
||||
bool? skipPush,
|
||||
}) {
|
||||
assert(() {
|
||||
if (pinExpires is! DateTime &&
|
||||
@@ -331,7 +324,6 @@ class Message extends Equatable {
|
||||
pinnedBy: pinnedBy ?? this.pinnedBy,
|
||||
pinExpires:
|
||||
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
||||
skipPush: skipPush ?? this.skipPush,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -366,7 +358,6 @@ class Message extends Equatable {
|
||||
pinnedAt: other.pinnedAt,
|
||||
pinExpires: other.pinExpires,
|
||||
pinnedBy: other.pinnedBy,
|
||||
skipPush: other.skipPush,
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -399,7 +390,6 @@ class Message extends Equatable {
|
||||
pinnedBy,
|
||||
extraData,
|
||||
status,
|
||||
skipPush,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ Message _$MessageFromJson(Map<String, dynamic> json) {
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
skipPush: json['skip_push'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,7 +96,6 @@ Map<String, dynamic> _$MessageToJson(Message instance) {
|
||||
writeNotNull('thread_participants', readonly(instance.threadParticipants));
|
||||
val['show_in_channel'] = instance.showInChannel;
|
||||
val['silent'] = instance.silent;
|
||||
val['skip_push'] = instance.skipPush;
|
||||
writeNotNull('shadowed', readonly(instance.shadowed));
|
||||
writeNotNull('command', readonly(instance.command));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
|
||||
@@ -52,7 +52,10 @@ void main() {
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/channels/messaging/testid/message',
|
||||
data: {'message': message.toJson()},
|
||||
data: {
|
||||
'message': message.toJson(),
|
||||
'skip_push': false,
|
||||
},
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
@@ -67,6 +70,7 @@ void main() {
|
||||
verify(() =>
|
||||
mockDio.post<String>('/channels/messaging/testid/message', data: {
|
||||
'message': message.toJson(),
|
||||
'skip_push': false,
|
||||
})).called(1);
|
||||
});
|
||||
|
||||
@@ -430,7 +434,7 @@ void main() {
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: anything,
|
||||
),
|
||||
@@ -445,7 +449,7 @@ void main() {
|
||||
await channelClient.pinMessage(message, 30);
|
||||
|
||||
verify(() =>
|
||||
mockDio.post<String>('/messages/${message.id}', data: anything))
|
||||
mockDio.put<String>('/messages/${message.id}', data: anything))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
@@ -475,7 +479,7 @@ void main() {
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: anything,
|
||||
),
|
||||
@@ -490,7 +494,7 @@ void main() {
|
||||
await channelClient.pinMessage(message);
|
||||
|
||||
verify(() =>
|
||||
mockDio.post<String>('/messages/${message.id}', data: anything))
|
||||
mockDio.put<String>('/messages/${message.id}', data: anything))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
@@ -520,7 +524,7 @@ void main() {
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: anything,
|
||||
),
|
||||
@@ -535,7 +539,7 @@ void main() {
|
||||
await channelClient.unpinMessage(message);
|
||||
|
||||
verify(() =>
|
||||
mockDio.post<String>('/messages/${message.id}', data: anything))
|
||||
mockDio.put<String>('/messages/${message.id}', data: anything))
|
||||
.called(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -745,6 +745,39 @@ void main() {
|
||||
data: {'message': anything})).called(1);
|
||||
});
|
||||
|
||||
test('partiallyUpdateMessage', () async {
|
||||
final mockDio = MockDio();
|
||||
|
||||
when(() => mockDio.options).thenReturn(BaseOptions());
|
||||
when(() => mockDio.interceptors).thenReturn(Interceptors());
|
||||
|
||||
final client = StreamChatClient('api-key', httpClient: mockDio);
|
||||
final message = Message(
|
||||
id: 'test',
|
||||
text: 'demo',
|
||||
);
|
||||
|
||||
when(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: {'set': anything},
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
);
|
||||
|
||||
await client.partiallyUpdateMessage(message.id, {
|
||||
'set': {'text': message.text}
|
||||
});
|
||||
|
||||
verify(() => mockDio.put<String>('/messages/${message.id}',
|
||||
data: {'set': anything})).called(1);
|
||||
});
|
||||
|
||||
test('deleteMessage', () async {
|
||||
final mockDio = MockDio();
|
||||
|
||||
@@ -1094,7 +1127,7 @@ void main() {
|
||||
final message = Message(text: 'Hello');
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: anything,
|
||||
),
|
||||
@@ -1108,15 +1141,15 @@ void main() {
|
||||
|
||||
await client.pinMessage(message, timeout);
|
||||
|
||||
verify(() => mockDio.post<String>('/messages/${message.id}',
|
||||
data: {'message': anything})).called(1);
|
||||
verify(() => mockDio.put<String>('/messages/${message.id}',
|
||||
data: {'set': anything})).called(1);
|
||||
});
|
||||
|
||||
test('should complete successfully with a null value', () async {
|
||||
final message = Message(text: 'Hello');
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: anything,
|
||||
),
|
||||
@@ -1130,15 +1163,15 @@ void main() {
|
||||
|
||||
await client.pinMessage(message);
|
||||
|
||||
verify(() => mockDio.post<String>('/messages/${message.id}',
|
||||
data: {'message': anything})).called(1);
|
||||
verify(() => mockDio.put<String>('/messages/${message.id}',
|
||||
data: {'set': anything})).called(1);
|
||||
});
|
||||
|
||||
test('should unpin message successfully', () async {
|
||||
final message = Message(text: 'Hello');
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
() => mockDio.put<String>(
|
||||
'/messages/${message.id}',
|
||||
data: anything,
|
||||
),
|
||||
@@ -1152,7 +1185,7 @@ void main() {
|
||||
|
||||
await client.unpinMessage(message);
|
||||
|
||||
verify(() => mockDio.post<String>('/messages/${message.id}',
|
||||
verify(() => mockDio.put<String>('/messages/${message.id}',
|
||||
data: anything)).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -902,7 +902,6 @@ void main() {
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"skip_push": false,
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
@@ -919,7 +918,6 @@ void main() {
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"skip_push": false,
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
@@ -929,7 +927,6 @@ void main() {
|
||||
{
|
||||
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
|
||||
"text": "test message",
|
||||
"skip_push": false,
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
@@ -952,7 +949,6 @@ void main() {
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"skip_push": false,
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
@@ -964,7 +960,6 @@ void main() {
|
||||
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
|
||||
"text": "test",
|
||||
"attachments": [],
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -982,7 +977,6 @@ void main() {
|
||||
"text": "hi",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"skip_push": false,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
@@ -1000,7 +994,6 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1023,7 +1016,6 @@ void main() {
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"skip_push": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
@@ -1041,7 +1033,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1053,7 +1044,6 @@ void main() {
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"skip_push": false,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
@@ -1071,7 +1061,6 @@ void main() {
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"skip_push": false,
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
@@ -1090,7 +1079,6 @@ void main() {
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"skip_push": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
@@ -1100,7 +1088,6 @@ void main() {
|
||||
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
|
||||
"text": "what are you doing?",
|
||||
"attachments": [],
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1118,7 +1105,6 @@ void main() {
|
||||
"text": "👍",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"skip_push": false,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
@@ -1134,7 +1120,6 @@ void main() {
|
||||
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
|
||||
"text": "sdasas",
|
||||
"attachments": [],
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1155,7 +1140,6 @@ void main() {
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"skip_push": false,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
@@ -1168,7 +1152,6 @@ void main() {
|
||||
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
|
||||
"text": "nhisagdhsadz",
|
||||
"attachments": [],
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1187,7 +1170,6 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1204,7 +1186,6 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1212,7 +1193,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1229,7 +1209,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1246,7 +1225,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1263,7 +1241,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1280,7 +1257,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1297,7 +1273,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1314,7 +1289,6 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
}
|
||||
|
||||
@@ -133,7 +133,6 @@ void main() {
|
||||
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"silent": false,
|
||||
"skip_push": false,
|
||||
"attachments": [
|
||||
{
|
||||
"type": "video",
|
||||
|
||||
Reference in New Issue
Block a user