diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index de87000d..896d84d3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -734,6 +734,7 @@ } }, "chat_sendGif": "Send GIF", + "chat_receivedGif": "Received a GIF", "chat_reply": "Reply", "chat_addReaction": "Add Reaction", "chat_me": "Me", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 2fdf7439..d34afa00 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -2692,6 +2692,12 @@ abstract class AppLocalizations { /// **'Send GIF'** String get chat_sendGif; + /// No description provided for @chat_receivedGif. + /// + /// In en, this message translates to: + /// **'Received a GIF'** + String get chat_receivedGif; + /// No description provided for @chat_reply. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 40604e9c..14768373 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -1468,6 +1468,9 @@ class AppLocalizationsBg extends AppLocalizations { @override String get chat_sendGif => 'Изпрати GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Отговори'; @@ -2706,7 +2709,6 @@ class AppLocalizationsBg extends AppLocalizations { 'Байтовете, използвани за кодиране на идентификатора на този повторител в таговете за откриване на потоци/цикли, са: 0=1 байт (256 идентификатора, до 64 скока), 1=2 байта (65 000 идентификатора, до 32 скока), 2=3 байта (16 милиона идентификатора, до 21 скока). Версиите 1.13 и по-старите фърмуери използват многобайтови пътища - само след като мрежата е актуализирана до версия 1.14 или по-нова.'; @override - String get repeater_txDelay => 'Забавяне на Flood TX'; String get repeater_keySettings => 'Change Identity Keys'; @override @@ -2742,6 +2744,7 @@ class AppLocalizationsBg extends AppLocalizations { } @override + String get repeater_txDelay => 'Забавяне на Flood TX'; @override String get repeater_txDelayHelper => diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 18dee3b6..cb434eb4 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1469,6 +1469,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get chat_sendGif => 'GIF senden'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Antworten'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 8e64f869..65bcc6a8 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1438,6 +1438,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get chat_sendGif => 'Send GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Reply'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index cc581454..d075d6c0 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -1465,6 +1465,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get chat_sendGif => 'Enviar GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Responder'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 6f853afb..9566987b 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1467,6 +1467,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get chat_sendGif => 'Envoyer un GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Répondre'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index ed24b80d..0679f558 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -1460,6 +1460,9 @@ class AppLocalizationsHu extends AppLocalizations { @override String get chat_sendGif => 'GIF küldése'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Válasz'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 8333bc93..4ebbae4c 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -1466,6 +1466,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get chat_sendGif => 'Invia GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Rispondi'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index f2c78eda..d012a95d 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -1395,6 +1395,9 @@ class AppLocalizationsJa extends AppLocalizations { @override String get chat_sendGif => 'GIF を送信'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => '返信'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index cd5cdfea..37f2b36b 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -1398,6 +1398,9 @@ class AppLocalizationsKo extends AppLocalizations { @override String get chat_sendGif => 'GIF 보내기'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => '답변'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 75e39e46..7c6c7762 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -1454,6 +1454,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get chat_sendGif => 'GIF verzenden'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Reageren'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 5a4c8508..40965bdd 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -1477,6 +1477,9 @@ class AppLocalizationsPl extends AppLocalizations { @override String get chat_sendGif => 'Wyślij GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Odpowiedz'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 31bd21e6..e41ef822 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -1464,6 +1464,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get chat_sendGif => 'Enviar GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Responder'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 5011e737..452308c7 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -1465,6 +1465,9 @@ class AppLocalizationsRu extends AppLocalizations { @override String get chat_sendGif => 'Отправить GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Ответить'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index eb1ad77c..cf0b4a5f 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -1454,6 +1454,9 @@ class AppLocalizationsSk extends AppLocalizations { @override String get chat_sendGif => 'Odoslať GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Odpovedať'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 030139bb..a5e0b3d6 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -1453,6 +1453,9 @@ class AppLocalizationsSl extends AppLocalizations { @override String get chat_sendGif => 'Pošlji GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Odgovori'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 1b3dcc1c..e4768664 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -1446,6 +1446,9 @@ class AppLocalizationsSv extends AppLocalizations { @override String get chat_sendGif => 'Skicka GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Svara'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index 68bfe695..7a3158b9 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -1459,6 +1459,9 @@ class AppLocalizationsUk extends AppLocalizations { @override String get chat_sendGif => 'Надіслати GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => 'Відповісти'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index d1b6b76c..edcaf12c 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -1381,6 +1381,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get chat_sendGif => '发送 GIF'; + @override + String get chat_receivedGif => 'Received a GIF'; + @override String get chat_reply => '回复'; diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index b6f66306..8b6e2b28 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -1579,9 +1579,11 @@ class _ChannelChatScreenState extends State { } String _formatPathPrefixes(Uint8List pathBytes) { + // Join with ", " (not bare ",") so long paths have soft-wrap break points + // and stay confined to the message bubble instead of overflowing right. return pathBytes .map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase()) - .join(','); + .join(', '); } Future openRegionSelectDialog(Channel channel) async { diff --git a/lib/screens/channels_screen.dart b/lib/screens/channels_screen.dart index 4b19d472..fb5039d2 100644 --- a/lib/screens/channels_screen.dart +++ b/lib/screens/channels_screen.dart @@ -27,6 +27,7 @@ import '../widgets/qr_code_display.dart'; import '../widgets/quick_switch_bar.dart'; import '../widgets/sync_progress_overlay.dart'; import '../widgets/unread_badge.dart'; +import '../helpers/gif_helper.dart'; import '../helpers/snack_bar_builder.dart'; import 'channel_chat_screen.dart'; import 'community_qr_scanner_screen.dart'; @@ -410,7 +411,11 @@ class _ChannelsScreenState extends State // Last message preview final messages = connector.getChannelMessages(channel); final lastMessage = messages.isNotEmpty ? messages.last : null; - final lastPreview = lastMessage?.text ?? ''; + final lastMessageText = lastMessage?.text ?? ''; + final lastPreview = lastMessageText.isNotEmpty && + GifHelper.parseGif(lastMessageText) != null + ? context.l10n.chat_receivedGif + : lastMessageText; final lastTime = lastMessage?.timestamp; final channelLabel = channel.name.isEmpty @@ -453,7 +458,7 @@ class _ChannelsScreenState extends State ) : null, child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ // Leading avatar with optional community badge Stack( @@ -581,10 +586,13 @@ class _ChannelsScreenState extends State const SizedBox(width: 4), ReorderableDragStartListener( index: dragIndex, + // Top-aligned with the "CH n" / time line. Bottom padding keeps + // a comfortable drag target without pushing the icon down. child: Padding( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.only(left: 8, right: 8, bottom: 16), child: Icon( Icons.drag_handle, + size: 18, color: scheme.onSurfaceVariant, ), ), diff --git a/lib/screens/neighbors_screen.dart b/lib/screens/neighbors_screen.dart index 529a00dd..219afa6e 100644 --- a/lib/screens/neighbors_screen.dart +++ b/lib/screens/neighbors_screen.dart @@ -276,7 +276,7 @@ class _NeighborsScreenState extends State { return Scaffold( appBar: AppBar( title: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Text( @@ -296,7 +296,7 @@ class _NeighborsScreenState extends State { ), ], ), - centerTitle: false, + centerTitle: true, actions: [ IconButton( icon: Icon(isFloodMode ? Icons.waves : Icons.route), diff --git a/lib/screens/telemetry_screen.dart b/lib/screens/telemetry_screen.dart index fafa68f2..96a59c75 100644 --- a/lib/screens/telemetry_screen.dart +++ b/lib/screens/telemetry_screen.dart @@ -334,7 +334,7 @@ class _TelemetryScreenState extends State { return Scaffold( appBar: AppBar( title: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Text( @@ -350,7 +350,7 @@ class _TelemetryScreenState extends State { ), ], ), - centerTitle: false, + centerTitle: true, bottom: const SyncProgressAppBarBottom(), actions: [ IconButton( diff --git a/lib/widgets/quick_switch_bar.dart b/lib/widgets/quick_switch_bar.dart index 90b90b40..917ceced 100644 --- a/lib/widgets/quick_switch_bar.dart +++ b/lib/widgets/quick_switch_bar.dart @@ -26,9 +26,16 @@ class QuickSwitchBar extends StatelessWidget { final colorScheme = theme.colorScheme; final labelStyle = theme.textTheme.labelMedium ?? const TextStyle(); final background = highContrast ? MapPalette.panelDark : Colors.transparent; - final selectedColor = highContrast + // The selected icon sits on the primary indicator pill, so it uses + // onPrimary. The label sits below on the bar background, so it must use a + // foreground color that contrasts with the surface (not onPrimary, which + // is white-on-white in the light theme). + final selectedIconColor = highContrast ? MapPalette.textPrimary : colorScheme.onPrimary; + final selectedLabelColor = highContrast + ? MapPalette.textPrimary + : colorScheme.onSurface; final unselectedColor = highContrast ? MapPalette.textSecondary : colorScheme.onSurfaceVariant; @@ -59,13 +66,13 @@ class QuickSwitchBar extends StatelessWidget { final isSelected = states.contains(WidgetState.selected); return labelStyle.copyWith( fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500, - color: isSelected ? selectedColor : unselectedColor, + color: isSelected ? selectedLabelColor : unselectedColor, ); }), iconTheme: WidgetStateProperty.resolveWith((states) { final isSelected = states.contains(WidgetState.selected); return IconThemeData( - color: isSelected ? selectedColor : unselectedColor, + color: isSelected ? selectedIconColor : unselectedColor, ); }), ), diff --git a/untranslated.json b/untranslated.json index e63eed61..8115c352 100644 --- a/untranslated.json +++ b/untranslated.json @@ -16,6 +16,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -32,6 +33,7 @@ "settings_regionFetchRegions", "settings_regionFetchRegionsFail", "settings_regionFetchRegionsAlreadyExists", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -61,6 +63,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -90,6 +93,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -119,6 +123,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -148,6 +153,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -177,6 +183,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -206,6 +213,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -235,6 +243,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -264,6 +273,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -293,6 +303,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -322,6 +333,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -351,6 +363,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -380,6 +393,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -409,6 +423,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -438,6 +453,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey", @@ -467,6 +483,7 @@ "channels_regionNotSet", "channels_regionSelect_Title", "channels_clearRegion", + "chat_receivedGif", "repeater_keySettings", "repeater_keySettingsSubtitle", "repeater_prvKey",