Вот моя текущая реализация:
< div class="snippet-code">
Код: Выделить всё
class ChatBox extends StatefulWidget {
const ChatBox({super.key, required this.liveID, required this.username});
final int liveID;
final String username;
@override
State createState() => _ChatBoxState();
}
class _ChatBoxState extends State {
final TextEditingController _messageController = TextEditingController();
bool _showEmojiPicker = false;
late IO.Socket socket;
int? currentUserID;
String? currentUsername;
List _messages = [];
final StreamController _streamController = StreamController();
Stream get messagesStream => _streamController.stream;
void _onEmojiSelected(Emoji emoji) {
_messageController
..text += emoji.emoji
..selection = TextSelection.fromPosition(
TextPosition(offset: _messageController.text.length),
);
}
void _onBackspacePressed() {
_messageController
..text = _messageController.text.characters.skipLast(1).toString()
..selection = TextSelection.fromPosition(
TextPosition(offset: _messageController.text.length),
);
}
@override
void initState() {
super.initState();
_loadCurrentUserID();
_initializeSocket();
}
@override
void dispose() {
_messageController.dispose();
_streamController.close();
socket.disconnect();
super.dispose();
}
Future _loadCurrentUserID() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
currentUserID = prefs.getInt('loginUserId');
currentUsername = prefs.getString('username'); // Assuming you have stored the username
});
}
void _initializeSocket() {
socket = IO.io('https://socket.example.com', {
'transports': ['websocket'],
'autoConnect': false,
});
socket.connect();
socket.onConnect((_) {
debugPrint('connected to websocket');
});
socket.onDisconnect((_) {
debugPrint('disconnected from websocket');
});
socket.on('chat_list_message', (data) {
debugPrint('Received message: $data');
_streamController.add(data);
// setState(() {
// if (data is Map && data['message'] is List && data['message'].isNotEmpty) {
// for (var messageObj in data['message']) {
// if (messageObj is Map && messageObj.containsKey('message')) {
// String messageContent = messageObj['message'];
// _messages.add(ChatMessage(
// userID: messageObj['userID'],
// liveID: messageObj['liveID'],
// message: messageContent,
// username: messageObj['username'],
// ));
// debugPrint('Received Message: $messageContent');
// } else {
// debugPrint('Unexpected message object: $messageObj');
// }
// }
// }
// });
});
socket.onError((error) {
debugPrint('Socket error: $error');
});
}
void _sendMessage() {
String message = _messageController.text.trim();
if (message.isNotEmpty) {
final newMessage = {
'userID': currentUserID,
'liveID': widget.liveID,
'message': message,
'username': currentUsername ?? 'Unknown',
'time': DateTime.now().toIso8601String(),
};
setState(() {
_messages.add(ChatMessage.fromJson(newMessage));
});
socket.emit('add_chat_message', newMessage);
_messageController.clear();
}
}
@override
Widget build(BuildContext context) {
return BlocListener(
listener: (context, state) {
if (state is ChatDataLiveSuccess) {
setState(() {
_messages = state.allChatDataLives ?? [];
});
} else if (state is ChatDataLiveFail) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(state.message)),
);
}
},
child: SizedBox(
height: 150,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Divider(
color: Theme.of(context).primaryColor,
height: 1,
thickness: 1.5,
),
),
const SizedBox(width: 8.0),
Text(
'New Message',
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodySmall,
maxLines: 1,
),
const SizedBox(width: 8.0),
Expanded(
child: Divider(
color: Theme.of(context).primaryColor,
height: 1,
thickness: 1.5,
),
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
final message = _messages[index];
return Row(
children: [
const SizedBox(width: 20),
Text(
'${widget.username} : ',
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyMedium,
maxLines: 1,
),
const SizedBox(width: 10),
Text(
message.message ?? '',
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodySmall,
maxLines: 1,
),
],
);
},
),
),
Container(
margin: const EdgeInsets.only(left: 12.0, top: 12),
child: Row(
children: [
Expanded(
child: TextField(
controller: _messageController,
decoration: const InputDecoration(
hintText: 'Type your message...',
border: OutlineInputBorder(),
),
),
),
const SizedBox(width: 8.0),
IconButton(
icon: const Icon(Icons.emoji_emotions),
onPressed: () {
setState(() {
_showEmojiPicker = !_showEmojiPicker;
});
},
),
IconButton(
icon: const Icon(Icons.send),
onPressed: () {
_sendMessage();
},
),
],
),
),
Offstage(
offstage: !_showEmojiPicker,
child: SizedBox(
height: 250,
child: EmojiPicker(
onEmojiSelected: (category, emoji) {
_onEmojiSelected(emoji);
},
onBackspacePressed: _onBackspacePressed,
config: const Config(
height: 200,
checkPlatformCompatibility: true,
emojiViewConfig: EmojiViewConfig(
emojiSizeMax: 32,
),
swapCategoryAndBottomBar: false,
),
),
),
),
],
),
),
);
}
}Внесенные изменения:
Правильно Анализ данных: при получении событияchat_list_message я проанализировал каждое сообщение в списке и добавил его в _messages.
Немедленное обновление пользовательского интерфейса: использовал setState, чтобы гарантировать немедленное обновление пользовательского интерфейса при получении новых сообщений. .
Правильное отображение: отрегулировано отображение сообщений, чтобы они правильно отображались в дереве виджетов.
Если у вас возникнут какие-либо дополнительные проблемы или вам понадобится подробнее, спрашивайте!
Подробнее здесь: https://stackoverflow.com/questions/786 ... -with-sock