Files
chat/client/flutter/lib/providers/chat_provider.dart
2026-04-25 16:36:34 +08:00

198 lines
5.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import 'package:sales_chat/models/group.dart';
import 'package:sales_chat/models/message.dart';
import 'package:sales_chat/services/api_service.dart';
class ChatProvider with ChangeNotifier {
final ApiService _apiService;
List<Group> _groups = [];
Map<String, List<Message>> _messagesByConverse = {};
Group? _currentGroup;
bool _isLoading = false;
bool _isLoadingMessages = false;
String? _error;
ChatProvider(this._apiService);
List<Group> get groups => _groups;
Group? get currentGroup => _currentGroup;
bool get isLoading => _isLoading;
bool get isLoadingMessages => _isLoadingMessages;
String? get error => _error;
List<Message> get currentMessages {
if (_currentGroup == null) return [];
// 使用第一个文本面板的 ID 作为 converseId
final converseId = _currentGroup!.firstTextPanel?.id ?? _currentGroup!.id;
return _messagesByConverse[converseId] ?? [];
}
/// 获取群组的 converseId第一个文本面板或以群组 ID 作为备选)
String _getConverseIdForGroup(Group group) {
return group.firstTextPanel?.id ?? group.id;
}
Future<void> loadGroups() async {
_isLoading = true;
_error = null;
notifyListeners();
try {
_groups = await _apiService.getGroups();
_isLoading = false;
notifyListeners();
} catch (e) {
_error = 'Failed to load groups';
_isLoading = false;
notifyListeners();
}
}
void selectGroup(Group group) {
_currentGroup = group;
notifyListeners();
final converseId = _getConverseIdForGroup(group);
if (_messagesByConverse[converseId] == null) {
loadMessages(converseId);
}
}
void deselectGroup() {
_currentGroup = null;
notifyListeners();
}
Future<void> loadMessages(String converseId, {bool refresh = false}) async {
if (_isLoadingMessages) return;
_isLoadingMessages = true;
notifyListeners();
try {
final messages = await _apiService.getMessages(
converseId,
limit: 50,
before: refresh ? null : (_messagesByConverse[converseId]?.first.id),
);
if (refresh) {
_messagesByConverse[converseId] = messages;
} else {
_messagesByConverse[converseId] = [
...messages,
...(_messagesByConverse[converseId] ?? [])
];
}
_isLoadingMessages = false;
notifyListeners();
} catch (e) {
_error = 'Failed to load messages';
_isLoadingMessages = false;
notifyListeners();
}
}
Future<void> sendMessage(String content) async {
if (_currentGroup == null || content.isEmpty) return;
final converseId = _getConverseIdForGroup(_currentGroup!);
final groupId = _currentGroup!.id;
try {
final message = await _apiService.sendMessage(
converseId,
content,
groupId: groupId,
);
_messagesByConverse[converseId] = [
...(_messagesByConverse[converseId] ?? []),
message,
];
notifyListeners();
} catch (e) {
_error = 'Failed to send message';
notifyListeners();
}
}
/// 撤回消息
Future<bool> recallMessage(String messageId) async {
try {
await _apiService.recallMessage(messageId);
// 更新本地消息列表
if (_currentGroup != null) {
final converseId = _getConverseIdForGroup(_currentGroup!);
final messages = _messagesByConverse[converseId];
if (messages != null) {
final idx = messages.indexWhere((m) => m.id == messageId);
if (idx != -1) {
// 标记为已撤回而非删除
final old = messages[idx];
messages[idx] = Message(
id: old.id,
content: 'Message recalled',
author: old.author,
groupId: old.groupId,
converseId: old.converseId,
hasRecall: true,
meta: old.meta,
createdAt: old.createdAt,
updatedAt: old.updatedAt,
);
notifyListeners();
}
}
}
return true;
} catch (e) {
_error = 'Failed to recall message: $e';
notifyListeners();
return false;
}
}
/// 删除消息(管理员)
Future<bool> deleteMessage(String messageId) async {
try {
await _apiService.deleteMessage(messageId);
// 从本地消息列表中移除
if (_currentGroup != null) {
final converseId = _getConverseIdForGroup(_currentGroup!);
final messages = _messagesByConverse[converseId];
if (messages != null) {
messages.removeWhere((m) => m.id == messageId);
notifyListeners();
}
}
return true;
} catch (e) {
_error = 'Failed to delete message: $e';
notifyListeners();
return false;
}
}
/// 添加通过 socket.io 接收的消息
void addMessage(Message message) {
final converseId = message.converseId;
_messagesByConverse[converseId] = [
...(_messagesByConverse[converseId] ?? []),
message,
];
notifyListeners();
}
void clearError() {
_error = null;
notifyListeners();
}
}