авотаро4ки в пересланных сообщениях
This commit is contained in:
@@ -6,13 +6,21 @@ import '../../core/storage/app_database.dart';
|
||||
import '../../models/attachment.dart';
|
||||
|
||||
class ContactCache {
|
||||
static final Map<int, String> _cache = {};
|
||||
static final Map<int, String> _nameCache = {};
|
||||
static final Map<int, String> _avatarCache = {};
|
||||
|
||||
static void put(int id, String name) {
|
||||
_cache[id] = name;
|
||||
_nameCache[id] = name;
|
||||
}
|
||||
|
||||
static String? get(int id) => _cache[id];
|
||||
static void putAvatar(int id, String? baseUrl) {
|
||||
if (baseUrl != null) {
|
||||
_avatarCache[id] = baseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
static String? get(int id) => _nameCache[id];
|
||||
static String? getAvatar(int id) => _avatarCache[id];
|
||||
}
|
||||
|
||||
class CachedMessage {
|
||||
@@ -371,6 +379,10 @@ class MessagesModule {
|
||||
? '$firstName $lastName'
|
||||
: firstName;
|
||||
ContactCache.put(contactId, fullName);
|
||||
|
||||
final baseUrl = contact['baseUrl'] as String?;
|
||||
ContactCache.putAvatar(contactId, baseUrl);
|
||||
|
||||
return fullName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import '../../../backend/api.dart';
|
||||
import '../../../backend/modules/messages.dart';
|
||||
import '../../../core/storage/app_database.dart';
|
||||
import '../../../models/attachment.dart';
|
||||
import '../../../backend/modules/messages.dart' show ContactCache;
|
||||
import '../../widgets/message_bubble.dart';
|
||||
|
||||
class ChatScreen extends StatefulWidget {
|
||||
@@ -183,6 +184,7 @@ class _ChatScreenState extends State<ChatScreen>
|
||||
|
||||
for (final id in forwardIds) {
|
||||
final name = await messagesModule.searchContactById(id);
|
||||
final avatar = ContactCache.getAvatar(id);
|
||||
if (name != null && mounted) {
|
||||
setState(() {
|
||||
for (var i = 0; i < _messages.length; i++) {
|
||||
@@ -195,6 +197,7 @@ class _ChatScreenState extends State<ChatScreen>
|
||||
return ForwardedMessageAttachment(
|
||||
originalSenderId: id,
|
||||
originalSenderName: name,
|
||||
originalSenderAvatar: avatar,
|
||||
originalMessageId: a.originalMessageId,
|
||||
originalTime: a.originalTime,
|
||||
originalText: a.originalText,
|
||||
|
||||
@@ -360,12 +360,14 @@ class MessageBubble extends StatelessWidget {
|
||||
ForwardedMessageAttachment forwarded,
|
||||
Color textColor,
|
||||
) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final headerColor = isMe
|
||||
? Colors.white.withValues(alpha: 0.7)
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant;
|
||||
: cs.onSurfaceVariant;
|
||||
|
||||
final senderName = forwarded.originalSenderName;
|
||||
final displaySender = senderName ?? forwarded.originalSenderId.toString();
|
||||
final senderAvatar = forwarded.originalSenderAvatar;
|
||||
final origText = forwarded.originalText;
|
||||
final hasOrigText = origText != null && origText.isNotEmpty;
|
||||
|
||||
@@ -378,6 +380,24 @@ class MessageBubble extends StatelessWidget {
|
||||
children: [
|
||||
Icon(Symbols.forward, size: 14, color: headerColor),
|
||||
const SizedBox(width: 4),
|
||||
if (senderAvatar != null && senderAvatar.isNotEmpty)
|
||||
CircleAvatar(
|
||||
radius: 10,
|
||||
backgroundImage: NetworkImage(senderAvatar),
|
||||
backgroundColor: cs.primaryContainer,
|
||||
)
|
||||
else
|
||||
CircleAvatar(
|
||||
radius: 10,
|
||||
backgroundColor: cs.primaryContainer,
|
||||
child: Text(
|
||||
displaySender.isNotEmpty
|
||||
? displaySender[0].toUpperCase()
|
||||
: '?',
|
||||
style: TextStyle(fontSize: 9, color: cs.onPrimaryContainer),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
displaySender,
|
||||
style: TextStyle(
|
||||
@@ -580,11 +600,13 @@ class MessageBubble extends StatelessWidget {
|
||||
ForwardedMessageAttachment forwarded,
|
||||
List<PhotoAttachment> photos,
|
||||
) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final headerColor = isMe
|
||||
? Colors.white.withValues(alpha: 0.7)
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant;
|
||||
: cs.onSurfaceVariant;
|
||||
final senderName = forwarded.originalSenderName;
|
||||
final displaySender = senderName ?? forwarded.originalSenderId.toString();
|
||||
final senderAvatar = forwarded.originalSenderAvatar;
|
||||
final hasCaption = message.text != null && message.text!.isNotEmpty;
|
||||
|
||||
return Column(
|
||||
@@ -598,6 +620,24 @@ class MessageBubble extends StatelessWidget {
|
||||
children: [
|
||||
Icon(Symbols.forward, size: 14, color: headerColor),
|
||||
const SizedBox(width: 4),
|
||||
if (senderAvatar != null && senderAvatar.isNotEmpty)
|
||||
CircleAvatar(
|
||||
radius: 10,
|
||||
backgroundImage: NetworkImage(senderAvatar),
|
||||
backgroundColor: cs.primaryContainer,
|
||||
)
|
||||
else
|
||||
CircleAvatar(
|
||||
radius: 10,
|
||||
backgroundColor: cs.primaryContainer,
|
||||
child: Text(
|
||||
displaySender.isNotEmpty
|
||||
? displaySender[0].toUpperCase()
|
||||
: '?',
|
||||
style: TextStyle(fontSize: 9, color: cs.onPrimaryContainer),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
displaySender,
|
||||
style: TextStyle(
|
||||
|
||||
@@ -62,8 +62,7 @@ import 'app_localizations_ru.dart';
|
||||
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
|
||||
/// property.
|
||||
abstract class AppLocalizations {
|
||||
AppLocalizations(String locale)
|
||||
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
final String localeName;
|
||||
|
||||
@@ -71,8 +70,7 @@ abstract class AppLocalizations {
|
||||
return Localizations.of<AppLocalizations>(context, AppLocalizations);
|
||||
}
|
||||
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||||
_AppLocalizationsDelegate();
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
|
||||
|
||||
/// A list of this localizations delegate along with the default localizations
|
||||
/// delegates.
|
||||
@@ -84,18 +82,17 @@ abstract class AppLocalizations {
|
||||
/// Additional delegates can be added by appending to this list in
|
||||
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||
/// of delegates is preferred or required.
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||
<LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('en'),
|
||||
Locale('ru'),
|
||||
Locale('ru')
|
||||
];
|
||||
|
||||
/// No description provided for @loginTitle.
|
||||
@@ -381,8 +378,7 @@ abstract class AppLocalizations {
|
||||
String get proxyInvalidHostOrPort;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
extends LocalizationsDelegate<AppLocalizations> {
|
||||
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
const _AppLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
@@ -391,26 +387,25 @@ class _AppLocalizationsDelegate
|
||||
}
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) =>
|
||||
<String>['en', 'ru'].contains(locale.languageCode);
|
||||
bool isSupported(Locale locale) => <String>['en', 'ru'].contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||
}
|
||||
|
||||
AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||
|
||||
|
||||
// Lookup logic when only language code is specified.
|
||||
switch (locale.languageCode) {
|
||||
case 'en':
|
||||
return AppLocalizationsEn();
|
||||
case 'ru':
|
||||
return AppLocalizationsRu();
|
||||
case 'en': return AppLocalizationsEn();
|
||||
case 'ru': return AppLocalizationsRu();
|
||||
}
|
||||
|
||||
throw FlutterError(
|
||||
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
|
||||
'an issue with the localizations generation tool. Please file an issue '
|
||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||
'that was used.',
|
||||
'that was used.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get loginTitle => 'Sign in to Komet';
|
||||
|
||||
@override
|
||||
String get loginSubtitle =>
|
||||
'Check your country code and enter your\nphone number.';
|
||||
String get loginSubtitle => 'Check your country code and enter your\nphone number.';
|
||||
|
||||
@override
|
||||
String get loginCountry => 'Country';
|
||||
@@ -103,8 +102,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get selectCountrySearchHint => 'Search countries…';
|
||||
|
||||
@override
|
||||
String get codeConfirmationSmsSent =>
|
||||
'We sent an SMS with a verification code to your phone number.';
|
||||
String get codeConfirmationSmsSent => 'We sent an SMS with a verification code to your phone number.';
|
||||
|
||||
@override
|
||||
String codeResendInSeconds(int seconds) {
|
||||
@@ -151,6 +149,5 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get proxySettingsSaved => 'Proxy settings applied';
|
||||
|
||||
@override
|
||||
String get proxyInvalidHostOrPort =>
|
||||
'Enter a valid proxy host and port (1–65535)';
|
||||
String get proxyInvalidHostOrPort => 'Enter a valid proxy host and port (1–65535)';
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get loginTitle => 'Войдите в Komet';
|
||||
|
||||
@override
|
||||
String get loginSubtitle =>
|
||||
'Проверьте код страны и введите свой\nномер телефона.';
|
||||
String get loginSubtitle => 'Проверьте код страны и введите свой\nномер телефона.';
|
||||
|
||||
@override
|
||||
String get loginCountry => 'Страна';
|
||||
@@ -43,8 +42,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get loginDone => 'Готово';
|
||||
|
||||
@override
|
||||
String get loginReadTermsNotification =>
|
||||
'Сначала прочитайте условия использования';
|
||||
String get loginReadTermsNotification => 'Сначала прочитайте условия использования';
|
||||
|
||||
@override
|
||||
String get loginSpoofRedacted => 'Подделка спуфа';
|
||||
@@ -71,8 +69,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get serverUseDefault => 'Сбросить к умолчанию';
|
||||
|
||||
@override
|
||||
String get serverInvalidHostOrPort =>
|
||||
'Укажите корректный хост и порт (1–65535)';
|
||||
String get serverInvalidHostOrPort => 'Укажите корректный хост и порт (1–65535)';
|
||||
|
||||
@override
|
||||
String get serverSettingsSaved => 'Настройки сервера применены';
|
||||
@@ -105,8 +102,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get selectCountrySearchHint => 'Поиск страны…';
|
||||
|
||||
@override
|
||||
String get codeConfirmationSmsSent =>
|
||||
'Мы отправили SMS с кодом подтверждения на ваш номер телефона.';
|
||||
String get codeConfirmationSmsSent => 'Мы отправили SMS с кодом подтверждения на ваш номер телефона.';
|
||||
|
||||
@override
|
||||
String codeResendInSeconds(int seconds) {
|
||||
@@ -153,6 +149,5 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get proxySettingsSaved => 'Настройки прокси применены';
|
||||
|
||||
@override
|
||||
String get proxyInvalidHostOrPort =>
|
||||
'Укажите корректный хост и порт прокси (1–65535)';
|
||||
String get proxyInvalidHostOrPort => 'Укажите корректный хост и порт прокси (1–65535)';
|
||||
}
|
||||
|
||||
@@ -436,6 +436,7 @@ class ControlAttachment extends MessageAttachment {
|
||||
class ForwardedMessageAttachment extends MessageAttachment {
|
||||
final int originalSenderId;
|
||||
final String? originalSenderName;
|
||||
final String? originalSenderAvatar;
|
||||
final String? originalMessageId;
|
||||
final int? originalTime;
|
||||
final String? originalText;
|
||||
@@ -445,6 +446,7 @@ class ForwardedMessageAttachment extends MessageAttachment {
|
||||
const ForwardedMessageAttachment({
|
||||
required this.originalSenderId,
|
||||
this.originalSenderName,
|
||||
this.originalSenderAvatar,
|
||||
this.originalMessageId,
|
||||
this.originalTime,
|
||||
this.originalText,
|
||||
@@ -493,6 +495,7 @@ class ForwardedMessageAttachment extends MessageAttachment {
|
||||
'_type': 'FORWARD',
|
||||
'originalSenderId': originalSenderId,
|
||||
'originalSenderName': originalSenderName,
|
||||
'originalSenderAvatar': originalSenderAvatar,
|
||||
'originalMessageId': originalMessageId,
|
||||
'originalTime': originalTime,
|
||||
'originalText': originalText,
|
||||
|
||||
Reference in New Issue
Block a user