Skip to content

Commit 4eddfb9

Browse files
feat: ✨ Show Pinned Chat First in ChatViewList
1 parent b4ac82b commit 4eddfb9

File tree

5 files changed

+94
-5
lines changed

5 files changed

+94
-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/chat_view.dart';
4343
export 'src/widgets/chat_view_appbar.dart';

lib/src/controller/chat_list_view_controller.dart

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,28 @@ 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,
34+
bool sortEnable = true,
35+
ChatSorter? chatSorter,
3336
}) {
37+
chatListStream = _chatListStreamController.stream.map(
38+
(chatMap) {
39+
final chatList = chatMap.values.toList();
40+
if (sortEnable) {
41+
chatList.sort(
42+
chatSorter ?? ChatViewListSortBy.pinFirstByPinTime.sort,
43+
);
44+
}
45+
return chatList;
46+
},
47+
);
48+
3449
final chatListLength = initialChatList.length;
3550

3651
final chatsMap = {
@@ -61,10 +76,7 @@ class ChatViewListController {
6176
_chatListStreamController =
6277
StreamController<Map<String, ChatViewListItem>>.broadcast();
6378

64-
late final Stream<List<ChatViewListItem>> chatListStream =
65-
_chatListStreamController.stream.map(
66-
(chatMap) => chatMap.values.toList(),
67-
);
79+
late final Stream<List<ChatViewListItem>> chatListStream;
6880

6981
/// Adds a chat to the chat list.
7082
void addChat(ChatViewListItem chat) {

lib/src/extensions/extensions.dart

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

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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,8 @@ typedef ChatStatusCallback<T> = void Function(
124124
({ChatViewListItem chat, T status}) result,
125125
);
126126
typedef StatusTrailingIcon<T> = IconData Function(T status);
127+
128+
typedef ChatSorter = int Function(
129+
ChatViewListItem chat1,
130+
ChatViewListItem chat2,
131+
);

0 commit comments

Comments
 (0)