diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4924aa4..42a95d8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -702,6 +702,7 @@ }, "chat_sendGif": "Send GIF", "chat_reply": "Reply", + "chat_replyWithRoute": "Reply with route", "chat_addReaction": "Add Reaction", "chat_me": "Me", "emojiCategorySmileys": "Smileys", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index ccdd201..8505916 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -2536,6 +2536,12 @@ abstract class AppLocalizations { /// **'Reply'** String get chat_reply; + /// No description provided for @chat_replyWithRoute. + /// + /// In en, this message translates to: + /// **'Reply with route'** + String get chat_replyWithRoute; + /// No description provided for @chat_addReaction. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 88cbfd6..255970e 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -1380,6 +1380,9 @@ class AppLocalizationsBg extends AppLocalizations { @override String get chat_reply => 'Отговори'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Добави Реакция'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 7d30fc3..9251278 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1379,6 +1379,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get chat_reply => 'Beantworten'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Reaktion hinzufügen'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 347190a..0d94948 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1351,6 +1351,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get chat_reply => 'Reply'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Add Reaction'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index fcd09c2..a7dc433 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -1378,6 +1378,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get chat_reply => 'Responder'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Añadir Reacción'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 95e4bbc..8eb0b68 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1383,6 +1383,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get chat_reply => 'Répondre'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Ajouter une Réaction'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index ad84875..60307ae 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -1385,6 +1385,9 @@ class AppLocalizationsHu extends AppLocalizations { @override String get chat_reply => 'Válasz'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Hozzon létre reakciót'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 73eb2d0..dcde96a 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -1380,6 +1380,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get chat_reply => 'Rispondi'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Aggiungi Reazione'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 9e7d910..07e0eac 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -1316,6 +1316,9 @@ class AppLocalizationsJa extends AppLocalizations { @override String get chat_reply => '返信'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => '反応を追加'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 08ee2a5..8d286b6 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -1311,6 +1311,9 @@ class AppLocalizationsKo extends AppLocalizations { @override String get chat_reply => '답변'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => '댓글 추가'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 40e2202..ae7a063 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -1367,6 +1367,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get chat_reply => 'Reageren'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Reactie toevoegen'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 5becab4..54c7029 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -1390,6 +1390,9 @@ class AppLocalizationsPl extends AppLocalizations { @override String get chat_reply => 'Odpowiedz'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Dodaj Reakcję'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index e65dc4d..da50fe9 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -1377,6 +1377,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get chat_reply => 'Responder'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Adicionar Reação'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 319eb02..ad2ced8 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -1378,6 +1378,9 @@ class AppLocalizationsRu extends AppLocalizations { @override String get chat_reply => 'Ответить'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Добавить реакцию'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index 43020e6..c6fcfbd 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -1367,6 +1367,9 @@ class AppLocalizationsSk extends AppLocalizations { @override String get chat_reply => 'Odpovedať'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Pridať Reakciu'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 75e0572..3b5d075 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -1365,6 +1365,9 @@ class AppLocalizationsSl extends AppLocalizations { @override String get chat_reply => 'Odgovori'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Dodaj reakcijo'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index eba3800..160d71d 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -1359,6 +1359,9 @@ class AppLocalizationsSv extends AppLocalizations { @override String get chat_reply => 'Svara'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Lägg till reaktion'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index 5c7d26c..07a5969 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -1372,6 +1372,9 @@ class AppLocalizationsUk extends AppLocalizations { @override String get chat_reply => 'Відповісти'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => 'Додати реакцію'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 8e747d1..7988d99 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -1297,6 +1297,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get chat_reply => '回复'; + @override + String get chat_replyWithRoute => 'Reply with route'; + @override String get chat_addReaction => '添加表情'; diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index fb6dc33..755a106 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -185,6 +185,11 @@ class _ChannelChatScreenState extends State { setState(() { _replyingToMessage = message; }); + // Drop the cursor straight into the composer (the reply banner has just + // laid out, so focus after the frame). Saves a click/tab on reply. (#131) + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) _textFieldFocusNode.requestFocus(); + }); } void _cancelReply() { @@ -1219,6 +1224,34 @@ class _ChannelChatScreenState extends State { ); } + /// One-click reply quoting the route a message took — hop count + path, + /// truncated with … to fit the channel byte budget, fired directly. (#106) + void _sendRouteReply(ChannelMessage message) { + final connector = context.read(); + final w = connector.pathHashByteWidth; + final hops = message.pathBytes.length ~/ (w < 1 ? 1 : w); + final prefix = + '@[${message.senderName}] ↩ ${context.l10n.chat_hopsCount(hops)} · via '; + final maxBytes = maxChannelMessageBytes(connector.selfName); + + var path = _formatPathPrefixes(message.pathBytes, w); + var truncated = false; + String outbound() => connector.prepareChannelOutboundText( + widget.channel.index, + '$prefix$path${truncated ? '…' : ''}', + ); + while (path.isNotEmpty && utf8.encode(outbound()).length > maxBytes) { + path = path.substring(0, path.length - 1); + truncated = true; + } + + var text = '$prefix$path${truncated ? '…' : ''}'; + if (connector.isChannelCyr2LatEnabled(widget.channel.index)) { + text = Cyr2Lat.encode(text); + } + connector.sendChannelMessage(widget.channel, text); + } + void _ensureDateFormats(BuildContext context) { final locale = Localizations.localeOf(context).toString(); final clock = context.read().settings.clockFormat; @@ -1394,6 +1427,15 @@ class _ChannelChatScreenState extends State { _setReplyingTo(message); }, ), + if (message.pathBytes.isNotEmpty) + ListTile( + leading: const Icon(Icons.alt_route), + title: Text(context.l10n.chat_replyWithRoute), + onTap: () { + Navigator.pop(sheetContext); + _sendRouteReply(message); + }, + ), if (PlatformInfo.isDesktop) ListTile( leading: const Icon(Icons.route), diff --git a/untranslated.json b/untranslated.json index c894cb7..b28dc3d 100644 --- a/untranslated.json +++ b/untranslated.json @@ -6,6 +6,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -17,6 +18,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -28,6 +30,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -39,6 +42,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -50,6 +54,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -61,6 +66,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -72,6 +78,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -83,6 +90,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -94,6 +102,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -105,6 +114,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -116,6 +126,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -127,6 +138,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -138,6 +150,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -149,6 +162,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -160,6 +174,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -171,6 +186,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ], @@ -182,6 +198,7 @@ "appSettings_clockSystem", "appSettings_clock12h", "appSettings_clock24h", + "chat_replyWithRoute", "channel_heardTooltip", "snrIndicator_noNeighbors" ]