diff --git a/lib/backend/modules/chats.dart b/lib/backend/modules/chats.dart index 08f9f30..8ca873d 100644 --- a/lib/backend/modules/chats.dart +++ b/lib/backend/modules/chats.dart @@ -7,6 +7,7 @@ import '../../core/config/komet_settings.dart'; import '../../core/protocol/opcode_map.dart'; import '../../core/protocol/packet.dart'; import '../../core/cache/info_cache.dart'; +import '../../core/cache/message_session_cache.dart'; import '../../core/storage/app_database.dart'; import '../../core/storage/token_storage.dart'; import '../../core/utils/logger.dart'; @@ -1520,6 +1521,35 @@ class ChatsModule { } } + static Future clearHistory( + Api api, { + required int chatId, + required int lastEventTime, + bool forAll = false, + }) async { + try { + await api.sendRequest(Opcode.chatClear, { + 'chatId': chatId, + 'lastEventTime': lastEventTime, + 'forAll': forAll, + }); + final accountId = await TokenStorage.getActiveAccountId(); + if (accountId != null) { + await AppDatabase.clearMessages(accountId, chatId); + MessageSessionCache.remove(accountId, chatId); + _historyFetched.remove(chatId); + await reconcileLastMessage(accountId, chatId); + } + return null; + } on PacketError catch (e) { + logger.w('clearHistory $chatId: ${e.message}'); + return e.message; + } catch (e) { + logger.w('clearHistory $chatId: $e'); + return 'Не удалось очистить историю'; + } + } + static Future leaveChat(Api api, {required int chatId}) async { try { await api.sendRequest(Opcode.chatLeave, {'chatId': chatId}); diff --git a/lib/frontend/screens/chats/chat_screen.dart b/lib/frontend/screens/chats/chat_screen.dart index ed3b2f8..5a7faae 100644 --- a/lib/frontend/screens/chats/chat_screen.dart +++ b/lib/frontend/screens/chats/chat_screen.dart @@ -2349,17 +2349,93 @@ class _ChatScreenState extends State ChatMenuItem( icon: Symbols.mop, label: 'Очистить историю', - onTap: () {}, + onTap: _clearHistory, ), ChatMenuItem( icon: Symbols.delete, label: 'Удалить чат', - onTap: () {}, + onTap: _deleteChat, ), ], ); } + Future _showConfirmDialog({ + required String title, + required String body, + required String confirmLabel, + }) { + final cs = Theme.of(context).colorScheme; + return showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: cs.surfaceContainerHigh, + title: Text(title), + content: Text( + body, + style: TextStyle(color: cs.onSurfaceVariant, fontSize: 15), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx, false), + child: const Text('Отмена'), + ), + TextButton( + onPressed: () => Navigator.pop(ctx, true), + child: Text(confirmLabel, style: TextStyle(color: cs.error)), + ), + ], + ), + ); + } + + Future _clearHistory() async { + final confirmed = await _showConfirmDialog( + title: 'Очистить историю', + body: 'Все сообщения в этом чате будут удалены без возможности ' + 'восстановления.', + confirmLabel: 'Очистить', + ); + if (!mounted || confirmed != true) return; + final err = await ChatsModule.clearHistory( + api, + chatId: widget.chatId, + lastEventTime: chat?.lastEventTime ?? 0, + ); + if (!mounted) return; + if (err != null) { + showCustomNotification(context, err); + return; + } + setState(() { + _messages = []; + _hasMoreHistory = false; + _combinedItemsCache = null; + }); + _messagesRev.value++; + } + + Future _deleteChat() async { + final confirmed = await _showConfirmDialog( + title: 'Удалить чат', + body: 'Чат будет удалён вместе со всей перепиской.', + confirmLabel: 'Удалить', + ); + if (!mounted || confirmed != true) return; + final err = await ChatsModule.deleteChat( + api, + chatId: widget.chatId, + lastEventTime: chat?.lastEventTime ?? 0, + forAll: false, + ); + if (!mounted) return; + if (err != null) { + showCustomNotification(context, err); + return; + } + Navigator.of(context).pop(); + } + Future _startCall() async { if (widget.chatType != 'DIALOG') { showCustomNotification(context, 'Звонки доступны только в диалогах');