Skip to content

Commit f53dc66

Browse files
dhyash-simformaditya-css
authored andcommitted
feat: ✨ Show Pinned Chat First in ChatViewList (#367)
1 parent ede54d8 commit f53dc66

File tree

5 files changed

+93
-5
lines changed

5 files changed

+93
-5
lines changed

lib/chatview.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export 'src/extensions/extensions.dart' show MessageTypes;
3737
export 'src/models/models.dart';
3838
export 'src/utils/chat_view_locale.dart';
3939
export 'src/utils/package_strings.dart';
40-
export 'src/values/enumeration.dart';
40+
export 'src/values/enumeration.dart' hide ChatViewListSortBy;
4141
export 'src/values/typedefs.dart';
4242
export 'src/widgets/action_widgets/camera_action_button.dart';
4343
export 'src/widgets/action_widgets/emoji_picker_action_button.dart';

lib/src/controller/chat_list_view_controller.dart

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,29 @@ import 'dart:async';
2424
import 'package:flutter/material.dart';
2525

2626
import '../models/chat_view_list_item.dart';
27+
import '../values/enumeration.dart';
2728
import '../values/typedefs.dart';
2829

2930
class ChatViewListController {
3031
ChatViewListController({
3132
required List<ChatViewListItem> initialChatList,
3233
required this.scrollController,
3334
this.disposeOtherResources = true,
35+
bool sortEnable = true,
36+
ChatSorter? chatSorter,
3437
}) {
38+
chatListStream = _chatListStreamController.stream.map(
39+
(chatMap) {
40+
final chatList = chatMap.values.toList();
41+
if (sortEnable) {
42+
chatList.sort(
43+
chatSorter ?? ChatViewListSortBy.pinFirstByPinTime.sort,
44+
);
45+
}
46+
return chatList;
47+
},
48+
);
49+
3550
final chatListLength = initialChatList.length;
3651

3752
final chatsMap = {
@@ -64,10 +79,7 @@ class ChatViewListController {
6479
_chatListStreamController =
6580
StreamController<Map<String, ChatViewListItem>>.broadcast();
6681

67-
late final Stream<List<ChatViewListItem>> chatListStream =
68-
_chatListStreamController.stream.map(
69-
(chatMap) => chatMap.values.toList(),
70-
);
82+
late final Stream<List<ChatViewListItem>> chatListStream;
7183

7284
/// Adds a chat to the chat list.
7385
void addChat(ChatViewListItem chat) {

lib/src/extensions/extensions.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,30 @@ extension BuildContextExtension on BuildContext {
216216
ChatBubbleConfiguration? get chatBubbleConfig =>
217217
chatListConfig.chatBubbleConfig;
218218
}
219+
220+
/// Extension methods for nullable [DateTime] objects.
221+
///
222+
/// Provides utility methods for comparing nullable [DateTime] instances.
223+
extension NullableDateTimeExtension on DateTime? {
224+
/// Compares this nullable [DateTime] with another nullable [other].
225+
///
226+
/// Returns:
227+
/// - `0` if both dates are null or occur at the same moment.
228+
/// - A negative value if this date is null (considered earlier)
229+
/// or occurs before [other].
230+
/// - A positive value if [other] is null (considered later)
231+
/// or occurs after this date.
232+
int compareWith(DateTime? other) {
233+
final a = this;
234+
final b = other;
235+
if (a == null && b == null) {
236+
return 0;
237+
} else if (a == null) {
238+
return -1;
239+
} else if (b == null) {
240+
return 1;
241+
} else {
242+
return a.compareTo(b);
243+
}
244+
}
245+
}

lib/src/values/enumeration.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import 'package:chatview_utils/chatview_utils.dart';
2626
import 'package:flutter/material.dart';
2727

28+
import '../extensions/extensions.dart';
29+
import '../models/models.dart';
2830
import '../utils/package_strings.dart';
2931

3032
enum ShowReceiptsIn { all, lastMessage }
@@ -183,3 +185,46 @@ enum PinStatus {
183185
unpinned => Icons.push_pin_outlined,
184186
};
185187
}
188+
189+
/// Enum for different chat list sorting options (for internal use only)
190+
enum ChatViewListSortBy {
191+
/// No sorting applied.
192+
none,
193+
194+
/// Pin chats first (sorted by pin time), then unpinned by message date/time
195+
pinFirstByPinTime;
196+
197+
int sort(ChatViewListItem chat1, ChatViewListItem chat2) {
198+
switch (this) {
199+
case none:
200+
return 0;
201+
case pinFirstByPinTime:
202+
final isChatAPinned = chat1.settings.pinStatus.isPinned;
203+
final isChatBPinned = chat2.settings.pinStatus.isPinned;
204+
205+
// 1. Pinned chats first
206+
if (isChatAPinned && !isChatBPinned) return -1;
207+
if (!isChatAPinned && isChatBPinned) return 1;
208+
209+
// 2. Sort pinned chats by pinTime descending (latest first)
210+
if (isChatAPinned && isChatBPinned) {
211+
final pinTimeA = chat1.settings.pinTime;
212+
final pinTimeB = chat2.settings.pinTime;
213+
if (pinTimeA != null && pinTimeB != null) {
214+
return pinTimeB.compareTo(pinTimeA);
215+
}
216+
// If one has null pinTime, treat it as older
217+
if (pinTimeA == null && pinTimeB != null) return 1;
218+
if (pinTimeA != null && pinTimeB == null) return -1;
219+
}
220+
221+
// 3. Sort unpinned chats by message date/time (newest first)
222+
if (!isChatAPinned && !isChatBPinned) {
223+
final chatBCreateAt = chat2.lastMessage?.createdAt;
224+
return chatBCreateAt.compareWith(chat1.lastMessage?.createdAt);
225+
}
226+
227+
return 0;
228+
}
229+
}
230+
}

lib/src/values/typedefs.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,7 @@ typedef ChatViewListTileBuilder = Widget Function(
136136
typedef UserAvatarBuilder = Widget Function(ChatViewListItem chat);
137137
typedef UserNameBuilder = Widget Function(ChatViewListItem chat);
138138
typedef TrailingBuilder = Widget Function(ChatViewListItem chat);
139+
typedef ChatSorter = int Function(
140+
ChatViewListItem chat1,
141+
ChatViewListItem chat2,
142+
);

0 commit comments

Comments
 (0)