Merge branch 'develop' into feat/pinned
This commit is contained in:
@@ -351,9 +351,13 @@ class Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send a [message] to this 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
|
/// Waits for a [_messageAttachmentsUploadCompleter] to complete
|
||||||
/// before actually sending the message.
|
/// before actually sending the message.
|
||||||
Future<SendMessageResponse> sendMessage(Message message) async {
|
Future<SendMessageResponse> sendMessage(
|
||||||
|
Message message, {
|
||||||
|
bool skipPush = false,
|
||||||
|
}) async {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
// Cancelling previous completer in case it's called again in the process
|
// Cancelling previous completer in case it's called again in the process
|
||||||
// Eg. Updating the message while the previous call is in progress.
|
// Eg. Updating the message while the previous call is in progress.
|
||||||
@@ -396,7 +400,12 @@ class Channel {
|
|||||||
message = await attachmentsUploadCompleter.future;
|
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);
|
state!.addMessage(response.message);
|
||||||
return response;
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1329,11 +1329,15 @@ class StreamChatClient {
|
|||||||
Future<SendMessageResponse> sendMessage(
|
Future<SendMessageResponse> sendMessage(
|
||||||
Message message,
|
Message message,
|
||||||
String channelId,
|
String channelId,
|
||||||
String channelType,
|
String channelType, {
|
||||||
) async {
|
bool skipPush = false,
|
||||||
|
}) async {
|
||||||
final response = await post(
|
final response = await post(
|
||||||
'/channels/$channelType/$channelId/message',
|
'/channels/$channelType/$channelId/message',
|
||||||
data: {'message': message.toJson()},
|
data: {
|
||||||
|
'message': message.toJson(),
|
||||||
|
'skip_push': skipPush,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
return decode(response.data, SendMessageResponse.fromJson);
|
return decode(response.data, SendMessageResponse.fromJson);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ class Message extends Equatable {
|
|||||||
this.extraData = const {},
|
this.extraData = const {},
|
||||||
this.deletedAt,
|
this.deletedAt,
|
||||||
this.status = MessageSendingStatus.sent,
|
this.status = MessageSendingStatus.sent,
|
||||||
this.skipPush = false,
|
|
||||||
}) : id = id ?? const Uuid().v4(),
|
}) : id = id ?? const Uuid().v4(),
|
||||||
pinExpires = pinExpires?.toUtc(),
|
pinExpires = pinExpires?.toUtc(),
|
||||||
createdAt = createdAt ?? DateTime.now(),
|
createdAt = createdAt ?? DateTime.now(),
|
||||||
@@ -158,10 +157,6 @@ class Message extends Equatable {
|
|||||||
@JsonKey(defaultValue: false)
|
@JsonKey(defaultValue: false)
|
||||||
final bool silent;
|
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
|
/// If true the message is shadowed
|
||||||
@JsonKey(
|
@JsonKey(
|
||||||
includeIfNull: false,
|
includeIfNull: false,
|
||||||
@@ -253,7 +248,6 @@ class Message extends Equatable {
|
|||||||
'pinned_at',
|
'pinned_at',
|
||||||
'pin_expires',
|
'pin_expires',
|
||||||
'pinned_by',
|
'pinned_by',
|
||||||
'skip_push',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Serialize to json
|
/// Serialize to json
|
||||||
@@ -291,7 +285,6 @@ class Message extends Equatable {
|
|||||||
User? pinnedBy,
|
User? pinnedBy,
|
||||||
Map<String, Object?>? extraData,
|
Map<String, Object?>? extraData,
|
||||||
MessageSendingStatus? status,
|
MessageSendingStatus? status,
|
||||||
bool? skipPush,
|
|
||||||
}) {
|
}) {
|
||||||
assert(() {
|
assert(() {
|
||||||
if (pinExpires is! DateTime &&
|
if (pinExpires is! DateTime &&
|
||||||
@@ -331,7 +324,6 @@ class Message extends Equatable {
|
|||||||
pinnedBy: pinnedBy ?? this.pinnedBy,
|
pinnedBy: pinnedBy ?? this.pinnedBy,
|
||||||
pinExpires:
|
pinExpires:
|
||||||
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
||||||
skipPush: skipPush ?? this.skipPush,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,7 +390,6 @@ class Message extends Equatable {
|
|||||||
pinnedBy,
|
pinnedBy,
|
||||||
extraData,
|
extraData,
|
||||||
status,
|
status,
|
||||||
skipPush,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ Message _$MessageFromJson(Map<String, dynamic> json) {
|
|||||||
deletedAt: json['deleted_at'] == null
|
deletedAt: json['deleted_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['deleted_at'] as String),
|
: 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));
|
writeNotNull('thread_participants', readonly(instance.threadParticipants));
|
||||||
val['show_in_channel'] = instance.showInChannel;
|
val['show_in_channel'] = instance.showInChannel;
|
||||||
val['silent'] = instance.silent;
|
val['silent'] = instance.silent;
|
||||||
val['skip_push'] = instance.skipPush;
|
|
||||||
writeNotNull('shadowed', readonly(instance.shadowed));
|
writeNotNull('shadowed', readonly(instance.shadowed));
|
||||||
writeNotNull('command', readonly(instance.command));
|
writeNotNull('command', readonly(instance.command));
|
||||||
writeNotNull('created_at', readonly(instance.createdAt));
|
writeNotNull('created_at', readonly(instance.createdAt));
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ void main() {
|
|||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
'/channels/messaging/testid/message',
|
'/channels/messaging/testid/message',
|
||||||
data: {'message': message.toJson()},
|
data: {
|
||||||
|
'message': message.toJson(),
|
||||||
|
'skip_push': false,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
).thenAnswer(
|
).thenAnswer(
|
||||||
(_) async => Response(
|
(_) async => Response(
|
||||||
@@ -67,6 +70,7 @@ void main() {
|
|||||||
verify(() =>
|
verify(() =>
|
||||||
mockDio.post<String>('/channels/messaging/testid/message', data: {
|
mockDio.post<String>('/channels/messaging/testid/message', data: {
|
||||||
'message': message.toJson(),
|
'message': message.toJson(),
|
||||||
|
'skip_push': false,
|
||||||
})).called(1);
|
})).called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -902,7 +902,6 @@ void main() {
|
|||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"skip_push": false,
|
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
@@ -919,7 +918,6 @@ void main() {
|
|||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"skip_push": false,
|
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
@@ -929,7 +927,6 @@ void main() {
|
|||||||
{
|
{
|
||||||
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
|
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
|
||||||
"text": "test message",
|
"text": "test message",
|
||||||
"skip_push": false,
|
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
@@ -952,7 +949,6 @@ void main() {
|
|||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"skip_push": false,
|
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
@@ -964,7 +960,6 @@ void main() {
|
|||||||
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
|
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
|
||||||
"text": "test",
|
"text": "test",
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"skip_push": false,
|
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
@@ -982,7 +977,6 @@ void main() {
|
|||||||
"text": "hi",
|
"text": "hi",
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"skip_push": false,
|
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
@@ -1000,7 +994,6 @@ void main() {
|
|||||||
"attachments": [],
|
"attachments": [],
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"skip_push": false,
|
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
@@ -1023,7 +1016,6 @@ void main() {
|
|||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"skip_push": false,
|
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
@@ -1041,7 +1033,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1053,7 +1044,6 @@ void main() {
|
|||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"skip_push": false,
|
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
@@ -1071,7 +1061,6 @@ void main() {
|
|||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"skip_push": false,
|
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
@@ -1090,7 +1079,6 @@ void main() {
|
|||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"skip_push": false,
|
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
@@ -1100,7 +1088,6 @@ void main() {
|
|||||||
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
|
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
|
||||||
"text": "what are you doing?",
|
"text": "what are you doing?",
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"skip_push": false,
|
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
@@ -1118,7 +1105,6 @@ void main() {
|
|||||||
"text": "👍",
|
"text": "👍",
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"skip_push": false,
|
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
@@ -1134,7 +1120,6 @@ void main() {
|
|||||||
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
|
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
|
||||||
"text": "sdasas",
|
"text": "sdasas",
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"skip_push": false,
|
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
@@ -1155,7 +1140,6 @@ void main() {
|
|||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"skip_push": false,
|
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
"status": "SENT",
|
"status": "SENT",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
@@ -1168,7 +1152,6 @@ void main() {
|
|||||||
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
|
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
|
||||||
"text": "nhisagdhsadz",
|
"text": "nhisagdhsadz",
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
"skip_push": false,
|
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
@@ -1187,7 +1170,6 @@ void main() {
|
|||||||
"attachments": [],
|
"attachments": [],
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"skip_push": false,
|
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
@@ -1204,7 +1186,6 @@ void main() {
|
|||||||
"attachments": [],
|
"attachments": [],
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"quoted_message": null,
|
"quoted_message": null,
|
||||||
"skip_push": false,
|
|
||||||
"quoted_message_id": null,
|
"quoted_message_id": null,
|
||||||
"show_in_channel": null,
|
"show_in_channel": null,
|
||||||
"mentioned_users": [],
|
"mentioned_users": [],
|
||||||
@@ -1212,7 +1193,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1229,7 +1209,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1246,7 +1225,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1263,7 +1241,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1280,7 +1257,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1297,7 +1273,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
},
|
},
|
||||||
@@ -1314,7 +1289,6 @@ void main() {
|
|||||||
"silent": false,
|
"silent": false,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"pinned_at": null,
|
"pinned_at": null,
|
||||||
"skip_push": false,
|
|
||||||
"pin_expires": null,
|
"pin_expires": null,
|
||||||
"pinned_by": null
|
"pinned_by": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,6 @@ void main() {
|
|||||||
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||||
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||||
"silent": false,
|
"silent": false,
|
||||||
"skip_push": false,
|
|
||||||
"attachments": [
|
"attachments": [
|
||||||
{
|
{
|
||||||
"type": "video",
|
"type": "video",
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
|||||||
/// Callback called when tapping on a channel
|
/// Callback called when tapping on a channel
|
||||||
typedef ChannelTapCallback = void Function(Channel, Widget?);
|
typedef ChannelTapCallback = void Function(Channel, Widget?);
|
||||||
|
|
||||||
|
/// Callback called when tapping on a channel
|
||||||
|
typedef ChannelInfoCallback = void Function(Channel);
|
||||||
|
|
||||||
/// Builder used to create a custom [ChannelPreview] from a [Channel]
|
/// Builder used to create a custom [ChannelPreview] from a [Channel]
|
||||||
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
|
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
|
||||||
|
|
||||||
@@ -78,6 +81,9 @@ class ChannelListView extends StatefulWidget {
|
|||||||
this.emptyBuilder,
|
this.emptyBuilder,
|
||||||
this.loadingBuilder,
|
this.loadingBuilder,
|
||||||
this.listBuilder,
|
this.listBuilder,
|
||||||
|
this.onMoreDetailsPressed,
|
||||||
|
this.onDeletePressed,
|
||||||
|
this.swipeActions,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// If true a default swipe to action behaviour will be added to this widget
|
/// If true a default swipe to action behaviour will be added to this widget
|
||||||
@@ -158,6 +164,15 @@ class ChannelListView extends StatefulWidget {
|
|||||||
/// The builder used when the channel list is empty.
|
/// The builder used when the channel list is empty.
|
||||||
final WidgetBuilder? emptyBuilder;
|
final WidgetBuilder? emptyBuilder;
|
||||||
|
|
||||||
|
/// Callback used when the more details slidable option is pressed
|
||||||
|
final ChannelInfoCallback? onMoreDetailsPressed;
|
||||||
|
|
||||||
|
/// Callback used when the delete slidable option is pressed
|
||||||
|
final ChannelInfoCallback? onDeletePressed;
|
||||||
|
|
||||||
|
/// List of actions for slidable
|
||||||
|
final List<SwipeAction>? swipeActions;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ChannelListViewState createState() => _ChannelListViewState();
|
_ChannelListViewState createState() => _ChannelListViewState();
|
||||||
}
|
}
|
||||||
@@ -465,61 +480,79 @@ class _ChannelListViewState extends State<ChannelListView> {
|
|||||||
enabled: widget.swipeToAction,
|
enabled: widget.swipeToAction,
|
||||||
actionPane: const SlidableBehindActionPane(),
|
actionPane: const SlidableBehindActionPane(),
|
||||||
actionExtentRatio: 0.12,
|
actionExtentRatio: 0.12,
|
||||||
secondaryActions: <Widget>[
|
secondaryActions: widget.swipeActions
|
||||||
IconSlideAction(
|
?.map((e) => IconSlideAction(
|
||||||
color: backgroundColor,
|
color: e.color,
|
||||||
icon: Icons.more_horiz,
|
iconWidget: e.iconWidget,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showModalBottomSheet(
|
e.onTap?.call(channel);
|
||||||
clipBehavior: Clip.hardEdge,
|
},
|
||||||
shape: const RoundedRectangleBorder(
|
))
|
||||||
borderRadius: BorderRadius.only(
|
.toList() ??
|
||||||
topLeft: Radius.circular(32),
|
<Widget>[
|
||||||
topRight: Radius.circular(32),
|
IconSlideAction(
|
||||||
),
|
color: backgroundColor,
|
||||||
),
|
icon: Icons.more_horiz,
|
||||||
context: context,
|
onTap: widget.onMoreDetailsPressed != null
|
||||||
builder: (context) => StreamChannel(
|
? () {
|
||||||
channel: channel,
|
widget.onMoreDetailsPressed!(channel);
|
||||||
child: ChannelBottomSheet(
|
}
|
||||||
onViewInfoTap: () {
|
: () {
|
||||||
widget.onViewInfoTap?.call(channel);
|
showModalBottomSheet(
|
||||||
},
|
clipBehavior: Clip.hardEdge,
|
||||||
),
|
shape: const RoundedRectangleBorder(
|
||||||
),
|
borderRadius: BorderRadius.only(
|
||||||
);
|
topLeft: Radius.circular(32),
|
||||||
},
|
topRight: Radius.circular(32),
|
||||||
),
|
),
|
||||||
if ([
|
),
|
||||||
'admin',
|
context: context,
|
||||||
'owner',
|
builder: (context) => StreamChannel(
|
||||||
].contains(channel.state!.members
|
channel: channel,
|
||||||
.firstWhereOrNull(
|
child: ChannelBottomSheet(
|
||||||
(m) => m.userId == channel.client.state.user?.id)
|
onViewInfoTap: () {
|
||||||
?.role))
|
widget.onViewInfoTap?.call(channel);
|
||||||
IconSlideAction(
|
},
|
||||||
color: backgroundColor,
|
),
|
||||||
iconWidget: StreamSvgIcon.delete(
|
),
|
||||||
color: chatThemeData.colorTheme.accentRed,
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
onTap: () async {
|
if ([
|
||||||
final res = await showConfirmationDialog(
|
'admin',
|
||||||
context,
|
'owner',
|
||||||
title: 'Delete Conversation',
|
].contains(channel.state!.members
|
||||||
okText: 'DELETE',
|
.firstWhereOrNull(
|
||||||
question:
|
(m) => m.userId == channel.client.state.user?.id)
|
||||||
'Are you sure you want to delete this conversation?',
|
?.role))
|
||||||
cancelText: 'CANCEL',
|
IconSlideAction(
|
||||||
icon: StreamSvgIcon.delete(
|
color: backgroundColor,
|
||||||
|
iconWidget: StreamSvgIcon.delete(
|
||||||
color: chatThemeData.colorTheme.accentRed,
|
color: chatThemeData.colorTheme.accentRed,
|
||||||
),
|
),
|
||||||
);
|
onTap: widget.onDeletePressed != null
|
||||||
if (res == true) {
|
? () {
|
||||||
await channel.delete();
|
widget.onDeletePressed!(channel);
|
||||||
}
|
}
|
||||||
},
|
: () async {
|
||||||
),
|
final res = await showConfirmationDialog(
|
||||||
],
|
context,
|
||||||
|
title: 'Delete Conversation',
|
||||||
|
okText: 'DELETE',
|
||||||
|
question:
|
||||||
|
// ignore: lines_longer_than_80_chars
|
||||||
|
'Are you sure you want to delete this conversation?',
|
||||||
|
cancelText: 'CANCEL',
|
||||||
|
icon: StreamSvgIcon.delete(
|
||||||
|
color: chatThemeData.colorTheme.accentRed,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (res == true) {
|
||||||
|
await channel.delete();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
child: Container(
|
child: Container(
|
||||||
color: chatThemeData.colorTheme.whiteSnow,
|
color: chatThemeData.colorTheme.whiteSnow,
|
||||||
child: widget.channelPreviewBuilder?.call(context, channel) ??
|
child: widget.channelPreviewBuilder?.call(context, channel) ??
|
||||||
@@ -640,3 +673,22 @@ class _ChannelListViewState extends State<ChannelListView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Class for slidable action
|
||||||
|
class SwipeAction {
|
||||||
|
/// Constructor for creating [SwipeAction]
|
||||||
|
SwipeAction({
|
||||||
|
this.color,
|
||||||
|
required this.iconWidget,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Background color of action
|
||||||
|
Color? color;
|
||||||
|
|
||||||
|
/// Widget to display as icon
|
||||||
|
Widget iconWidget;
|
||||||
|
|
||||||
|
/// Callback when icon is tapped
|
||||||
|
ChannelInfoCallback? onTap;
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class MessageActionsModal extends StatefulWidget {
|
|||||||
this.customActions = const [],
|
this.customActions = const [],
|
||||||
this.attachmentBorderRadiusGeometry,
|
this.attachmentBorderRadiusGeometry,
|
||||||
this.onCopyTap,
|
this.onCopyTap,
|
||||||
|
this.textBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Builder for edit message
|
/// Builder for edit message
|
||||||
@@ -105,6 +106,9 @@ class MessageActionsModal extends StatefulWidget {
|
|||||||
/// List of custom actions
|
/// List of custom actions
|
||||||
final List<MessageAction> customActions;
|
final List<MessageAction> customActions;
|
||||||
|
|
||||||
|
/// Customize the MessageWidget textBuilder
|
||||||
|
final Widget Function(BuildContext context, Message message)? textBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MessageActionsModalState createState() => _MessageActionsModalState();
|
_MessageActionsModalState createState() => _MessageActionsModalState();
|
||||||
}
|
}
|
||||||
@@ -231,6 +235,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
|||||||
shape: widget.messageShape,
|
shape: widget.messageShape,
|
||||||
attachmentShape: widget.attachmentShape,
|
attachmentShape: widget.attachmentShape,
|
||||||
showPinHighlight: false,
|
showPinHighlight: false,
|
||||||
|
textBuilder: widget.textBuilder,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|||||||
@@ -156,9 +156,10 @@ class MessageListView extends StatefulWidget {
|
|||||||
this.onMessageTap,
|
this.onMessageTap,
|
||||||
this.onSystemMessageTap,
|
this.onSystemMessageTap,
|
||||||
this.onAttachmentTap,
|
this.onAttachmentTap,
|
||||||
this.textBuilder,
|
|
||||||
this.onLinkTap,
|
this.onLinkTap,
|
||||||
this.pinPermissions = const [],
|
this.pinPermissions = const [],
|
||||||
|
this.textBuilder,
|
||||||
|
this.usernameBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Function used to build a custom message widget
|
/// Function used to build a custom message widget
|
||||||
@@ -260,7 +261,10 @@ class MessageListView extends StatefulWidget {
|
|||||||
final void Function(Message message, Attachment attachment)? onAttachmentTap;
|
final void Function(Message message, Attachment attachment)? onAttachmentTap;
|
||||||
|
|
||||||
/// Customize the MessageWidget textBuilder
|
/// Customize the MessageWidget textBuilder
|
||||||
final void Function(BuildContext context, Message message)? textBuilder;
|
final Widget Function(BuildContext context, Message message)? textBuilder;
|
||||||
|
|
||||||
|
/// Customize the MessageWidget usernameBuilder
|
||||||
|
final Widget Function(BuildContext context, Message message)? usernameBuilder;
|
||||||
|
|
||||||
/// Callback for when link is tapped
|
/// Callback for when link is tapped
|
||||||
final void Function(String link)? onLinkTap;
|
final void Function(String link)? onLinkTap;
|
||||||
@@ -865,8 +869,8 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
}
|
}
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
},
|
},
|
||||||
textBuilder:
|
textBuilder: widget.textBuilder,
|
||||||
widget.textBuilder as Widget Function(BuildContext, Message)?,
|
usernameBuilder: widget.usernameBuilder,
|
||||||
onLinkTap: widget.onLinkTap,
|
onLinkTap: widget.onLinkTap,
|
||||||
showPinButton: widget.pinPermissions.contains(currentUserMember.role),
|
showPinButton: widget.pinPermissions.contains(currentUserMember.role),
|
||||||
);
|
);
|
||||||
@@ -1070,8 +1074,8 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
},
|
},
|
||||||
onAttachmentTap: widget.onAttachmentTap,
|
onAttachmentTap: widget.onAttachmentTap,
|
||||||
textBuilder:
|
textBuilder: widget.textBuilder,
|
||||||
widget.textBuilder as Widget Function(BuildContext, Message)?,
|
usernameBuilder: widget.usernameBuilder,
|
||||||
onLinkTap: widget.onLinkTap,
|
onLinkTap: widget.onLinkTap,
|
||||||
showPinButton: widget.pinPermissions.contains(currentUserMember.role),
|
showPinButton: widget.pinPermissions.contains(currentUserMember.role),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class MessageReactionsModal extends StatelessWidget {
|
|||||||
this.showUserAvatar = DisplayWidget.show,
|
this.showUserAvatar = DisplayWidget.show,
|
||||||
this.onUserAvatarTap,
|
this.onUserAvatarTap,
|
||||||
this.attachmentBorderRadiusGeometry,
|
this.attachmentBorderRadiusGeometry,
|
||||||
|
this.textBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Message to display reactions of
|
/// Message to display reactions of
|
||||||
@@ -52,6 +53,9 @@ class MessageReactionsModal extends StatelessWidget {
|
|||||||
/// [BorderRadius] to apply to attachments
|
/// [BorderRadius] to apply to attachments
|
||||||
final BorderRadius? attachmentBorderRadiusGeometry;
|
final BorderRadius? attachmentBorderRadiusGeometry;
|
||||||
|
|
||||||
|
/// Customize the MessageWidget textBuilder
|
||||||
|
final Widget Function(BuildContext context, Message message)? textBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final size = MediaQuery.of(context).size;
|
final size = MediaQuery.of(context).size;
|
||||||
@@ -157,6 +161,7 @@ class MessageReactionsModal extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
showReactionPickerIndicator: showReactions &&
|
showReactionPickerIndicator: showReactions &&
|
||||||
(message.status == MessageSendingStatus.sent),
|
(message.status == MessageSendingStatus.sent),
|
||||||
|
textBuilder: textBuilder,
|
||||||
showPinHighlight: false,
|
showPinHighlight: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class MessageWidget extends StatefulWidget {
|
|||||||
this.onQuotedMessageTap,
|
this.onQuotedMessageTap,
|
||||||
this.customActions = const [],
|
this.customActions = const [],
|
||||||
this.onAttachmentTap,
|
this.onAttachmentTap,
|
||||||
|
this.usernameBuilder,
|
||||||
}) : attachmentBuilders = {
|
}) : attachmentBuilders = {
|
||||||
'image': (context, message, attachments) {
|
'image': (context, message, attachments) {
|
||||||
final border = RoundedRectangleBorder(
|
final border = RoundedRectangleBorder(
|
||||||
@@ -267,6 +268,9 @@ class MessageWidget extends StatefulWidget {
|
|||||||
/// Widget builder for building text
|
/// Widget builder for building text
|
||||||
final Widget Function(BuildContext, Message)? textBuilder;
|
final Widget Function(BuildContext, Message)? textBuilder;
|
||||||
|
|
||||||
|
/// Widget builder for building username
|
||||||
|
final Widget Function(BuildContext, Message)? usernameBuilder;
|
||||||
|
|
||||||
/// Function called on long press
|
/// Function called on long press
|
||||||
final void Function(BuildContext, Message)? onMessageActions;
|
final void Function(BuildContext, Message)? onMessageActions;
|
||||||
|
|
||||||
@@ -751,14 +755,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
child: Text(msg, style: widget.messageTheme.replies),
|
child: Text(msg, style: widget.messageTheme.replies),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (showUsername)
|
if (showUsername) _buildUsername(usernameKey),
|
||||||
Text(
|
|
||||||
widget.message.user!.name,
|
|
||||||
maxLines: 1,
|
|
||||||
key: usernameKey,
|
|
||||||
style: widget.messageTheme.messageAuthor,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
if (showTimeStamp)
|
if (showTimeStamp)
|
||||||
Text(
|
Text(
|
||||||
Jiffy(widget.message.createdAt.toLocal()).jm,
|
Jiffy(widget.message.createdAt.toLocal()).jm,
|
||||||
@@ -821,6 +818,19 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildUsername(Key usernameKey) {
|
||||||
|
if (widget.usernameBuilder != null) {
|
||||||
|
return widget.usernameBuilder!(context, widget.message);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
widget.message.user!.name,
|
||||||
|
maxLines: 1,
|
||||||
|
key: usernameKey,
|
||||||
|
style: widget.messageTheme.messageAuthor,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildUrlAttachment() {
|
Widget _buildUrlAttachment() {
|
||||||
final urlAttachment = widget.message.attachments
|
final urlAttachment = widget.message.attachments
|
||||||
.firstWhere((element) => element.ogScrapeUrl != null);
|
.firstWhere((element) => element.ogScrapeUrl != null);
|
||||||
@@ -912,6 +922,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
builder: (context) => StreamChannel(
|
builder: (context) => StreamChannel(
|
||||||
channel: channel,
|
channel: channel,
|
||||||
child: MessageActionsModal(
|
child: MessageActionsModal(
|
||||||
|
textBuilder: widget.textBuilder,
|
||||||
onCopyTap: (message) =>
|
onCopyTap: (message) =>
|
||||||
Clipboard.setData(ClipboardData(text: message.text)),
|
Clipboard.setData(ClipboardData(text: message.text)),
|
||||||
attachmentBorderRadiusGeometry:
|
attachmentBorderRadiusGeometry:
|
||||||
@@ -962,6 +973,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
builder: (context) => StreamChannel(
|
builder: (context) => StreamChannel(
|
||||||
channel: channel,
|
channel: channel,
|
||||||
child: MessageReactionsModal(
|
child: MessageReactionsModal(
|
||||||
|
textBuilder: widget.textBuilder,
|
||||||
attachmentBorderRadiusGeometry:
|
attachmentBorderRadiusGeometry:
|
||||||
widget.attachmentBorderRadiusGeometry as BorderRadius?,
|
widget.attachmentBorderRadiusGeometry as BorderRadius?,
|
||||||
showUserAvatar:
|
showUserAvatar:
|
||||||
|
|||||||
Reference in New Issue
Block a user