import 'package:chepuhagram/domain/services/aPI_service.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '/data/models/contact_model.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:chepuhagram/data/models/message_model.dart'; class ContactTile extends StatefulWidget { final Contact contact; final VoidCallback? onTap; ContactTile({super.key, required this.contact, this.onTap}); @override State createState() => _ContactTileState(); } class _ContactTileState extends State { SharedPreferences? _prefs; String? token; @override void initState() { super.initState(); _initPrefs(); } Future _initPrefs() async { final apiService = ApiService(); final accessToken = await apiService.getAccessToken(); final shared = await SharedPreferences.getInstance(); if (mounted) { setState(() { _prefs = shared; token = accessToken; }); } } String get displayName { if (_prefs == null) return widget.contact.name; final id = widget.contact.id; final savedName = _prefs!.getString('firstname_$id'); final savedSurname = _prefs!.getString('lastname_$id'); final name = savedName ?? widget.contact.name; final surname = savedSurname ?? widget.contact.surname; final full = '${name != 'Unknown' ? name : ''} ${surname != 'Unknown' ? surname : ''}' .trim(); if (full.isNotEmpty) return full; if (widget.contact.username != 'Unknown') return widget.contact.username; return 'User'; } @override Widget build(BuildContext context) { final primary = Theme.of(context).colorScheme.primary; final username = widget.contact.username; // final initials = (displayName.isNotEmpty ? displayName : (username != 'Unknown' ? username : 'U')) .trim() .split(RegExp(r'\s+')) .where((p) => p.isNotEmpty) .take(2) .map((p) => p[0].toUpperCase()) .join(); // debugPrint( '=== CONTACT DEBUG: ${widget.contact.name} -> URL: ${widget.contact.effectiveAvatarUrl}', ); return ListTile( onTap: widget.onTap, // contentPadding: EdgeInsets.symmetric( horizontal: 16, vertical: 4, ), // // Переписываем ведущий виджет (аватарку) leading: SizedBox( width: 56, // Соответствует радиусу 28 * 2 height: 56, child: widget.contact.effectiveAvatarUrl != null // ? CachedNetworkImage( imageUrl: widget.contact.effectiveAvatarUrl!, // // Передаем токен для FastAPI, чтобы сервер разрешил скачивание файла httpHeaders: { if (token != null) 'Authorization': 'Bearer $token', }, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: imageProvider, fit: BoxFit.cover, ), ), ), // Пока картинка качается — показываем цветной круг с инициалами placeholder: (context, url) => CircleAvatar( radius: 28, backgroundColor: primary.withAlpha((0.1 * 255).round()), child: Text( initials, style: TextStyle( color: primary, fontWeight: FontWeight.bold, ), ), ), // Ошибка 401, 404 или упал интернет? Без паники, плавно вернем инициалы errorWidget: (context, url, error) => CircleAvatar( radius: 28, backgroundColor: primary.withAlpha((0.1 * 255).round()), child: Text( initials, style: TextStyle( color: primary, fontWeight: FontWeight.bold, ), ), ), ) : CircleAvatar( radius: 28, backgroundColor: primary.withAlpha((0.1 * 255).round()), // child: Text( initials, style: TextStyle(color: primary, fontWeight: FontWeight.bold), ), ), ), title: Text( displayName, // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), // ), subtitle: Text( widget.contact.isLastMsgDecrypted ? widget.contact.lastMessage == null ? "Нет сообщений" : "${widget.contact.lastMessageType != null ? MessageModel.getMediaPreview(widget.contact.lastMessageType!) : ''} ${widget.contact.lastMessage}" : (widget.contact.lastMessage != null ? "Ожидание дешифровки..." : "Нет сообщений"), maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.grey), // ), trailing: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( _formatTime(widget.contact.lastMessageTime), // style: TextStyle(color: Colors.grey, fontSize: 12), // ), SizedBox(height: 4), // if (widget.contact.unreadCount > 0) // Container( padding: EdgeInsets.all(6), // decoration: BoxDecoration( color: primary.withAlpha((0.5 * 255).round()), // shape: BoxShape.circle, // ), child: Text( '${widget.contact.unreadCount}', // style: TextStyle(color: Colors.white, fontSize: 10), // ), ), ], ), ); } String _formatTime(DateTime? time) { if (time == null) return ""; return "${time.hour}:${time.minute.toString().padLeft(2, '0')}"; } }