Skip to content

Commit 798cc9b

Browse files
feat: ✨ Implement chat list UI components including app bar, controller, and example page
1 parent c9da40e commit 798cc9b

29 files changed

+1375
-1051
lines changed
Lines changed: 71 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import 'package:chatview/chatview.dart';
22
import 'package:flutter/material.dart';
33

4-
import 'main.dart';
4+
import 'chat_view_screen.dart';
5+
import 'data.dart';
56

67
class ChatViewListScreen extends StatefulWidget {
78
const ChatViewListScreen({super.key});
@@ -11,144 +12,88 @@ class ChatViewListScreen extends StatefulWidget {
1112
}
1213

1314
class _ChatViewListScreenState extends State<ChatViewListScreen> {
14-
late final ChatViewListController controller;
15+
ChatViewListController? controller;
1516

17+
// Assign the controller in didChangeDependencies
18+
// to ensure PrimaryScrollController is available.
1619
@override
17-
void initState() {
18-
final now = DateTime.now().toUtc();
19-
final fiveMinAgo = now.subtract(const Duration(minutes: 5));
20-
final today = DateTime(now.year, now.month, now.day);
21-
final yesterday = DateTime(now.year, now.month, now.day - 1);
22-
final lastMessageTime = DateTime.parse('2025-06-06T13:58:00.000Z');
23-
var initialUsersList = [
24-
ChatViewListModel(
25-
id: '1',
26-
name: 'Breaking Bad',
27-
lastMessage: Message(
28-
message:
29-
'I am not in danger, Skyler. I am the danger. A guy opens his door and gets shot and you think that of me? No. I am the one who knocks!',
30-
createdAt: now,
31-
sentBy: '2',
32-
id: '1',
33-
status: MessageStatus.read,
34-
),
35-
unreadCount: 1,
36-
imageUrl:
37-
'https://m.media-amazon.com/images/M/MV5BMzU5ZGYzNmQtMTdhYy00OGRiLTg0NmQtYjVjNzliZTg1ZGE4XkEyXkFqcGc@._V1_.jpg',
38-
chatType: ChatType.group,
39-
),
40-
ChatViewListModel(
41-
id: '2',
42-
name: 'Heisenberg',
43-
lastMessage: Message(
44-
message: 'Say my name!!',
45-
createdAt: fiveMinAgo,
46-
sentBy: '3',
47-
id: '2',
48-
status: MessageStatus.read,
49-
),
50-
imageUrl:
51-
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTzc87OtZ7mZe-kca89Mfi4o1--95dQI7Ne-w&s',
52-
unreadCount: 2,
53-
userActiveStatus: UserActiveStatus.online,
54-
),
55-
ChatViewListModel(
56-
id: '3',
57-
name: 'Jessie Pinkman',
58-
lastMessage: Message(
59-
message: 'Yeah....!!!!',
60-
createdAt: today,
61-
sentBy: '4',
62-
id: '3',
63-
status: MessageStatus.read,
64-
),
65-
imageUrl: 'https://i.insider.com/5d9f454ee94e865e924818da?width=700',
66-
),
67-
ChatViewListModel(
68-
id: '4',
69-
name: 'Walter White',
70-
lastMessage: Message(
71-
message: 'Whats up?',
72-
createdAt: yesterday,
73-
sentBy: '4',
74-
id: '4',
75-
status: MessageStatus.read,
76-
),
77-
imageUrl:
78-
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS1Efw6_noLe4BzEsbgsfHIhvZNqWKaDtckdQ&s',
79-
),
80-
ChatViewListModel(
81-
id: '5',
82-
name: 'Hank Schrader',
83-
lastMessage: Message(
84-
message: 'Hello',
85-
createdAt: lastMessageTime,
86-
sentBy: '6',
87-
id: '5',
88-
status: MessageStatus.read,
89-
),
90-
imageUrl:
91-
'https://upload.wikimedia.org/wikipedia/en/d/db/Hank_Schrader_S5B.png',
92-
),
93-
];
94-
95-
controller = ChatViewListController(
96-
initialUsersList: initialUsersList,
97-
scrollController: ScrollController(),
20+
void didChangeDependencies() {
21+
super.didChangeDependencies();
22+
controller ??= ChatViewListController(
23+
initialChatList: Data.chatList(),
24+
scrollController: PrimaryScrollController.of(context),
9825
);
99-
super.initState();
10026
}
10127

102-
@override
103-
void dispose() {
104-
controller.dispose();
105-
super.dispose();
106-
}
28+
final _searchController = TextEditingController();
10729

10830
@override
10931
Widget build(BuildContext context) {
11032
return Scaffold(
111-
body: ChatViewList(
112-
controller: controller,
113-
appbar: const ChatViewListAppBar(
114-
title: 'Breaking Bad',
115-
),
116-
config: ChatViewListConfig(
117-
chatViewListTileConfig: ChatViewListTileConfig(
118-
backgroundColor: Colors.blue,
119-
onTap: (user) {
120-
Navigator.of(context).push(
121-
MaterialPageRoute(
122-
builder: (context) => ChatScreen(
123-
user: user,
33+
body: controller == null
34+
? const Center(child: CircularProgressIndicator())
35+
: ChatViewList(
36+
controller: controller!,
37+
appbar: const ChatViewListAppBar(
38+
titleText: 'Breaking Bad',
39+
),
40+
loadMoreChats: () async =>
41+
await Future.delayed(const Duration(seconds: 2)),
42+
config: ChatViewListConfig(
43+
enablePagination: true,
44+
loadMoreConfig: const LoadMoreConfig(),
45+
tileConfig: ListTileConfig(
46+
unreadCountConfig: const UnreadCountConfig(
47+
backgroundColor: Colors.red,
48+
style: UnreadCountStyle.ninetyNinePlus,
49+
),
50+
userActiveStatusConfig: const UserActiveStatusConfig(
51+
color: Colors.red,
52+
),
53+
userAvatarConfig: const UserAvatarConfig(
54+
backgroundColor: Colors.blue,
55+
),
56+
onTap: (chat) {
57+
Navigator.of(context).push(
58+
MaterialPageRoute(
59+
builder: (context) => ChatViewScreen(
60+
chat: chat,
61+
),
62+
),
63+
);
64+
},
65+
onLongPress: (chat) {
66+
debugPrint('Long pressed on chat: ${chat.name}');
67+
},
68+
),
69+
searchConfig: ChatViewListSearchConfig(
70+
textEditingController: _searchController,
71+
onSearch: (value) async {
72+
if (value.isEmpty) {
73+
return null;
74+
}
75+
final list = controller?.initialChatList
76+
.where((chat) => chat.name
77+
.toLowerCase()
78+
.contains(value.toLowerCase()))
79+
.toList();
80+
return list;
81+
},
82+
border: const OutlineInputBorder(
83+
borderRadius: BorderRadius.all(
84+
Radius.circular(10),
85+
),
12486
),
12587
),
126-
);
127-
},
128-
onLongPress: (user) {
129-
debugPrint('Long pressed on user: ${user.name}');
130-
},
131-
),
132-
searchConfig: SearchConfig(
133-
textEditingController: TextEditingController(),
134-
onSearch: (value) async {
135-
if (value.isEmpty) {
136-
return null;
137-
}
138-
final list = controller.initialUsersList
139-
.where((user) =>
140-
user.name.toLowerCase().contains(value.toLowerCase()))
141-
.toList();
142-
return list;
143-
},
144-
border: const OutlineInputBorder(
145-
borderRadius: BorderRadius.all(
146-
Radius.circular(10),
14788
),
14889
),
149-
),
150-
),
151-
),
15290
);
15391
}
92+
93+
@override
94+
void dispose() {
95+
controller?.dispose();
96+
_searchController.dispose();
97+
super.dispose();
98+
}
15499
}

0 commit comments

Comments
 (0)