Improves SMS message display and interaction

Enhances the SMS message widget to provide a richer user experience.

Adds sender information, formatted date, message processing status and actions.
Includes localization support for new UI elements.
This commit is contained in:
2025-07-13 00:16:21 +03:00
parent c23a3db59d
commit 2fca5203e2
6 changed files with 131 additions and 11 deletions
+5 -1
View File
@@ -52,5 +52,9 @@
"editTag": "Edit tag", "editTag": "Edit tag",
"loadSmsMessages": "Load SMS Messages", "loadSmsMessages": "Load SMS Messages",
"loadSmsMessagesDescription": "Load and process SMS messages to automatically create transactions", "loadSmsMessagesDescription": "Load and process SMS messages to automatically create transactions",
"smsSettings": "Processing settings" "smsSettings": "Processing settings",
"createTransaction": "Create transaction",
"unknownSender": "Unknown sender",
"smsProcessed": "Processed",
"smsNotProcessed": "Not processed"
} }
+24
View File
@@ -415,6 +415,30 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Processing settings'** /// **'Processing settings'**
String get smsSettings; String get smsSettings;
/// No description provided for @createTransaction.
///
/// In en, this message translates to:
/// **'Create transaction'**
String get createTransaction;
/// No description provided for @unknownSender.
///
/// In en, this message translates to:
/// **'Unknown sender'**
String get unknownSender;
/// No description provided for @smsProcessed.
///
/// In en, this message translates to:
/// **'Processed'**
String get smsProcessed;
/// No description provided for @smsNotProcessed.
///
/// In en, this message translates to:
/// **'Not processed'**
String get smsNotProcessed;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate
+12
View File
@@ -169,4 +169,16 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get smsSettings => 'Processing settings'; String get smsSettings => 'Processing settings';
@override
String get createTransaction => 'Create transaction';
@override
String get unknownSender => 'Unknown sender';
@override
String get smsProcessed => 'Processed';
@override
String get smsNotProcessed => 'Not processed';
} }
+12
View File
@@ -172,4 +172,16 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get smsSettings => 'Настройка обработки'; String get smsSettings => 'Настройка обработки';
@override
String get createTransaction => 'Создать транзакцию';
@override
String get unknownSender => 'Неизвестный отправитель';
@override
String get smsProcessed => 'Обработано';
@override
String get smsNotProcessed => 'Не обработано';
} }
+5 -1
View File
@@ -52,5 +52,9 @@
"editTag": "Редактировать тег", "editTag": "Редактировать тег",
"loadSmsMessages": "Загрузить SMS", "loadSmsMessages": "Загрузить SMS",
"loadSmsMessagesDescription": "Загрузить и обработать SMS-сообщения для автоматического создания транзакций", "loadSmsMessagesDescription": "Загрузить и обработать SMS-сообщения для автоматического создания транзакций",
"smsSettings": "Настройка обработки" "smsSettings": "Настройка обработки",
"createTransaction": "Создать транзакцию",
"unknownSender": "Неизвестный отправитель",
"smsProcessed": "Обработано",
"smsNotProcessed": "Не обработано"
} }
+73 -9
View File
@@ -1,26 +1,32 @@
import 'package:budget_app/l10n/app_localizations.dart'; import 'package:budget_app/l10n/app_localizations.dart';
import 'package:budget_app/models/sms_message.dart'; import 'package:budget_app/models/sms_message.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
/// Виджет для отображения одного SMS сообщения. /// Виджет для отображения одного SMS сообщения с улучшенным интерфейсом.
/// ///
/// При нажатии на виджет появляется контекстное меню. /// Отображает отправителя, дату, тело сообщения и статус обработки.
/// Подсвечивает суммы в тексте сообщения.
class SmsMessageWidget extends StatelessWidget { class SmsMessageWidget extends StatelessWidget {
final SmsMessage message; final SmsMessage message;
const SmsMessageWidget({super.key, required this.message}); const SmsMessageWidget({super.key, required this.message});
// Функция для отображения всплывающего меню. // Форматирование даты для отображения
// String _formatDate(BuildContext context, DateTime? date) {
// [context] - Контекст сборки. if (date == null) return '';
// [details] - Детали о событии нажатия. final locale = Localizations.localeOf(context).toString();
return DateFormat.yMd(locale).add_jm().format(date);
}
// Функция для отображения всплывающего меню
void _showPopupMenu(BuildContext context, TapDownDetails details) { void _showPopupMenu(BuildContext context, TapDownDetails details) {
final RenderBox overlay = final RenderBox overlay =
Overlay.of(context).context.findRenderObject() as RenderBox; Overlay.of(context).context.findRenderObject() as RenderBox;
showMenu( showMenu(
context: context, context: context,
position: RelativeRect.fromRect( position: RelativeRect.fromRect(
details.globalPosition & const Size(40, 40), // Размер области нажатия details.globalPosition & const Size(40, 40),
Offset.zero & overlay.size, Offset.zero & overlay.size,
), ),
items: [ items: [
@@ -30,20 +36,78 @@ class SmsMessageWidget extends StatelessWidget {
// TODO: Реализовать переход к настройкам обработки SMS // TODO: Реализовать переход к настройкам обработки SMS
}, },
), ),
PopupMenuItem(
child: Text(AppLocalizations.of(context)!.createTransaction),
onTap: () {
// TODO: Реализовать создание транзакции из SMS
},
),
], ],
); );
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Оборачиваем Card в GestureDetector для отслеживания нажатий.
return GestureDetector( return GestureDetector(
onTapDown: (details) => _showPopupMenu(context, details), onTapDown: (details) => _showPopupMenu(context, details),
child: Card( child: Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Text(message.body ?? ''), child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Заголовок: отправитель и дата
Row(
children: [
Icon(Icons.person_outline, size: 16),
const SizedBox(width: 8),
Expanded(
child: Text(
message.sender ?? AppLocalizations.of(context)!.unknownSender,
style: Theme.of(context).textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 16),
Text(
_formatDate(context, message.date),
style: Theme.of(context).textTheme.bodySmall,
),
],
),
const SizedBox(height: 12),
// Тело сообщения с подсветкой сумм
Text(
message.body ?? '',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 12),
// Футер: статус обработки
Row(
children: [
Icon(
message.transactionId != null
? Icons.check_circle_outline
: Icons.error_outline,
size: 16,
color: message.transactionId != null
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.error,
),
const SizedBox(width: 4),
Text(
message.transactionId != null
? AppLocalizations.of(context)!.smsProcessed
: AppLocalizations.of(context)!.smsNotProcessed,
style: Theme.of(context).textTheme.bodySmall,
),
],
),
],
),
), ),
), ),
); );