diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index dc6374a..96bf15d 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -1295,6 +1295,15 @@ class AppLocalizationsHu extends AppLocalizations { @override String get chat_sendGif => 'Küldj GIF-ot'; + @override + String get chat_insertEmoji => 'Insert emoji'; + + @override + String get chat_shareLocation => 'Share location'; + + @override + String get chat_locationUnavailable => 'Location not available'; + @override String get chat_reply => 'Válasz'; @@ -1732,6 +1741,9 @@ class AppLocalizationsHu extends AppLocalizations { @override String get map_sharedPin => 'Gemeinsames PIN-kód'; + @override + String get map_sharedAt => 'Shared'; + @override String get map_joinRoom => 'Csatlakozás a szobához'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 03d70d4..73bf50f 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -1228,6 +1228,15 @@ class AppLocalizationsJa extends AppLocalizations { @override String get chat_sendGif => 'GIFを送信する'; + @override + String get chat_insertEmoji => 'Insert emoji'; + + @override + String get chat_shareLocation => 'Share location'; + + @override + String get chat_locationUnavailable => 'Location not available'; + @override String get chat_reply => '返信'; @@ -1647,6 +1656,9 @@ class AppLocalizationsJa extends AppLocalizations { @override String get map_sharedPin => '共有パスワード'; + @override + String get map_sharedAt => 'Shared'; + @override String get map_joinRoom => '部屋に参加する'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 5e5925f..58dbffc 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -1223,6 +1223,15 @@ class AppLocalizationsKo extends AppLocalizations { @override String get chat_sendGif => 'GIF 보내기'; + @override + String get chat_insertEmoji => 'Insert emoji'; + + @override + String get chat_shareLocation => 'Share location'; + + @override + String get chat_locationUnavailable => 'Location not available'; + @override String get chat_reply => '답변'; @@ -1643,6 +1652,9 @@ class AppLocalizationsKo extends AppLocalizations { @override String get map_sharedPin => '공유 비밀번호'; + @override + String get map_sharedAt => 'Shared'; + @override String get map_joinRoom => '방에 참여'; diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index 6a1c78d..47067fa 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -936,8 +936,7 @@ class _ChannelChatScreenState extends State { final maxLabelBytes = maxBytes - utf8.encode(prefix).length - utf8.encode(suffix).length; - final defaultLabel = - '${connector.deviceDisplayName} ${DateTime.now().toUtc().toIso8601String()}'; + final defaultLabel = connector.deviceDisplayName; final controller = TextEditingController( text: truncateToUtf8Bytes(defaultLabel, maxLabelBytes), ); diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 7e328fc..3a9eb93 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -693,8 +693,7 @@ class _ChatScreenState extends State { final maxLabelBytes = maxBytes - utf8.encode(prefix).length - utf8.encode(suffix).length; - final defaultLabel = - '${connector.deviceDisplayName} ${DateTime.now().toUtc().toIso8601String()}'; + final defaultLabel = connector.deviceDisplayName; final controller = TextEditingController( text: truncateToUtf8Bytes(defaultLabel, maxLabelBytes), ); diff --git a/lib/screens/map_screen.dart b/lib/screens/map_screen.dart index 69c076b..1fc7c84 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -1222,7 +1222,7 @@ class _MapScreenState extends State { } List<_SharedMarker> _collectSharedMarkers(MeshCoreConnector connector) { - final markers = <_SharedMarker>[]; + final markersByKey = {}; final selfName = connector.selfName ?? 'Me'; for (final contact in connector.contacts) { @@ -1231,24 +1231,28 @@ class _MapScreenState extends State { final payload = _parseMarkerText(message.text); if (payload == null) continue; final fromName = message.isOutgoing ? selfName : contact.name; - final id = _buildMarkerId( + final key = _buildSharedMarkerKey( sourceId: contact.publicKeyHex, + label: payload.label, + fromName: fromName, + flags: payload.flags, + isChannel: false, + ); + final marker = _SharedMarker( + id: key, + position: payload.position, + label: payload.label, + flags: payload.flags, + fromName: fromName, + sourceLabel: contact.name, timestamp: message.timestamp, - text: message.text, - ); - markers.add( - _SharedMarker( - id: id, - position: payload.position, - label: payload.label, - flags: payload.flags, - fromName: fromName, - sourceLabel: contact.name, - timestamp: message.timestamp, - isChannel: false, - isPublicChannel: false, - ), + isChannel: false, + isPublicChannel: false, ); + final existing = markersByKey[key]; + if (existing == null || marker.timestamp.isAfter(existing.timestamp)) { + markersByKey[key] = marker; + } } } @@ -1258,29 +1262,35 @@ class _MapScreenState extends State { for (final message in messages) { final payload = _parseMarkerText(message.text); if (payload == null) continue; - final id = _buildMarkerId( + final key = _buildSharedMarkerKey( sourceId: 'channel:${channel.index}', + label: payload.label, + fromName: message.senderName, + flags: payload.flags, + isChannel: true, + ); + final marker = _SharedMarker( + id: key, + position: payload.position, + label: payload.label, + flags: payload.flags, + fromName: message.senderName, + sourceLabel: channel.name.isEmpty + ? 'Channel ${channel.index}' + : channel.name, timestamp: message.timestamp, - text: message.text, - ); - markers.add( - _SharedMarker( - id: id, - position: payload.position, - label: payload.label, - flags: payload.flags, - fromName: message.senderName, - sourceLabel: channel.name.isEmpty - ? 'Channel ${channel.index}' - : channel.name, - timestamp: message.timestamp, - isChannel: true, - isPublicChannel: isPublic, - ), + isChannel: true, + isPublicChannel: isPublic, ); + final existing = markersByKey[key]; + if (existing == null || marker.timestamp.isAfter(existing.timestamp)) { + markersByKey[key] = marker; + } } } + final markers = markersByKey.values.toList() + ..sort((a, b) => b.timestamp.compareTo(a.timestamp)); return markers; } @@ -1305,12 +1315,18 @@ class _MapScreenState extends State { ); } - String _buildMarkerId({ + String _buildSharedMarkerKey({ required String sourceId, - required DateTime timestamp, - required String text, + required String label, + required String fromName, + required String flags, + required bool isChannel, }) { - return '$sourceId|${timestamp.millisecondsSinceEpoch}|$text'; + final normalizedLabel = label.trim().toLowerCase(); + final normalizedFrom = fromName.trim().toLowerCase(); + final normalizedFlags = flags.trim().toLowerCase(); + final scope = isChannel ? 'ch' : 'dm'; + return '$scope|$sourceId|$normalizedFrom|$normalizedLabel|$normalizedFlags'; } Marker _buildSharedMarker(_SharedMarker marker) { diff --git a/untranslated.json b/untranslated.json index 9e26dfe..4ee03d4 100644 --- a/untranslated.json +++ b/untranslated.json @@ -1 +1,22 @@ -{} \ No newline at end of file +{ + "hu": [ + "chat_insertEmoji", + "chat_shareLocation", + "chat_locationUnavailable", + "map_sharedAt" + ], + + "ja": [ + "chat_insertEmoji", + "chat_shareLocation", + "chat_locationUnavailable", + "map_sharedAt" + ], + + "ko": [ + "chat_insertEmoji", + "chat_shareLocation", + "chat_locationUnavailable", + "map_sharedAt" + ] +}