feat: анимации с реанимации

This commit is contained in:
Jganenokk
2026-08-06 19:21:45 +07:00
parent 81159bac60
commit 79c743e86a
50 changed files with 3247 additions and 925 deletions
+2
View File
@@ -7,6 +7,7 @@ import '../../models/bot_info.dart';
import '../../models/chat_info.dart';
import '../../models/contact_info.dart';
import '../protocol/opcode_map.dart';
import '../storage/chat_members_store.dart';
Api? _api;
@@ -336,6 +337,7 @@ class ChatInfoFetch {
if (chats is! List || chats.isEmpty) return null;
final first = chats.first;
if (first is! Map) return null;
ChatMembersStore.instance.applyChatPayload(first);
return ChatInfo.fromMap(Map<String, dynamic>.from(first));
}
}
+33 -9
View File
@@ -14,6 +14,24 @@ extension ChatActivityLabel on ChatActivity {
ChatActivity chatActivityFromType(dynamic type) =>
type == 'STICKER' ? ChatActivity.sticker : ChatActivity.typing;
class ChatActivitySnapshot {
const ChatActivitySnapshot({required this.activity, required this.userIds});
final ChatActivity activity;
final List<int> userIds;
String get label => activity.label;
@override
bool operator ==(Object other) =>
other is ChatActivitySnapshot &&
other.activity == activity &&
listEquals(other.userIds, userIds);
@override
int get hashCode => Object.hash(activity, Object.hashAll(userIds));
}
class ChatActivityStore {
ChatActivityStore._();
@@ -23,15 +41,17 @@ class ChatActivityStore {
final Map<int, Map<int, ChatActivity>> _users = {};
final Map<int, Map<int, Timer>> _timers = {};
final Map<int, ValueNotifier<ChatActivity?>> _notifiers = {};
final Map<int, ValueNotifier<ChatActivitySnapshot?>> _notifiers = {};
ValueListenable<ChatActivity?> listenable(int chatId) =>
ValueListenable<ChatActivitySnapshot?> listenable(int chatId) =>
_notifiers.putIfAbsent(
chatId,
() => ValueNotifier<ChatActivity?>(_current(chatId)),
() => ValueNotifier<ChatActivitySnapshot?>(_current(chatId)),
);
ChatActivity? activity(int chatId) => _current(chatId);
ChatActivitySnapshot? snapshot(int chatId) => _current(chatId);
ChatActivity? activity(int chatId) => _current(chatId)?.activity;
void mark(int chatId, int userId, ChatActivity activity) {
final timers = _timers.putIfAbsent(chatId, () => <int, Timer>{});
@@ -64,13 +84,17 @@ class ChatActivityStore {
_sync(chatId);
}
ChatActivity? _current(int chatId) {
ChatActivitySnapshot? _current(int chatId) {
final users = _users[chatId];
if (users == null || users.isEmpty) return null;
for (final activity in users.values) {
if (activity == ChatActivity.typing) return ChatActivity.typing;
}
return ChatActivity.sticker;
final leading = users.values.contains(ChatActivity.typing)
? ChatActivity.typing
: ChatActivity.sticker;
final ids = <int>[];
users.forEach((userId, activity) {
if (activity == leading) ids.add(userId);
});
return ChatActivitySnapshot(activity: leading, userIds: ids);
}
void _sync(int chatId) {
+45
View File
@@ -0,0 +1,45 @@
import 'package:flutter/foundation.dart';
class ChatMembersStore {
ChatMembersStore._();
static final ChatMembersStore instance = ChatMembersStore._();
final Map<int, int> _counts = {};
final Map<int, ValueNotifier<int?>> _notifiers = {};
ValueListenable<int?> listenable(int chatId) => _notifiers.putIfAbsent(
chatId,
() => ValueNotifier<int?>(_counts[chatId]),
);
int? count(int chatId) => _counts[chatId];
void setCount(int chatId, int? count) {
if (count == null || count < 0) return;
if (_counts[chatId] == count) return;
_counts[chatId] = count;
_notifiers[chatId]?.value = count;
}
void adjust(int chatId, int delta) {
final current = _counts[chatId];
if (current == null || delta == 0) return;
final next = current + delta;
setCount(chatId, next < 0 ? 0 : next);
}
void applyChatPayload(Object? chat) {
if (chat is! Map) return;
final id = chat['id'];
final count = chat['participantsCount'];
if (id is int && count is int) setCount(id, count);
}
void clear() {
_counts.clear();
for (final notifier in _notifiers.values) {
notifier.value = null;
}
}
}