Appearance
Overview
- File:
lib/widgets/chat_window.dart
The ChatWindow is a Flutter widget that provides a chat interface for the HVC Mobile application. It supports both regular chat functionality and in-call chat features, with capabilities for sending messages, viewing message history, and managing chat participants.
Class Structure
Class Definition
dart
class ChatWindow extends StatelessWidget {
final RxList<Message> messageList;
final RxBool loading;
final PagingController<int, Message> pagingController;
final Future Function() loader;
final double width, height;
final int userId;
final Function()? onCloseOrCancel;
final Function(String) sendMessage;
final bool showNotification;
final Function(bool) onNotificationChange;
final Function(InCallChatOption?)? onInCallChatOptionChange;
final ScrollController scrollController;
final bool isForCallPage;
final RxList<InCallChatOption>? options;
ChatWindow({
Key? key,
required this.messageList,
required this.width,
required this.userId,
required this.height,
this.onCloseOrCancel,
required this.sendMessage,
required this.onNotificationChange,
required this.showNotification,
required this.loading,
required this.pagingController,
required this.loader,
required this.scrollController,
this.isForCallPage = false,
this.options,
this.onInCallChatOptionChange,
}) : super(key: key);
}Supporting Classes
dart
class InCallChatOption {
final String name;
final int id;
InCallChatOption({required this.name, required this.id});
}
class LabeledSwitch extends StatelessWidget {
const LabeledSwitch({
Key? key,
required this.label,
required this.value,
required this.onChanged,
}) : super(key: key);
final String label;
final bool value;
final ValueChanged<bool> onChanged;
// Implementation...
}Dependencies
Required Packages
flutter/material.dart- Core Flutter UI componentsget/get_rx/src/rx_types/rx_types.dart- Reactive state typesget/get_state_manager/src/rx_flutter/rx_obx_widget.dart- Reactive widgetsinfinite_scroll_pagination- Infinite scrolling functionality
Internal Dependencies
models/core_models.dart- Data modelsshared/constants.dart- Shared constantswidgets/message_item.dart- Message display widgetwidgets/no_item_loader.dart- Empty state widget
State Management
State Variables
dart
final TextEditingController smsController = TextEditingController(text: '');
RxBool hasText = false.obs;
final _formKey = GlobalKey<FormState>();Reactive State
dart
Obx(() {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (scrollController.hasClients) {
scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
}
});
return PagedListView<int, Message>(
// Implementation...
);
})UI Components
Main Container
dart
Container(
height: height,
width: width,
color: kAppColorWhite,
child: Column(
children: [
Expanded(
child: Obx(
() => loading.isTrue && messageList.isEmpty
? const Center(child: CircularProgressIndicator())
: RefreshIndicator(
child: isForCallPage
? Column(
children: [
// In-call chat header
// Message list
],
)
: listview,
onRefresh: () async {
await loader();
},
),
),
),
// Message input area
],
),
)Message List
dart
PagedListView<int, Message>(
pagingController: pagingController,
scrollController: scrollController,
padding: const EdgeInsets.all(8),
builderDelegate: PagedChildBuilderDelegate<Message>(
animateTransitions: messageList.isNotEmpty,
itemBuilder: (BuildContext context, Message message, int index) =>
Container(
margin: index == messageList.length - 1
? const EdgeInsets.only(bottom: 32)
: null,
child: MessageItem(
message: message,
isMe: message.fromId == userId,
),
),
noItemsFoundIndicatorBuilder: (BuildContext context) => NoItemLoader(
message: 'No Messages present',
onTapHandler: () async => await loader(),
),
),
)Message Input Area
dart
Container(
decoration: BoxDecoration(
border: hasText.value ? Border.all(color: kAppColorBlue) : null,
color: kAppColorWhite,
borderRadius: BorderRadius.circular(5),
),
margin: const EdgeInsets.all(8),
child: Form(
key: _formKey,
child: Row(
children: [
Expanded(
child: TextField(
controller: smsController,
minLines: 1,
maxLines: 4,
keyboardType: TextInputType.multiline,
style: hasText.value
? const TextStyle(color: kAppColorBlack)
: null,
decoration: InputDecoration(
filled: true,
hintText: 'Enter message',
suffixIcon: Obx(
() => IconButton(
onPressed: hasText.value
? () {
if (smsController.text.isNotEmpty) {
scrollController.animateTo(
scrollController.position.maxScrollExtent + 64,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
sendMessage(smsController.text);
smsController.clear();
}
}
: null,
icon: const Icon(Icons.send),
),
),
),
autofocus: hasText.value,
onChanged: (String text) {
hasText.value = smsController.text.isNotEmpty;
},
),
),
const IconButton(
onPressed: null,
icon: Icon(Icons.attach_file),
),
],
),
),
)Message Handling
Sending Messages
dart
onPressed: hasText.value
? () {
if (smsController.text.isNotEmpty) {
scrollController.animateTo(
scrollController.position.maxScrollExtent + 64,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
sendMessage(smsController.text);
smsController.clear();
}
}
: null,Message Display
dart
MessageItem(
message: message,
isMe: message.fromId == userId,
)Empty State Handling
dart
noItemsFoundIndicatorBuilder: (BuildContext context) => NoItemLoader(
message: 'No Messages present',
onTapHandler: () async => await loader(),
),In-Call Chat Features
In-Call Chat Header
dart
Container(
color: kAppColorBlue,
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Row(
children: [
Expanded(
child: DropdownButtonFormField<InCallChatOption>(
decoration: getInputDecorationNoBorder(
'Chat With:', false,
style: whiteTextStyle),
value: options?.first,
onChanged: (InCallChatOption? newValue) {
if (onInCallChatOptionChange != null) {
onInCallChatOptionChange!(newValue);
}
},
items: options?.map<DropdownMenuItem<InCallChatOption>>(
(InCallChatOption value) {
return DropdownMenuItem<InCallChatOption>(
value: value,
child: Text(value.name),
);
}).toList(),
),
),
IconButton(
onPressed: onCloseOrCancel,
icon: const Icon(Icons.close, color: kAppColorWhite),
),
],
),
)In-Call Chat Option
dart
class InCallChatOption {
final String name;
final int id;
InCallChatOption({required this.name, required this.id});
}