From 5044cb6020717768ebe5948e59d300f8dfe76c08 Mon Sep 17 00:00:00 2001 From: Artur Date: Mon, 22 Jun 2026 11:32:19 +0500 Subject: [PATCH] 22-06-2026+11-32 --- lib/data/datasources/local_db_service.dart | 11 +++++ lib/presentation/screens/chat_screen.dart | 50 +++++++++++++++++++--- srv/app/services/notification_service.py | 6 ++- srv/app/websocket/connection_manager.py | 19 +++++--- srv/site/about-secutity/index.html | 1 - 5 files changed, 72 insertions(+), 15 deletions(-) diff --git a/lib/data/datasources/local_db_service.dart b/lib/data/datasources/local_db_service.dart index 5af5bf0..01086ee 100644 --- a/lib/data/datasources/local_db_service.dart +++ b/lib/data/datasources/local_db_service.dart @@ -286,6 +286,17 @@ class LocalDbService extends _$LocalDbService { ); } + Future markAllAsRead(int contactId, int myId) async { + await (update(messages) + ..where((tbl) => + tbl.senderId.equals(contactId) & + tbl.receiverId.equals(myId) & + tbl.readAt.isNull())) + .write( + MessagesCompanion(readAt: Value(DateTime.now().toIso8601String())), + ); + } + Future updateMessageContent( int messageId, String content, diff --git a/lib/presentation/screens/chat_screen.dart b/lib/presentation/screens/chat_screen.dart index 466229f..916fef7 100644 --- a/lib/presentation/screens/chat_screen.dart +++ b/lib/presentation/screens/chat_screen.dart @@ -3561,18 +3561,14 @@ class _ChatScreenState extends State with RouteAware { WidgetsBinding.instance.addPostFrameCallback((_) { Future.delayed(const Duration(milliseconds: 500), () async { if (mounted) { - // Если чат пуст или нет непрочитанных — сразу отправляем прочтение final hasUnread = messages.any( (m) => !m.isMe && m.status != MessageStatus.read, ); final positions = _itemPositionsListener.itemPositions.value; - print( - 'Отправка прочтения: ${(!hasUnread || (positions.isNotEmpty && positions.last.index > 5))}', - ); - // Если пользователь уже внизу (сразу после загрузки) - if (!hasUnread || - (positions.isNotEmpty && positions.last.index > 5)) { + final isAtBottom = positions.isNotEmpty && positions.any((p) => p.index == 0); + if (!hasUnread || isAtBottom) { _socketService.sendReadAllChat(widget.contact.id); + _markAllLocalMessagesAsRead(); } } }); @@ -4357,6 +4353,46 @@ class _ChatScreenState extends State with RouteAware { } _showScrollButtonNotifier.value = showScrollButton; + + // Если пользователь внизу и есть непрочитанные сообщения от собеседника, отправляем прочтение всех + if (!showScrollButton) { + final hasUnread = messages.any( + (m) => !m.isMe && m.status != MessageStatus.read, + ); + if (hasUnread) { + print("DEBUG: Пользователь внизу чата, отправляем прочтение всех сообщений"); + _socketService.sendReadAllChat(_currentContact.id); + _markAllLocalMessagesAsRead(); + } + } + } + + Future _markAllLocalMessagesAsRead() async { + bool updated = false; + for (int i = 0; i < messages.length; i++) { + if (!messages[i].isMe && messages[i].status != MessageStatus.read) { + messages[i] = messages[i].copyWith(status: MessageStatus.read); + updated = true; + } + } + if (updated && mounted) { + setState(() {}); + } + + // Обновляем список контактов в провайдере + final contactProvider = context.read(); + await contactProvider.updateContact( + _currentContact.id, + unreadCount: 0, + firstUnreadMessageId: 0, + ); + + // Обновляем локальную базу данных + try { + await _localDbService.markAllAsRead(_currentContact.id, myId); + } catch (e) { + print('Ошибка при пометке всех сообщений прочитанными в БД: $e'); + } } Future _scrollToBottom() async { diff --git a/srv/app/services/notification_service.py b/srv/app/services/notification_service.py index db4c394..6773de4 100644 --- a/srv/app/services/notification_service.py +++ b/srv/app/services/notification_service.py @@ -71,7 +71,11 @@ async def send_system_notification(db: AsyncSession, receiver_id: int, plain_tex try: unread_res = await db.execute( select(func.count(models.Message.id)) - .where(models.Message.receiver_id == receiver_id, models.Message.read_at == None) + .where( + models.Message.receiver_id == receiver_id, + models.Message.sender_id == 0, + models.Message.read_at.is_(None) + ) ) unread_count = unread_res.scalar() or 0 fcm_message = messaging.Message( diff --git a/srv/app/websocket/connection_manager.py b/srv/app/websocket/connection_manager.py index ad1f21f..4505185 100644 --- a/srv/app/websocket/connection_manager.py +++ b/srv/app/websocket/connection_manager.py @@ -172,7 +172,11 @@ async def websocket_endpoint(websocket: WebSocket, token: str = Query(None), db: unread_res = await db.execute( select(func.count(models.Message.id)) - .where(models.Message.receiver_id == receiver_id, models.Message.read_at == None) + .where( + models.Message.receiver_id == receiver_id, + models.Message.sender_id == user_id, + models.Message.read_at.is_(None) + ) ) unread_count = unread_res.scalar() or 0 @@ -347,13 +351,16 @@ async def websocket_endpoint(websocket: WebSocket, token: str = Query(None), db: continue + sender_id = int(msg.sender_id) unread_res = await db.execute( select(func.count(models.Message.id)) - .where(models.Message.receiver_id == user_id, models.Message.read_at == None) + .where( + models.Message.receiver_id == user_id, + models.Message.sender_id == sender_id, + models.Message.read_at.is_(None) + ) ) unread_count = unread_res.scalar() or 0 - - sender_id = int(msg.sender_id) await manager.send_personal_message({ "type": "message_read", "sender_id": sender_id, @@ -394,14 +401,14 @@ async def websocket_endpoint(websocket: WebSocket, token: str = Query(None), db: await manager.send_personal_message({ "type": "all_chat_read", - "sender_id": sender_id, + "sender_id": contact_id, "reader_id": user_id, "timestamp": read_at_time.isoformat(), }, str(contact_id)) await manager.send_personal_message({ "type": "all_chat_read", - "sender_id": sender_id, + "sender_id": contact_id, "reader_id": user_id, "timestamp": read_at_time.isoformat(), }, str(user_id)) diff --git a/srv/site/about-secutity/index.html b/srv/site/about-secutity/index.html index d72d21d..fc13e3f 100644 --- a/srv/site/about-secutity/index.html +++ b/srv/site/about-secutity/index.html @@ -133,7 +133,6 @@ margin-bottom: 16px; line-height: 1.2; background: linear-gradient(135deg, #ffffff 40%, #d1c4e9 100%); - -webkit-background-clip: text; -webkit-text-fill-color: transparent; }