бля это сэкс

This commit is contained in:
Ваше Имя
2026-04-03 20:54:12 +07:00
parent da5ec16b8e
commit 676c2c715f
5 changed files with 182 additions and 24 deletions
-2
View File
@@ -97,7 +97,6 @@ class MessagesModule {
final List<CachedMessage> results = [];
final List<Map<String, dynamic>> rows = [];
// Обрабатываем сообщения "кусочками", чтобы не фризить UI при маппинге большого количества данных
for (var i = 0; i < messagesData.length; i++) {
final m = messagesData[i];
if (m is! Map) continue;
@@ -108,7 +107,6 @@ class MessagesModule {
rows.add(msg.toDbRow());
}
// Каждые 20 сообщений даем UI-потоку "дохнуть" и отрисовать кадр
if (i > 0 && i % 20 == 0) {
await Future.delayed(Duration.zero);
}
-2
View File
@@ -3,8 +3,6 @@ import 'dart:isolate';
import 'package:dart_lz4/dart_lz4.dart';
import 'package:msgpack_dart/msgpack_dart.dart' as msgpack;
import '../utils/logger.dart';
/// ver(1) + cmd(1) + seq(2) + opcode(2) + packedLen(4) = 10
const int headerSize = 10;
const int _maxDecompressedSize = 1048576; // 1 MB
@@ -23,10 +23,11 @@ class ChatListScreen extends StatefulWidget {
}
class _ChatListScreenState extends State<ChatListScreen>
with SingleTickerProviderStateMixin {
with TickerProviderStateMixin {
String _selectedCategory = 'Все чаты';
int _currentNavIndex = 0;
bool _isFabOpen = false;
bool _showCacheWarning = false;
late AnimationController _fabController;
final Set<String> _selectedChats = {};
final ScrollController _scrollController = ScrollController();
@@ -64,6 +65,9 @@ class _ChatListScreenState extends State<ChatListScreen>
});
}
bool _isInitialLoading = true;
late AnimationController _shimmerController;
@override
void initState() {
super.initState();
@@ -71,11 +75,26 @@ class _ChatListScreenState extends State<ChatListScreen>
vsync: this,
duration: const Duration(milliseconds: 350),
);
_shimmerController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500),
)..repeat();
_scrollController.addListener(_onScroll);
_sessionState = api.state;
_stateSub = api.stateStream.listen((state) {
if (mounted) setState(() => _sessionState = state);
if (mounted) {
setState(() {
_sessionState = state;
if (state == SessionState.disconnected && _chats.isNotEmpty) {
_showCacheWarning = true;
}
if (state == SessionState.online) {
_showCacheWarning = false;
}
});
}
});
_loadProfile();
@@ -89,6 +108,13 @@ class _ChatListScreenState extends State<ChatListScreen>
setState(() {
_profile = p;
_chats = chats;
_isInitialLoading = false;
});
}
} else {
if (mounted) {
setState(() {
_isInitialLoading = false;
});
}
}
@@ -102,6 +128,59 @@ class _ChatListScreenState extends State<ChatListScreen>
return '$h:$m';
}
Widget _buildChatShimmer() {
final cs = Theme.of(context).colorScheme;
return AnimatedBuilder(
animation: _shimmerController,
builder: (context, child) {
final opacity = 0.3 + 0.3 * sin(_shimmerController.value * pi * 2);
return Opacity(
opacity: opacity,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: cs.surfaceContainerHighest,
shape: BoxShape.circle,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 120,
height: 14,
decoration: BoxDecoration(
color: cs.surfaceContainerHighest,
borderRadius: BorderRadius.circular(7),
),
),
const SizedBox(height: 10),
Container(
width: double.infinity,
height: 10,
decoration: BoxDecoration(
color: cs.surfaceContainerHighest,
borderRadius: BorderRadius.circular(5),
),
),
],
),
),
],
),
),
);
},
);
}
void _onScroll() {
if (_scrollController.hasClients) {
final double offset = _scrollController.offset;
@@ -319,6 +398,49 @@ class _ChatListScreenState extends State<ChatListScreen>
),
),
),
if (_showCacheWarning)
Padding(
padding: const EdgeInsets.fromLTRB(
20,
0,
20,
8,
),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
decoration: BoxDecoration(
color: cs.errorContainer.withOpacity(
0.3,
),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: cs.error.withOpacity(0.2),
),
),
child: Row(
children: [
Icon(
Symbols.cloud_off,
size: 18,
color: cs.error,
),
const SizedBox(width: 12),
const Expanded(
child: Text(
'Ошибка соединения, сейчас вы смотрите КЕШ',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(
20,
@@ -418,6 +540,9 @@ class _ChatListScreenState extends State<ChatListScreen>
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
if (_isInitialLoading) {
return _buildChatShimmer();
}
final chat = _chats[index];
return _buildChatItem(
chat.id.toString(),
@@ -431,10 +556,10 @@ class _ChatListScreenState extends State<ChatListScreen>
unreadCount: chat.unreadCount,
isMuted: chat.dontDisturbUntil > 0,
);
}, childCount: _chats.length),
}, childCount: _isInitialLoading ? 10 : _chats.length),
),
const SliverPadding(
padding: EdgeInsets.only(bottom: 120),
padding: EdgeInsets.only(bottom: 100),
),
],
), // CustomScrollView
@@ -449,7 +574,7 @@ class _ChatListScreenState extends State<ChatListScreen>
curve: Curves.easeOutCubic,
left: 8,
right: 8,
bottom: _isSelectionMode ? -100 : 24.0,
bottom: _isSelectionMode ? -100 : 10.0,
child: RepaintBoundary(
child: Container(
height: 68,
@@ -561,7 +686,7 @@ class _ChatListScreenState extends State<ChatListScreen>
if (_fabController.value > 0)
Positioned(
right: 20,
bottom: 110 + 74,
bottom: 90 + 74,
child: RepaintBoundary(
child: Transform.scale(
scale: val,
@@ -575,7 +700,7 @@ class _ChatListScreenState extends State<ChatListScreen>
),
Positioned(
right: 20,
bottom: 110,
bottom: 90,
child: FloatingActionButton(
onPressed: _toggleFab,
backgroundColor: cs.primaryContainer,
+39 -5
View File
@@ -1,6 +1,9 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../../main.dart';
import '../../../backend/api.dart';
import '../../../backend/modules/messages.dart';
import '../../../core/storage/app_database.dart';
class ChatScreen extends StatefulWidget {
@@ -25,6 +28,7 @@ class _ChatScreenState extends State<ChatScreen>
bool _hasText = false;
bool _isLoading = true;
late AnimationController _shimmerController;
List<CachedMessage> _messages = [];
@override
void initState() {
@@ -34,17 +38,45 @@ class _ChatScreenState extends State<ChatScreen>
vsync: this,
duration: const Duration(milliseconds: 1500),
)..repeat();
_loadHistory();
}
Future<void> _loadHistory() async {
final activeProfile = await AppDatabase.loadActiveProfile();
final myId = activeProfile?.id ?? 0;
final cachedRows = await AppDatabase.loadMessages(
myId,
widget.chatId,
limit: 100,
);
if (mounted && cachedRows.isNotEmpty) {
setState(() {
_messages = cachedRows.map((r) => CachedMessage.fromDbRow(r)).toList();
if (api.state == SessionState.online) {
_isLoading = false;
}
});
}
try {
final activeProfile = await AppDatabase.loadActiveProfile();
final myId = activeProfile?.id ?? 0;
await messagesModule.fetchHistory(myId, widget.chatId);
final updatedRows = await AppDatabase.loadMessages(
myId,
widget.chatId,
limit: 100,
);
if (mounted) {
setState(() {
_messages = updatedRows
.map((r) => CachedMessage.fromDbRow(r))
.toList();
_isLoading = false;
});
}
} catch (e) {
debugPrint('Background history fetch failed: $e');
} finally {
debugPrint('Error fetching history: $e');
if (mounted) {
setState(() {
_isLoading = false;
@@ -148,7 +180,9 @@ class _ChatScreenState extends State<ChatScreen>
body: Column(
children: [
Expanded(
child: _isLoading
child:
_isLoading ||
(_messages.isEmpty && api.state != SessionState.online)
? _buildShimmerLoading()
: const SizedBox.shrink(),
),
+11 -8
View File
@@ -91,16 +91,19 @@ class _StartupScreenState extends State<_StartupScreen> {
return;
}
if (mounted) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const ChatListScreen()),
);
}
try {
await accountModule.login(accountId: accountId);
if (mounted) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const ChatListScreen()),
);
}
} catch (_) {
_goToLogin();
} catch (e) {
debugPrint(
'Background auto-login failed (safe to ignore if offline): $e',
);
}
}