Compare commits

..

16 Commits

Author SHA1 Message Date
zjs81 4239fb11ed Fix radio settings to only send repeat byte when the current state is known 2026-02-18 00:07:08 -07:00
zjs81 5fae2e5f73 fix formatting 2026-02-17 23:50:11 -07:00
zjs81 947fafbbb7 Refactor radio settings and localization updates
fixes #72

- Removed preset configurations for 915 MHz, 868 MHz, and 433 MHz from the RadioSettings model.
- Introduced a new list of regional preset configurations for various countries.
- Updated the settings screen to use a dropdown for selecting presets instead of chips.
- Added a switch for enabling client repeat functionality with appropriate warnings for frequency usage.
- Updated localization files for multiple languages to reflect changes in settings related to client repeat functionality.
2026-02-17 23:42:04 -07:00
zjs81 72f0aa7208 Update dependencies and improve code consistency across multiple files 2026-02-14 02:22:45 -07:00
zjs81 f87d4896ab Merge pull request #161 from ChaoticLeah/enhancement/bluetooth-disabled-warning
Add warning when bluetooth is off
2026-02-14 02:00:36 -07:00
zjs81 9250dfec31 Gate the turn on BLE button to android 2026-02-14 01:54:30 -07:00
zjs81 37db955ab2 Fixed banner flash, added enable bluetooth button fixed theme to use app theme colors removed FAB overrides because material 3 does this for us, fixed missing translations. 2026-02-14 01:46:40 -07:00
zjs81 739d9475c0 Merge remote-tracking branch 'origin/main' into enhancement/bluetooth-disabled-warning 2026-02-14 01:28:54 -07:00
zjs81 b526175be4 bump version for android 2026-02-14 01:13:06 -07:00
Winston Lowe 73081862ad Add path tracing functionality (#165)
- Implemented path tracing feature in the map screen, allowing users to add nodes to a path and visualize it on the map.
- Added buttons for starting path tracing, removing the last node, and running the path trace.
- Introduced a new overlay to display current path information and distance.
- Updated localization files for multiple languages to include new strings related to path tracing.
- Refactored map rendering logic to accommodate path tracing visuals.
2026-02-14 01:10:34 -07:00
Leah ef6bd78632 Merge branch 'enhancement/bluetooth-disabled-warning' of github.com:ChaoticLeah/meshcore-open into enhancement/bluetooth-disabled-warning 2026-02-12 20:15:58 +01:00
Leah 01c8390989 make stuff unawaited + maybe fix edge case? 2026-02-12 20:14:56 +01:00
Leah c05f813d65 Update lib/screens/scanner_screen.dart
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-12 20:02:56 +01:00
Leah bc77f7e287 Remove unused translation
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-11 23:03:41 +01:00
Leah 9332d8126f linted and added greying out 2026-02-11 22:58:15 +01:00
Leah 9ce00556ec Add warning when bluetooth is off 2026-02-11 22:40:42 +01:00
52 changed files with 1816 additions and 1422 deletions
+1 -1
View File
@@ -83,5 +83,5 @@ flutter {
} }
dependencies { dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
} }
+14 -217
View File
@@ -2,8 +2,6 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:crypto/crypto.dart' as crypto; import 'package:crypto/crypto.dart' as crypto;
import 'package:geolocator/geolocator.dart';
import 'package:meshcore_open/services/sparse_location_logger.dart';
import 'package:pointycastle/export.dart'; import 'package:pointycastle/export.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart';
@@ -92,6 +90,8 @@ class MeshCoreConnector extends ChangeNotifier {
int? _currentBwHz; int? _currentBwHz;
int? _currentSf; int? _currentSf;
int? _currentCr; int? _currentCr;
bool? _clientRepeat;
int? _firmwareVerCode;
int? _batteryMillivolts; int? _batteryMillivolts;
double? _selfLatitude; double? _selfLatitude;
double? _selfLongitude; double? _selfLongitude;
@@ -132,7 +132,6 @@ class MeshCoreConnector extends ChangeNotifier {
PathHistoryService? _pathHistoryService; PathHistoryService? _pathHistoryService;
AppSettingsService? _appSettingsService; AppSettingsService? _appSettingsService;
BackgroundService? _backgroundService; BackgroundService? _backgroundService;
SparseLocationLogger? _sparseLocationLogger;
final NotificationService _notificationService = NotificationService(); final NotificationService _notificationService = NotificationService();
BleDebugLogService? _bleDebugLogService; BleDebugLogService? _bleDebugLogService;
AppDebugLogService? _appDebugLogService; AppDebugLogService? _appDebugLogService;
@@ -203,6 +202,8 @@ class MeshCoreConnector extends ChangeNotifier {
int? get currentBwHz => _currentBwHz; int? get currentBwHz => _currentBwHz;
int? get currentSf => _currentSf; int? get currentSf => _currentSf;
int? get currentCr => _currentCr; int? get currentCr => _currentCr;
bool? get clientRepeat => _clientRepeat;
int? get firmwareVerCode => _firmwareVerCode;
Map<String, String>? get currentCustomVars => _currentCustomVars; Map<String, String>? get currentCustomVars => _currentCustomVars;
int? get batteryMillivolts => _batteryMillivolts; int? get batteryMillivolts => _batteryMillivolts;
int get maxContacts => _maxContacts; int get maxContacts => _maxContacts;
@@ -505,7 +506,6 @@ class MeshCoreConnector extends ChangeNotifier {
BleDebugLogService? bleDebugLogService, BleDebugLogService? bleDebugLogService,
AppDebugLogService? appDebugLogService, AppDebugLogService? appDebugLogService,
BackgroundService? backgroundService, BackgroundService? backgroundService,
SparseLocationLogger? sparseLocationLogger,
}) { }) {
_retryService = retryService; _retryService = retryService;
_pathHistoryService = pathHistoryService; _pathHistoryService = pathHistoryService;
@@ -513,14 +513,11 @@ class MeshCoreConnector extends ChangeNotifier {
_bleDebugLogService = bleDebugLogService; _bleDebugLogService = bleDebugLogService;
_appDebugLogService = appDebugLogService; _appDebugLogService = appDebugLogService;
_backgroundService = backgroundService; _backgroundService = backgroundService;
_sparseLocationLogger = sparseLocationLogger;
// Initialize notification service // Initialize notification service
_notificationService.initialize(); _notificationService.initialize();
_loadChannelOrder(); _loadChannelOrder();
_sparseLocationLogger?.initialize(_updateLocationandAdvert);
// Initialize retry service callbacks // Initialize retry service callbacks
_retryService?.initialize( _retryService?.initialize(
sendMessageCallback: _sendMessageDirect, sendMessageCallback: _sendMessageDirect,
@@ -835,8 +832,6 @@ class MeshCoreConnector extends ChangeNotifier {
return result; return result;
} }
SparseLocationLogger? get sparseLocationLogger => _sparseLocationLogger;
bool get _shouldAutoReconnect => !_manualDisconnect && _lastDeviceId != null; bool get _shouldAutoReconnect => !_manualDisconnect && _lastDeviceId != null;
void _cancelReconnectTimer() { void _cancelReconnectTimer() {
@@ -925,6 +920,8 @@ class MeshCoreConnector extends ChangeNotifier {
_selfName = null; _selfName = null;
_selfLatitude = null; _selfLatitude = null;
_selfLongitude = null; _selfLongitude = null;
_clientRepeat = null;
_firmwareVerCode = null;
_batteryMillivolts = null; _batteryMillivolts = null;
_batteryRequested = false; _batteryRequested = false;
_awaitingSelfInfo = false; _awaitingSelfInfo = false;
@@ -1699,11 +1696,6 @@ class MeshCoreConnector extends ChangeNotifier {
_isLoadingContacts = true; _isLoadingContacts = true;
notifyListeners(); notifyListeners();
break; break;
case pushCodeNewAdvert:
debugPrint('Got New CONTACT');
// It the same format as respCodeContact, so we can reuse the handler
_handleContact(frame);
break;
case respCodeContact: case respCodeContact:
debugPrint('Got CONTACT'); debugPrint('Got CONTACT');
_handleContact(frame); _handleContact(frame);
@@ -1748,7 +1740,6 @@ class MeshCoreConnector extends ChangeNotifier {
case pushCodeStatusResponse: case pushCodeStatusResponse:
break; break;
case pushCodeLogRxData: case pushCodeLogRxData:
_handleRxData(frame);
_handleLogRxData(frame); _handleLogRxData(frame);
break; break;
case respCodeChannelInfo: case respCodeChannelInfo:
@@ -1762,7 +1753,6 @@ class MeshCoreConnector extends ChangeNotifier {
break; break;
case respCodeCustomVars: case respCodeCustomVars:
_handleCustomVars(frame); _handleCustomVars(frame);
break;
default: default:
debugPrint('Unknown frame code: $code'); debugPrint('Unknown frame code: $code');
} }
@@ -1836,6 +1826,13 @@ class MeshCoreConnector extends ChangeNotifier {
void _handleDeviceInfo(Uint8List frame) { void _handleDeviceInfo(Uint8List frame) {
if (frame.length < 4) return; if (frame.length < 4) return;
_firmwareVerCode = frame[1];
// Parse client_repeat from firmware v9+ (byte 80)
if (frame.length >= 81) {
_clientRepeat = frame[80] != 0;
}
// Firmware reports MAX_CONTACTS / 2 for v3+ device info. // Firmware reports MAX_CONTACTS / 2 for v3+ device info.
final reportedContacts = frame[2]; final reportedContacts = frame[2];
final reportedChannels = frame[3]; final reportedChannels = frame[3];
@@ -1856,8 +1853,8 @@ class MeshCoreConnector extends ChangeNotifier {
unawaited(getChannels(maxChannels: nextMaxChannels)); unawaited(getChannels(maxChannels: nextMaxChannels));
} }
} }
notifyListeners();
} }
notifyListeners();
} }
void _handleNoMoreMessages() { void _handleNoMoreMessages() {
@@ -2018,76 +2015,6 @@ class MeshCoreConnector extends ChangeNotifier {
} }
} }
void _handleContactAdvert(Contact contact) {
if (contact.type == advTypeRepeater) {
_contactUnreadCount.remove(contact.publicKeyHex);
_unreadStore.saveContactUnreadCount(
Map<String, int>.from(_contactUnreadCount),
);
}
// Check if this is a new contact
final isNewContact = !_knownContactKeys.contains(contact.publicKeyHex);
final existingIndex = _contacts.indexWhere(
(c) => c.publicKeyHex == contact.publicKeyHex,
);
if (existingIndex >= 0) {
final existing = _contacts[existingIndex];
final mergedLastMessageAt =
existing.lastMessageAt.isAfter(contact.lastMessageAt)
? existing.lastMessageAt
: contact.lastMessageAt;
appLogger.info(
'Refreshing contact ${contact.name}: devicePath=${contact.pathLength}, existingOverride=${existing.pathOverride}',
tag: 'Connector',
);
// CRITICAL: Preserve user's path override when contact is refreshed from device
_contacts[existingIndex] = contact.copyWith(
lastMessageAt: mergedLastMessageAt,
pathOverride: existing.pathOverride, // Preserve user's path choice
pathOverrideBytes: existing.pathOverrideBytes,
);
appLogger.info(
'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_contacts[existingIndex].pathLength}',
tag: 'Connector',
);
} else {
_contacts.add(contact);
appLogger.info(
'Added new contact ${contact.name}: pathLen=${contact.pathLength}',
tag: 'Connector',
);
}
_knownContactKeys.add(contact.publicKeyHex);
_loadMessagesForContact(contact.publicKeyHex);
// Add path to history if we have a valid path
if (_pathHistoryService != null && contact.pathLength >= 0) {
_pathHistoryService!.handlePathUpdated(contact);
}
notifyListeners();
// Show notification for new contact (advertisement)
if (isNewContact && _appSettingsService != null) {
final settings = _appSettingsService!.settings;
if (settings.notificationsEnabled && settings.notifyOnNewAdvert) {
_notificationService.showAdvertNotification(
contactName: contact.name,
contactType: contact.typeLabel,
contactId: contact.publicKeyHex,
);
}
}
if (!_isLoadingContacts) {
unawaited(_persistContacts());
}
}
Future<void> _persistContacts() async { Future<void> _persistContacts() async {
await _contactStore.saveContacts(_contacts); await _contactStore.saveContacts(_contacts);
} }
@@ -3371,136 +3298,6 @@ class MeshCoreConnector extends ChangeNotifier {
super.dispose(); super.dispose();
} }
_updateLocationandAdvert(Position position) async {
final snapToGridCenter = _sparseLocationLogger?.snapToGridCenter(
position: position,
cellSizeMeters: 0.001,
);
double lat = snapToGridCenter?.latitude ?? 0.0;
double lon = snapToGridCenter?.longitude ?? 0.0;
if (lat == 0.0 && lon == 0.0) {
debugPrint('Invalid location (0,0), skipping advert');
return;
}
await sendFrame(buildSetOtherParamsFrame(true, 1, 1, 0));
await setNodeLocation(lat: lat, lon: lon);
await sendSelfAdvert(flood: true);
_selfLatitude = lat;
_selfLongitude = lon;
notifyListeners();
}
void _handleRxData(Uint8List frame) {
final packet = BufferReader(frame);
packet.skipBytes(3); // Skip frame type byte
//final snr = packet.readByte() / 4.0;
//final rssi = packet.readByte();
final header = packet.readByte();
//final routeType = header & 0x03;
final payloadType = (header >> 2) & 0x0F;
//final payloadVer = (header >> 6) & 0x03;
if (packet.remaining <= 0) return;
final pathLen = packet.readByte();
if (packet.remaining < pathLen) return;
final pathBytes = packet.readBytes(pathLen);
if (packet.remaining <= 0) return;
final payload = packet.readBytes(packet.remaining);
switch (payloadType) {
case payloadTypeADVERT:
_handlePayloadAdvertReceived(payload, pathBytes);
break;
default:
}
}
void _handlePayloadAdvertReceived(Uint8List frame, Uint8List path) {
final advert = BufferReader(frame);
if (advert.remaining <= 32) return;
final publicKey = advert.readBytes(32);
final contactKeyHex = publicKey
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join();
if (advert.remaining <= 4) return;
final timestamp = advert.readInt32LE();
if (advert.remaining <= 64) return;
advert.skipBytes(64); // Skip signature for now
if (advert.remaining <= 1) return;
final flags = advert.readByte();
final type = flags & 0x0F;
final hasLocation = (flags & 0x10) != 0;
//final hasFeature1 = (flags & 0x20) != 0;
//final hasFeature2 = (flags & 0x40) != 0;
final hasName = (flags & 0x80) != 0;
double latitude = 0.0;
double longitude = 0.0;
if (hasLocation && advert.remaining >= 8) {
latitude = advert.readInt32LE() / 1e6;
longitude = advert.readInt32LE() / 1e6;
}
String name = '';
if (hasName && advert.remaining > 0) {
name = advert.readString();
}
// Check if this is a new contact
final isNewContact = !_knownContactKeys.contains(contactKeyHex);
if (isNewContact) {
_handleContactAdvert(
Contact(
publicKey: publicKey,
name: name,
type: type,
pathLength: path.length,
path: path,
latitude: latitude,
longitude: longitude,
lastSeen: DateTime.fromMillisecondsSinceEpoch(timestamp * 1000),
),
);
return;
}
final existingIndex = _contacts.indexWhere(
(c) => c.publicKeyHex == contactKeyHex,
);
if (existingIndex >= 0) {
final existing = _contacts[existingIndex];
final mergedLastMessageAt = existing.lastMessageAt.isAfter(DateTime.now())
? DateTime.now()
: existing.lastMessageAt;
appLogger.info(
'Refreshing contact ${existing.name}: devicePath=${existing.pathLength}, existingOverride=${existing.pathOverride}',
tag: 'Connector',
);
// CRITICAL: Preserve user's path override when contact is refreshed from device
_contacts[existingIndex] = existing.copyWith(
latitude: hasLocation ? latitude : existing.latitude,
longitude: hasLocation ? longitude : existing.longitude,
name: hasName ? name : existing.name,
path: path,
pathLength: path.length,
lastMessageAt: mergedLastMessageAt,
lastSeen: DateTime.fromMillisecondsSinceEpoch(timestamp * 1000),
pathOverride: existing.pathOverride, // Preserve user's path choice
pathOverrideBytes: existing.pathOverrideBytes,
);
appLogger.info(
'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_contacts[existingIndex].pathLength}',
tag: 'Connector',
);
notifyListeners();
}
}
} }
const int _phRouteMask = 0x03; const int _phRouteMask = 0x03;
+13 -46
View File
@@ -151,7 +151,6 @@ const int cmdGetContactByKey = 30;
const int cmdGetChannel = 31; const int cmdGetChannel = 31;
const int cmdSetChannel = 32; const int cmdSetChannel = 32;
const int cmdSendTracePath = 36; const int cmdSendTracePath = 36;
const int cmdSetOtherParams = 38;
const int cmdGetRadioSettings = 57; const int cmdGetRadioSettings = 57;
const int cmdGetTelemetryReq = 39; const int cmdGetTelemetryReq = 39;
const int cmdGetCustomVar = 40; const int cmdGetCustomVar = 40;
@@ -213,30 +212,6 @@ const int advTypeRepeater = 2;
const int advTypeRoom = 3; const int advTypeRoom = 3;
const int advTypeSensor = 4; const int advTypeSensor = 4;
// Payload Types
const int payloadTypeREQ =
0x00; // request (prefixed with dest/src hashes, MAC) (enc data: timestamp, blob)
const int payloadTypeRESPONSE =
0x01; // response to REQ or ANON_REQ (prefixed with dest/src hashes, MAC) (enc data: timestamp, blob)
const int payloadTypeTXTMSG =
0x02; // a plain text message (prefixed with dest/src hashes, MAC) (enc data: timestamp, text)
const int payloadTypeACK = 0x03; // a simple ack
const int payloadTypeADVERT = 0x04; // a node advertising its Identity
const int payloadTypeGRPTXT =
0x05; // an (unverified) group text message (prefixed with channel hash, MAC) (enc data: timestamp, "name: msg")
const int payloadTypeGRPDATA =
0x06; // an (unverified) group datagram (prefixed with channel hash, MAC) (enc data: timestamp, blob)
const int payloadTypeANONREQ =
0x07; // generic request (prefixed with dest_hash, ephemeral pub_key, MAC) (enc data: ...)
const int payloadTypePATH =
0x08; // returned path (prefixed with dest/src hashes, MAC) (enc data: path, extra)
const int payloadTypeTRACE = 0x09; // trace a path, collecting SNI for each hop
const int payloadTypeMULTIPART = 0x0A; // packet is one of a set of packets
const int payloadTypeCONTROL = 0x0B; // a control/discovery packet
//...
const int payloadTypeRawCustom =
0x0F; // custom packet as raw bytes, for applications with custom encryption, payloads, etc
// Sizes // Sizes
const int pubKeySize = 32; const int pubKeySize = 32;
const int maxPathSize = 64; const int maxPathSize = 64;
@@ -575,18 +550,29 @@ Uint8List buildSetChannelFrame(int channelIndex, String name, Uint8List psk) {
} }
// Build CMD_SET_RADIO_PARAMS frame // Build CMD_SET_RADIO_PARAMS frame
// Format: [cmd][freq x4][bw x4][sf][cr] // Format: [cmd][freq x4][bw x4][sf][cr] (pre-v9)
// [cmd][freq x4][bw x4][sf][cr][repeat] (firmware v9+)
// freq: frequency in Hz (300000-2500000) // freq: frequency in Hz (300000-2500000)
// bw: bandwidth in Hz (7000-500000) // bw: bandwidth in Hz (7000-500000)
// sf: spreading factor (5-12) // sf: spreading factor (5-12)
// cr: coding rate (5-8) // cr: coding rate (5-8)
Uint8List buildSetRadioParamsFrame(int freqHz, int bwHz, int sf, int cr) { // clientRepeat: enable off-grid packet repeat (firmware v9+, omit for older)
Uint8List buildSetRadioParamsFrame(
int freqHz,
int bwHz,
int sf,
int cr, {
bool? clientRepeat,
}) {
final writer = BufferWriter(); final writer = BufferWriter();
writer.writeByte(cmdSetRadioParams); writer.writeByte(cmdSetRadioParams);
writer.writeUInt32LE(freqHz); writer.writeUInt32LE(freqHz);
writer.writeUInt32LE(bwHz); writer.writeUInt32LE(bwHz);
writer.writeByte(sf); writer.writeByte(sf);
writer.writeByte(cr); writer.writeByte(cr);
if (clientRepeat != null) {
writer.writeByte(clientRepeat ? 1 : 0);
}
return writer.toBytes(); return writer.toBytes();
} }
@@ -802,22 +788,3 @@ Uint8List buildZeroHopContact(Uint8List pubKey) {
writer.writeBytes(pubKey); writer.writeBytes(pubKey);
return writer.toBytes(); return writer.toBytes();
} }
// Build CMD_SET_OTHER_PARAMS frame
// Format: [cmd][allowAutoAddContacts][allowTelemetryFlags][advertLocationPolicy][multiAcks]
Uint8List buildSetOtherParamsFrame(
bool allowAutoAddContacts,
int allowTelemetryFlags,
int advertLocationPolicy,
int multiAcks,
) {
final writer = BufferWriter();
writer.writeByte(cmdSetOtherParams);
writer.writeByte(
allowAutoAddContacts ? 0x00 : 0x01,
); // Allow Auto Add Contacts
writer.writeByte(allowTelemetryFlags); // Allow Telemetry Flags
writer.writeByte(advertLocationPolicy); // Advertisement Location Policy
writer.writeByte(multiAcks); // Multi Acknowledgements
return writer.toBytes();
}
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Брой контакти", "settings_infoContactsCount": "Брой контакти",
"settings_infoChannelCount": "Брой канали", "settings_infoChannelCount": "Брой канали",
"settings_presets": "Предварителни настройки", "settings_presets": "Предварителни настройки",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Честота (MHz)", "settings_frequency": "Честота (MHz)",
"settings_frequencyHelper": "300.0 - 2500.0", "settings_frequencyHelper": "300.0 - 2500.0",
"settings_frequencyInvalid": "Невалидна честота (300-2500 MHz)", "settings_frequencyInvalid": "Невалидна честота (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Мощност (dBm)", "settings_txPower": "TX Мощност (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Невалидна мощност на TX (0-22 dBm)", "settings_txPowerInvalid": "Невалидна мощност на TX (0-22 dBm)",
"settings_longRange": "Дълъг обхват",
"settings_fastSpeed": "Бърза скорост",
"settings_error": "Грешка: {message}", "settings_error": "Грешка: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{нов възел} other{нови възли}}", "notification_newNodesCount": "{count} {count, plural, =1{нов възел} other{нови възли}}",
"notification_newTypeDiscovered": "Открит нов {contactType}", "notification_newTypeDiscovered": "Открит нов {contactType}",
"notification_receivedNewMessage": "Получено ново съобщение", "notification_receivedNewMessage": "Получено ново съобщение",
"contacts_contactAdvertCopyFailed": "Копирането на обявата в клипборда не успя.",
"settings_gpxExportContactsSubtitle": "Експортира спътници с местоположение в GPX файл.", "settings_gpxExportContactsSubtitle": "Експортира спътници с местоположение в GPX файл.",
"settings_gpxExportRepeatersSubtitle": "Изпраща повторители / roomserver с местоположение в GPX файл.", "settings_gpxExportRepeatersSubtitle": "Изпраща повторители / roomserver с местоположение в GPX файл.",
"settings_gpxExportAll": "Експортирай всички контакти в GPX", "settings_gpxExportAll": "Експортирай всички контакти в GPX",
@@ -1591,6 +1585,16 @@
"settings_gpxExportAllContacts": "Местоположения на всички контакти", "settings_gpxExportAllContacts": "Местоположения на всички контакти",
"settings_gpxExportShareText": "Картинни данни изнесени от meshcore-open", "settings_gpxExportShareText": "Картинни данни изнесени от meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open износ на данни за карта в формат GPX", "settings_gpxExportShareSubject": "meshcore-open износ на данни за карта в формат GPX",
"pathTrace_someHopsNoLocation": "Един или повече от хмелите липсва местоположение!" "pathTrace_someHopsNoLocation": "Един или повече от хмелите липсва местоположение!",
"map_pathTraceCancelled": "Отменен е следването на пътя.",
"pathTrace_clearTooltip": "Изчисти пътя",
"map_removeLast": "Премахни Последно",
"map_runTrace": "Изпълни Път на Следване",
"map_tapToAdd": "Натиснете върху възлите, за да ги добавите към пътя.",
"scanner_bluetoothOff": "Bluetooth е изключен.",
"scanner_enableBluetooth": "Активирайте Bluetooth",
"scanner_bluetoothOffMessage": "Моля, активирайте Bluetooth, за да сканирате за устройства.",
"settings_clientRepeatSubtitle": "Позволете на това устройство да предава пакети към мрежата за други устройства.",
"settings_clientRepeatFreqWarning": "За повторение извън мрежата са необходими честоти от 433, 869 или 918 MHz.",
"settings_clientRepeat": "Без електричество – повторение"
} }
+24 -13
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Anzahl Kontakte", "settings_infoContactsCount": "Anzahl Kontakte",
"settings_infoChannelCount": "Anzahl Kanäle", "settings_infoChannelCount": "Anzahl Kanäle",
"settings_presets": "Voreinstellungen", "settings_presets": "Voreinstellungen",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frequenz (MHz)", "settings_frequency": "Frequenz (MHz)",
"settings_frequencyHelper": "300,00 - 2.500,00", "settings_frequencyHelper": "300,00 - 2.500,00",
"settings_frequencyInvalid": "Ungültige Frequenz (300-2500 MHz)", "settings_frequencyInvalid": "Ungültige Frequenz (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX-Leistung (dBm)", "settings_txPower": "TX-Leistung (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Ungültige TX-Leistung (0-22 dBm)", "settings_txPowerInvalid": "Ungültige TX-Leistung (0-22 dBm)",
"settings_longRange": "Grosse Reichweite",
"settings_fastSpeed": "Schnelle Geschwindigkeit",
"settings_error": "Fehler: {message}", "settings_error": "Fehler: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1569,34 +1564,40 @@
"contacts_zeroHopContactAdvertSent": "Kontakt über Anzeige gesendet", "contacts_zeroHopContactAdvertSent": "Kontakt über Anzeige gesendet",
"contacts_contactAdvertCopied": "Anzeige in die Zwischenablage kopiert.", "contacts_contactAdvertCopied": "Anzeige in die Zwischenablage kopiert.",
"contacts_contactAdvertCopyFailed": "Kopieren der Ankündigung in die Zwischenablage fehlgeschlagen.", "contacts_contactAdvertCopyFailed": "Kopieren der Ankündigung in die Zwischenablage fehlgeschlagen.",
"notification_activityTitle": "MeshCore Aktivität", "notification_activityTitle": "MeshCore Aktivität",
"notification_messagesCount": "{count} {count, plural, =1{Nachricht} other{Nachrichten}}", "notification_messagesCount": "{count} {count, plural, =1{Nachricht} other{Nachrichten}}",
"@notification_messagesCount": { "@notification_messagesCount": {
"placeholders": { "placeholders": {
"count": {"type": "int"} "count": {
"type": "int"
}
} }
}, },
"notification_channelMessagesCount": "{count} {count, plural, =1{Kanalnachricht} other{Kanalnachrichten}}", "notification_channelMessagesCount": "{count} {count, plural, =1{Kanalnachricht} other{Kanalnachrichten}}",
"@notification_channelMessagesCount": { "@notification_channelMessagesCount": {
"placeholders": { "placeholders": {
"count": {"type": "int"} "count": {
"type": "int"
}
} }
}, },
"notification_newNodesCount": "{count} {count, plural, =1{neuer Knoten} other{neue Knoten}}", "notification_newNodesCount": "{count} {count, plural, =1{neuer Knoten} other{neue Knoten}}",
"@notification_newNodesCount": { "@notification_newNodesCount": {
"placeholders": { "placeholders": {
"count": {"type": "int"} "count": {
"type": "int"
}
} }
}, },
"notification_newTypeDiscovered": "Neuer {contactType} entdeckt", "notification_newTypeDiscovered": "Neuer {contactType} entdeckt",
"@notification_newTypeDiscovered": { "@notification_newTypeDiscovered": {
"placeholders": { "placeholders": {
"contactType": {"type": "String"} "contactType": {
"type": "String"
}
} }
}, },
"notification_receivedNewMessage": "Neue Nachricht empfangen", "notification_receivedNewMessage": "Neue Nachricht empfangen",
"contacts_contactAdvertCopyFailed": "Kopieren der Ankündigung in die Zwischenablage fehlgeschlagen.",
"settings_gpxExportAll": "Alle Knoten als GPX exportieren", "settings_gpxExportAll": "Alle Knoten als GPX exportieren",
"settings_gpxExportAllSubtitle": "Exportiert alle Knoten mit einem Standort in eine GPX-Datei.", "settings_gpxExportAllSubtitle": "Exportiert alle Knoten mit einem Standort in eine GPX-Datei.",
"settings_gpxExportRepeaters": "Repeater und Raumserver als GPX exportieren", "settings_gpxExportRepeaters": "Repeater und Raumserver als GPX exportieren",
@@ -1612,6 +1613,16 @@
"settings_gpxExportAllContacts": "Alle Kontaktstandorte", "settings_gpxExportAllContacts": "Alle Kontaktstandorte",
"settings_gpxExportShareSubject": "GPX-Kartendaten aus meshcore-open exportieren", "settings_gpxExportShareSubject": "GPX-Kartendaten aus meshcore-open exportieren",
"settings_gpxExportShareText": "GPX-Kartendaten aus meshcore-open exportiert", "settings_gpxExportShareText": "GPX-Kartendaten aus meshcore-open exportiert",
"pathTrace_someHopsNoLocation": "Bei einer oder mehreren Knoten fehlt der Standort!" "pathTrace_someHopsNoLocation": "Bei einer oder mehreren Knoten fehlt der Standort!",
"map_removeLast": "Letztes Entfernen",
"map_tapToAdd": "Tippen Sie auf Knoten, um sie zum Pfad hinzuzufügen.",
"map_runTrace": "Pfadverlauf ausführen",
"pathTrace_clearTooltip": "Pfad löschen",
"map_pathTraceCancelled": "Pfadverfolgung abgebrochen.",
"scanner_bluetoothOffMessage": "Bitte aktivieren Sie Bluetooth, um nach Geräten zu suchen.",
"scanner_bluetoothOff": "Bluetooth ist deaktiviert.",
"scanner_enableBluetooth": "Bluetooth aktivieren",
"settings_clientRepeat": "Wiederholung, ohne Stromanschluss",
"settings_clientRepeatFreqWarning": "Die Kommunikation ohne Stromversorgung erfordert Frequenzen von 433, 869 oder 918 MHz.",
"settings_clientRepeatSubtitle": "Ermöglichen Sie diesem Gerät, Mesh-Pakete für andere zu wiederholen."
} }
+406 -170
View File
File diff suppressed because it is too large Load Diff
+24 -13
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Número de contactos", "settings_infoContactsCount": "Número de contactos",
"settings_infoChannelCount": "Número de canales", "settings_infoChannelCount": "Número de canales",
"settings_presets": "Preajustes", "settings_presets": "Preajustes",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frecuencia (MHz)", "settings_frequency": "Frecuencia (MHz)",
"settings_frequencyHelper": "300,0 - 2500,0", "settings_frequencyHelper": "300,0 - 2500,0",
"settings_frequencyInvalid": "Frecuencia inválida (300-2500 MHz)", "settings_frequencyInvalid": "Frecuencia inválida (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Potencia (dBm)", "settings_txPower": "TX Potencia (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Potencia de TX inválida (0-22 dBm)", "settings_txPowerInvalid": "Potencia de TX inválida (0-22 dBm)",
"settings_longRange": "Largo Alcance",
"settings_fastSpeed": "Velocidad Rápida",
"settings_error": "Error: {message}", "settings_error": "Error: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1569,34 +1564,40 @@
"contacts_zeroHopContactAdvertSent": "Envió contacto por anuncio.", "contacts_zeroHopContactAdvertSent": "Envió contacto por anuncio.",
"contacts_contactAdvertCopied": "Anuncio copiado al Portapapeles.", "contacts_contactAdvertCopied": "Anuncio copiado al Portapapeles.",
"contacts_contactAdvertCopyFailed": "Copiar anuncio al Portapapeles ha fallado.", "contacts_contactAdvertCopyFailed": "Copiar anuncio al Portapapeles ha fallado.",
"notification_activityTitle": "Actividad de MeshCore", "notification_activityTitle": "Actividad de MeshCore",
"notification_messagesCount": "{count} {count, plural, =1{mensaje} other{mensajes}}", "notification_messagesCount": "{count} {count, plural, =1{mensaje} other{mensajes}}",
"@notification_messagesCount": { "@notification_messagesCount": {
"placeholders": { "placeholders": {
"count": {"type": "int"} "count": {
"type": "int"
}
} }
}, },
"notification_channelMessagesCount": "{count} {count, plural, =1{mensaje de canal} other{mensajes de canal}}", "notification_channelMessagesCount": "{count} {count, plural, =1{mensaje de canal} other{mensajes de canal}}",
"@notification_channelMessagesCount": { "@notification_channelMessagesCount": {
"placeholders": { "placeholders": {
"count": {"type": "int"} "count": {
"type": "int"
}
} }
}, },
"notification_newNodesCount": "{count} {count, plural, =1{nuevo nodo} other{nuevos nodos}}", "notification_newNodesCount": "{count} {count, plural, =1{nuevo nodo} other{nuevos nodos}}",
"@notification_newNodesCount": { "@notification_newNodesCount": {
"placeholders": { "placeholders": {
"count": {"type": "int"} "count": {
"type": "int"
}
} }
}, },
"notification_newTypeDiscovered": "Nuevo {contactType} descubierto", "notification_newTypeDiscovered": "Nuevo {contactType} descubierto",
"@notification_newTypeDiscovered": { "@notification_newTypeDiscovered": {
"placeholders": { "placeholders": {
"contactType": {"type": "String"} "contactType": {
"type": "String"
}
} }
}, },
"notification_receivedNewMessage": "Nuevo mensaje recibido", "notification_receivedNewMessage": "Nuevo mensaje recibido",
"contacts_contactAdvertCopyFailed": "Copiar anuncio al Portapapeles ha fallado.",
"settings_gpxExportContactsSubtitle": "Exporta compañeros con una ubicación a archivo GPX.", "settings_gpxExportContactsSubtitle": "Exporta compañeros con una ubicación a archivo GPX.",
"settings_gpxExportRepeaters": "Exportar repetidores / servidor de sala a GPX", "settings_gpxExportRepeaters": "Exportar repetidores / servidor de sala a GPX",
"settings_gpxExportSuccess": "Archivo GPX exportado con éxito.", "settings_gpxExportSuccess": "Archivo GPX exportado con éxito.",
@@ -1612,6 +1613,16 @@
"settings_gpxExportAllContacts": "Todas las ubicaciones de contactos", "settings_gpxExportAllContacts": "Todas las ubicaciones de contactos",
"settings_gpxExportShareText": "Datos del mapa exportados desde meshcore-open", "settings_gpxExportShareText": "Datos del mapa exportados desde meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open exportación de datos de mapa GPX", "settings_gpxExportShareSubject": "meshcore-open exportación de datos de mapa GPX",
"pathTrace_someHopsNoLocation": "Uno o más de los lúpulos carecen de una ubicación" "pathTrace_someHopsNoLocation": "Uno o más de los lúpulos carecen de una ubicación",
"pathTrace_clearTooltip": "Borrar ruta",
"map_runTrace": "Ejecutar Rastreo de Ruta",
"map_tapToAdd": "Pulse en los nodos para agregarlos al camino.",
"map_removeLast": "Eliminar último",
"map_pathTraceCancelled": "Rastreo de ruta cancelado.",
"scanner_bluetoothOffMessage": "Por favor, active el Bluetooth para escanear dispositivos.",
"scanner_bluetoothOff": "Bluetooth está desactivado.",
"scanner_enableBluetooth": "Habilitar Bluetooth",
"settings_clientRepeatFreqWarning": "Para la comunicación fuera de la red, se requiere una frecuencia de 433, 869 o 918 MHz.",
"settings_clientRepeat": "Repetir sin conexión",
"settings_clientRepeatSubtitle": "Permita que este dispositivo repita los paquetes de red para otros usuarios."
} }
+12 -6
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Nombre de contacts", "settings_infoContactsCount": "Nombre de contacts",
"settings_infoChannelCount": "Nombre de canaux", "settings_infoChannelCount": "Nombre de canaux",
"settings_presets": "Préréglages", "settings_presets": "Préréglages",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Fréquence (MHz)", "settings_frequency": "Fréquence (MHz)",
"settings_frequencyHelper": "300,0 - 2 500,0", "settings_frequencyHelper": "300,0 - 2 500,0",
"settings_frequencyInvalid": "Fréquence invalide (300-2500 MHz)", "settings_frequencyInvalid": "Fréquence invalide (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Puissance (dBm)", "settings_txPower": "TX Puissance (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Puissance TX invalide (0-22 dBm)", "settings_txPowerInvalid": "Puissance TX invalide (0-22 dBm)",
"settings_longRange": "Portée Longue",
"settings_fastSpeed": "Vitesse Rapide",
"settings_error": "Erreur : {message}", "settings_error": "Erreur : {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1590,5 +1585,16 @@
"settings_gpxExportAllContacts": "Tous les emplacements des contacts", "settings_gpxExportAllContacts": "Tous les emplacements des contacts",
"settings_gpxExportShareText": "Données de carte exportées à partir de meshcore-open", "settings_gpxExportShareText": "Données de carte exportées à partir de meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open exporter les données de carte GPX", "settings_gpxExportShareSubject": "meshcore-open exporter les données de carte GPX",
"pathTrace_someHopsNoLocation": "Un ou plusieurs des sauts manquent d'une localisation !" "pathTrace_someHopsNoLocation": "Un ou plusieurs des sauts manquent d'une localisation !",
"map_tapToAdd": "Appuyez sur les nœuds pour les ajouter au chemin.",
"pathTrace_clearTooltip": "Effacer le chemin",
"map_pathTraceCancelled": "Traçage de chemin annulé",
"map_removeLast": "Supprimer le dernier",
"map_runTrace": "Exécuter la traçage de chemin",
"scanner_bluetoothOffMessage": "Veuillez activer le Bluetooth pour rechercher des appareils.",
"scanner_bluetoothOff": "Le Bluetooth est désactivé.",
"scanner_enableBluetooth": "Activer le Bluetooth",
"settings_clientRepeatFreqWarning": "Pour les transmissions hors réseau, il est nécessaire d'utiliser les fréquences de 433, 869 ou 918 MHz.",
"settings_clientRepeatSubtitle": "Permettez à cet appareil de répéter les paquets de données pour les autres.",
"settings_clientRepeat": "Répétition hors réseau"
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Numero contatti", "settings_infoContactsCount": "Numero contatti",
"settings_infoChannelCount": "Numero Canale", "settings_infoChannelCount": "Numero Canale",
"settings_presets": "Preset", "settings_presets": "Preset",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frequenza (MHz)", "settings_frequency": "Frequenza (MHz)",
"settings_frequencyHelper": "300,0 - 2500,0", "settings_frequencyHelper": "300,0 - 2500,0",
"settings_frequencyInvalid": "Frequenza non valida (300-2500 MHz)", "settings_frequencyInvalid": "Frequenza non valida (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Potenza (dBm)", "settings_txPower": "TX Potenza (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Potere TX non valido (0-22 dBm)", "settings_txPowerInvalid": "Potere TX non valido (0-22 dBm)",
"settings_longRange": "Lungo Raggio",
"settings_fastSpeed": "Velocità Rapida",
"settings_error": "Errore: {message}", "settings_error": "Errore: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{nuovo nodo} other{nuovi nodi}}", "notification_newNodesCount": "{count} {count, plural, =1{nuovo nodo} other{nuovi nodi}}",
"notification_newTypeDiscovered": "Nuovo {contactType} scoperto", "notification_newTypeDiscovered": "Nuovo {contactType} scoperto",
"notification_receivedNewMessage": "Nuovo messaggio ricevuto", "notification_receivedNewMessage": "Nuovo messaggio ricevuto",
"contacts_contactAdvertCopied": "Annuncio copiato negli Appunti.",
"settings_gpxExportRepeaters": "Esporta ripetitori / server di stanza in GPX", "settings_gpxExportRepeaters": "Esporta ripetitori / server di stanza in GPX",
"settings_gpxExportContacts": "Esporta compagni in GPX", "settings_gpxExportContacts": "Esporta compagni in GPX",
"settings_gpxExportSuccess": "Esportazione del file GPX completata con successo.", "settings_gpxExportSuccess": "Esportazione del file GPX completata con successo.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportAllContacts": "Tutte le posizioni dei contatti", "settings_gpxExportAllContacts": "Tutte le posizioni dei contatti",
"settings_gpxExportShareText": "Dati mappa esportati da meshcore-open", "settings_gpxExportShareText": "Dati mappa esportati da meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open esportazione dati mappa GPX", "settings_gpxExportShareSubject": "meshcore-open esportazione dati mappa GPX",
"pathTrace_someHopsNoLocation": "Uno o più dei luppoli mancano di una posizione!" "pathTrace_someHopsNoLocation": "Uno o più dei luppoli mancano di una posizione!",
"map_removeLast": "Rimuovi ultimo",
"map_pathTraceCancelled": "Tracciamento del percorso annullato.",
"pathTrace_clearTooltip": "Pulisci percorso",
"map_runTrace": "Esegui Path Trace",
"map_tapToAdd": "Tocca i nodi per aggiungerli al percorso.",
"scanner_bluetoothOff": "Il Bluetooth è disattivato.",
"scanner_bluetoothOffMessage": "Si prega di attivare il Bluetooth per effettuare la scansione dei dispositivi.",
"scanner_enableBluetooth": "Abilita il Bluetooth",
"settings_clientRepeat": "Ripetizione \"fuori dalla rete\"",
"settings_clientRepeatFreqWarning": "Per la comunicazione fuori rete, è necessario utilizzare frequenze di 433, 869 o 918 MHz.",
"settings_clientRepeatSubtitle": "Permetti a questo dispositivo di ripetere i pacchetti di rete per gli altri."
} }
+60 -24
View File
@@ -376,6 +376,24 @@ abstract class AppLocalizations {
/// **'Scan'** /// **'Scan'**
String get scanner_scan; String get scanner_scan;
/// No description provided for @scanner_bluetoothOff.
///
/// In en, this message translates to:
/// **'Bluetooth is off'**
String get scanner_bluetoothOff;
/// No description provided for @scanner_bluetoothOffMessage.
///
/// In en, this message translates to:
/// **'Please turn on Bluetooth to scan for devices'**
String get scanner_bluetoothOffMessage;
/// No description provided for @scanner_enableBluetooth.
///
/// In en, this message translates to:
/// **'Enable Bluetooth'**
String get scanner_enableBluetooth;
/// No description provided for @device_quickSwitch. /// No description provided for @device_quickSwitch.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@@ -730,24 +748,6 @@ abstract class AppLocalizations {
/// **'Presets'** /// **'Presets'**
String get settings_presets; String get settings_presets;
/// No description provided for @settings_preset915Mhz.
///
/// In en, this message translates to:
/// **'915 MHz'**
String get settings_preset915Mhz;
/// No description provided for @settings_preset868Mhz.
///
/// In en, this message translates to:
/// **'868 MHz'**
String get settings_preset868Mhz;
/// No description provided for @settings_preset433Mhz.
///
/// In en, this message translates to:
/// **'433 MHz'**
String get settings_preset433Mhz;
/// No description provided for @settings_frequency. /// No description provided for @settings_frequency.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@@ -802,17 +802,23 @@ abstract class AppLocalizations {
/// **'Invalid TX power (0-22 dBm)'** /// **'Invalid TX power (0-22 dBm)'**
String get settings_txPowerInvalid; String get settings_txPowerInvalid;
/// No description provided for @settings_longRange. /// No description provided for @settings_clientRepeat.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Long Range'** /// **'Off-Grid Repeat'**
String get settings_longRange; String get settings_clientRepeat;
/// No description provided for @settings_fastSpeed. /// No description provided for @settings_clientRepeatSubtitle.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Fast Speed'** /// **'Allow this device to repeat mesh packets for others'**
String get settings_fastSpeed; String get settings_clientRepeatSubtitle;
/// No description provided for @settings_clientRepeatFreqWarning.
///
/// In en, this message translates to:
/// **'Off-grid repeat requires 433, 869, or 918 MHz frequency'**
String get settings_clientRepeatFreqWarning;
/// No description provided for @settings_error. /// No description provided for @settings_error.
/// ///
@@ -2518,6 +2524,30 @@ abstract class AppLocalizations {
/// **'Manage Repeater'** /// **'Manage Repeater'**
String get map_manageRepeater; String get map_manageRepeater;
/// No description provided for @map_tapToAdd.
///
/// In en, this message translates to:
/// **'Tap on nodes to add them to the path.'**
String get map_tapToAdd;
/// No description provided for @map_runTrace.
///
/// In en, this message translates to:
/// **'Run Path Trace'**
String get map_runTrace;
/// No description provided for @map_removeLast.
///
/// In en, this message translates to:
/// **'Remove Last'**
String get map_removeLast;
/// No description provided for @map_pathTraceCancelled.
///
/// In en, this message translates to:
/// **'Path trace cancelled.'**
String get map_pathTraceCancelled;
/// No description provided for @mapCache_title. /// No description provided for @mapCache_title.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@@ -4730,6 +4760,12 @@ abstract class AppLocalizations {
/// **'One or more of the hops is missing a location!'** /// **'One or more of the hops is missing a location!'**
String get pathTrace_someHopsNoLocation; String get pathTrace_someHopsNoLocation;
/// No description provided for @pathTrace_clearTooltip.
///
/// In en, this message translates to:
/// **'Clear path.'**
String get pathTrace_clearTooltip;
/// No description provided for @contacts_pathTrace. /// No description provided for @contacts_pathTrace.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
+33 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsBg extends AppLocalizations {
@override @override
String get scanner_scan => 'Сканирай'; String get scanner_scan => 'Сканирай';
@override
String get scanner_bluetoothOff => 'Bluetooth е изключен.';
@override
String get scanner_bluetoothOffMessage =>
'Моля, активирайте Bluetooth, за да сканирате за устройства.';
@override
String get scanner_enableBluetooth => 'Активирайте Bluetooth';
@override @override
String get device_quickSwitch => 'Бързо превключване'; String get device_quickSwitch => 'Бързо превключване';
@@ -340,15 +350,6 @@ class AppLocalizationsBg extends AppLocalizations {
@override @override
String get settings_presets => 'Предварителни настройки'; String get settings_presets => 'Предварителни настройки';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Честота (MHz)'; String get settings_frequency => 'Честота (MHz)';
@@ -377,10 +378,15 @@ class AppLocalizationsBg extends AppLocalizations {
String get settings_txPowerInvalid => 'Невалидна мощност на TX (0-22 dBm)'; String get settings_txPowerInvalid => 'Невалидна мощност на TX (0-22 dBm)';
@override @override
String get settings_longRange => 'Дълъг обхват'; String get settings_clientRepeat => 'Без електричество – повторение';
@override @override
String get settings_fastSpeed => 'Бърза скорост'; String get settings_clientRepeatSubtitle =>
'Позволете на това устройство да предава пакети към мрежата за други устройства.';
@override
String get settings_clientRepeatFreqWarning =>
'За повторение извън мрежата са необходими честоти от 433, 869 или 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1363,6 +1369,19 @@ class AppLocalizationsBg extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Управление на Повтарящ се Елемент'; String get map_manageRepeater => 'Управление на Повтарящ се Елемент';
@override
String get map_tapToAdd =>
'Натиснете върху възлите, за да ги добавите към пътя.';
@override
String get map_runTrace => 'Изпълни Път на Следване';
@override
String get map_removeLast => 'Премахни Последно';
@override
String get map_pathTraceCancelled => 'Отменен е следването на пътя.';
@override @override
String get mapCache_title => 'Кеш на офлайн карти'; String get mapCache_title => 'Кеш на офлайн карти';
@@ -2699,6 +2718,9 @@ class AppLocalizationsBg extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Един или повече от хмелите липсва местоположение!'; 'Един или повече от хмелите липсва местоположение!';
@override
String get pathTrace_clearTooltip => 'Изчисти пътя';
@override @override
String get contacts_pathTrace => 'Пътен проследяване'; String get contacts_pathTrace => 'Пътен проследяване';
+33 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get scanner_scan => 'Scannen'; String get scanner_scan => 'Scannen';
@override
String get scanner_bluetoothOff => 'Bluetooth ist deaktiviert.';
@override
String get scanner_bluetoothOffMessage =>
'Bitte aktivieren Sie Bluetooth, um nach Geräten zu suchen.';
@override
String get scanner_enableBluetooth => 'Bluetooth aktivieren';
@override @override
String get device_quickSwitch => 'Schnelles Umschalten'; String get device_quickSwitch => 'Schnelles Umschalten';
@@ -334,15 +344,6 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get settings_presets => 'Voreinstellungen'; String get settings_presets => 'Voreinstellungen';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frequenz (MHz)'; String get settings_frequency => 'Frequenz (MHz)';
@@ -371,10 +372,15 @@ class AppLocalizationsDe extends AppLocalizations {
String get settings_txPowerInvalid => 'Ungültige TX-Leistung (0-22 dBm)'; String get settings_txPowerInvalid => 'Ungültige TX-Leistung (0-22 dBm)';
@override @override
String get settings_longRange => 'Grosse Reichweite'; String get settings_clientRepeat => 'Wiederholung, ohne Stromanschluss';
@override @override
String get settings_fastSpeed => 'Schnelle Geschwindigkeit'; String get settings_clientRepeatSubtitle =>
'Ermöglichen Sie diesem Gerät, Mesh-Pakete für andere zu wiederholen.';
@override
String get settings_clientRepeatFreqWarning =>
'Die Kommunikation ohne Stromversorgung erfordert Frequenzen von 433, 869 oder 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1362,6 +1368,19 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Repeater verwalten'; String get map_manageRepeater => 'Repeater verwalten';
@override
String get map_tapToAdd =>
'Tippen Sie auf Knoten, um sie zum Pfad hinzuzufügen.';
@override
String get map_runTrace => 'Pfadverlauf ausführen';
@override
String get map_removeLast => 'Letztes Entfernen';
@override
String get map_pathTraceCancelled => 'Pfadverfolgung abgebrochen.';
@override @override
String get mapCache_title => 'Offline-Karten-Cache'; String get mapCache_title => 'Offline-Karten-Cache';
@@ -2704,6 +2723,9 @@ class AppLocalizationsDe extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Bei einer oder mehreren Knoten fehlt der Standort!'; 'Bei einer oder mehreren Knoten fehlt der Standort!';
@override
String get pathTrace_clearTooltip => 'Pfad löschen';
@override @override
String get contacts_pathTrace => 'Pfadverfolgung'; String get contacts_pathTrace => 'Pfadverfolgung';
+32 -11
View File
@@ -142,6 +142,16 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get scanner_scan => 'Scan'; String get scanner_scan => 'Scan';
@override
String get scanner_bluetoothOff => 'Bluetooth is off';
@override
String get scanner_bluetoothOffMessage =>
'Please turn on Bluetooth to scan for devices';
@override
String get scanner_enableBluetooth => 'Enable Bluetooth';
@override @override
String get device_quickSwitch => 'Quick switch'; String get device_quickSwitch => 'Quick switch';
@@ -332,15 +342,6 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get settings_presets => 'Presets'; String get settings_presets => 'Presets';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frequency (MHz)'; String get settings_frequency => 'Frequency (MHz)';
@@ -369,10 +370,15 @@ class AppLocalizationsEn extends AppLocalizations {
String get settings_txPowerInvalid => 'Invalid TX power (0-22 dBm)'; String get settings_txPowerInvalid => 'Invalid TX power (0-22 dBm)';
@override @override
String get settings_longRange => 'Long Range'; String get settings_clientRepeat => 'Off-Grid Repeat';
@override @override
String get settings_fastSpeed => 'Fast Speed'; String get settings_clientRepeatSubtitle =>
'Allow this device to repeat mesh packets for others';
@override
String get settings_clientRepeatFreqWarning =>
'Off-grid repeat requires 433, 869, or 918 MHz frequency';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1342,6 +1348,18 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Manage Repeater'; String get map_manageRepeater => 'Manage Repeater';
@override
String get map_tapToAdd => 'Tap on nodes to add them to the path.';
@override
String get map_runTrace => 'Run Path Trace';
@override
String get map_removeLast => 'Remove Last';
@override
String get map_pathTraceCancelled => 'Path trace cancelled.';
@override @override
String get mapCache_title => 'Offline Map Cache'; String get mapCache_title => 'Offline Map Cache';
@@ -2659,6 +2677,9 @@ class AppLocalizationsEn extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'One or more of the hops is missing a location!'; 'One or more of the hops is missing a location!';
@override
String get pathTrace_clearTooltip => 'Clear path.';
@override @override
String get contacts_pathTrace => 'Path Trace'; String get contacts_pathTrace => 'Path Trace';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsEs extends AppLocalizations {
@override @override
String get scanner_scan => 'Escanea'; String get scanner_scan => 'Escanea';
@override
String get scanner_bluetoothOff => 'Bluetooth está desactivado.';
@override
String get scanner_bluetoothOffMessage =>
'Por favor, active el Bluetooth para escanear dispositivos.';
@override
String get scanner_enableBluetooth => 'Habilitar Bluetooth';
@override @override
String get device_quickSwitch => 'Cambiar rápidamente'; String get device_quickSwitch => 'Cambiar rápidamente';
@@ -337,15 +347,6 @@ class AppLocalizationsEs extends AppLocalizations {
@override @override
String get settings_presets => 'Preajustes'; String get settings_presets => 'Preajustes';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frecuencia (MHz)'; String get settings_frequency => 'Frecuencia (MHz)';
@@ -374,10 +375,15 @@ class AppLocalizationsEs extends AppLocalizations {
String get settings_txPowerInvalid => 'Potencia de TX inválida (0-22 dBm)'; String get settings_txPowerInvalid => 'Potencia de TX inválida (0-22 dBm)';
@override @override
String get settings_longRange => 'Largo Alcance'; String get settings_clientRepeat => 'Repetir sin conexión';
@override @override
String get settings_fastSpeed => 'Velocidad Rápida'; String get settings_clientRepeatSubtitle =>
'Permita que este dispositivo repita los paquetes de red para otros usuarios.';
@override
String get settings_clientRepeatFreqWarning =>
'Para la comunicación fuera de la red, se requiere una frecuencia de 433, 869 o 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1360,6 +1366,18 @@ class AppLocalizationsEs extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Gestionar Repetidor'; String get map_manageRepeater => 'Gestionar Repetidor';
@override
String get map_tapToAdd => 'Pulse en los nodos para agregarlos al camino.';
@override
String get map_runTrace => 'Ejecutar Rastreo de Ruta';
@override
String get map_removeLast => 'Eliminar último';
@override
String get map_pathTraceCancelled => 'Rastreo de ruta cancelado.';
@override @override
String get mapCache_title => 'Caché de Mapa Offline'; String get mapCache_title => 'Caché de Mapa Offline';
@@ -2698,6 +2716,9 @@ class AppLocalizationsEs extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Uno o más de los lúpulos carecen de una ubicación'; 'Uno o más de los lúpulos carecen de una ubicación';
@override
String get pathTrace_clearTooltip => 'Borrar ruta';
@override @override
String get contacts_pathTrace => 'Rastreo de caminos'; String get contacts_pathTrace => 'Rastreo de caminos';
+33 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsFr extends AppLocalizations {
@override @override
String get scanner_scan => 'Scanner'; String get scanner_scan => 'Scanner';
@override
String get scanner_bluetoothOff => 'Le Bluetooth est désactivé.';
@override
String get scanner_bluetoothOffMessage =>
'Veuillez activer le Bluetooth pour rechercher des appareils.';
@override
String get scanner_enableBluetooth => 'Activer le Bluetooth';
@override @override
String get device_quickSwitch => 'Basculement rapide'; String get device_quickSwitch => 'Basculement rapide';
@@ -338,15 +348,6 @@ class AppLocalizationsFr extends AppLocalizations {
@override @override
String get settings_presets => 'Préréglages'; String get settings_presets => 'Préréglages';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Fréquence (MHz)'; String get settings_frequency => 'Fréquence (MHz)';
@@ -375,10 +376,15 @@ class AppLocalizationsFr extends AppLocalizations {
String get settings_txPowerInvalid => 'Puissance TX invalide (0-22 dBm)'; String get settings_txPowerInvalid => 'Puissance TX invalide (0-22 dBm)';
@override @override
String get settings_longRange => 'Portée Longue'; String get settings_clientRepeat => 'Répétition hors réseau';
@override @override
String get settings_fastSpeed => 'Vitesse Rapide'; String get settings_clientRepeatSubtitle =>
'Permettez à cet appareil de répéter les paquets de données pour les autres.';
@override
String get settings_clientRepeatFreqWarning =>
'Pour les transmissions hors réseau, il est nécessaire d\'utiliser les fréquences de 433, 869 ou 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1367,6 +1373,19 @@ class AppLocalizationsFr extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Gérer le répéteur'; String get map_manageRepeater => 'Gérer le répéteur';
@override
String get map_tapToAdd =>
'Appuyez sur les nœuds pour les ajouter au chemin.';
@override
String get map_runTrace => 'Exécuter la traçage de chemin';
@override
String get map_removeLast => 'Supprimer le dernier';
@override
String get map_pathTraceCancelled => 'Traçage de chemin annulé';
@override @override
String get mapCache_title => 'Cache de Carte Hors Ligne'; String get mapCache_title => 'Cache de Carte Hors Ligne';
@@ -2714,6 +2733,9 @@ class AppLocalizationsFr extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Un ou plusieurs des sauts manquent d\'une localisation !'; 'Un ou plusieurs des sauts manquent d\'une localisation !';
@override
String get pathTrace_clearTooltip => 'Effacer le chemin';
@override @override
String get contacts_pathTrace => 'Traçage de chemin'; String get contacts_pathTrace => 'Traçage de chemin';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsIt extends AppLocalizations {
@override @override
String get scanner_scan => 'Scansiona'; String get scanner_scan => 'Scansiona';
@override
String get scanner_bluetoothOff => 'Il Bluetooth è disattivato.';
@override
String get scanner_bluetoothOffMessage =>
'Si prega di attivare il Bluetooth per effettuare la scansione dei dispositivi.';
@override
String get scanner_enableBluetooth => 'Abilita il Bluetooth';
@override @override
String get device_quickSwitch => 'Passa velocemente'; String get device_quickSwitch => 'Passa velocemente';
@@ -336,15 +346,6 @@ class AppLocalizationsIt extends AppLocalizations {
@override @override
String get settings_presets => 'Preset'; String get settings_presets => 'Preset';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frequenza (MHz)'; String get settings_frequency => 'Frequenza (MHz)';
@@ -373,10 +374,15 @@ class AppLocalizationsIt extends AppLocalizations {
String get settings_txPowerInvalid => 'Potere TX non valido (0-22 dBm)'; String get settings_txPowerInvalid => 'Potere TX non valido (0-22 dBm)';
@override @override
String get settings_longRange => 'Lungo Raggio'; String get settings_clientRepeat => 'Ripetizione \"fuori dalla rete\"';
@override @override
String get settings_fastSpeed => 'Velocità Rapida'; String get settings_clientRepeatSubtitle =>
'Permetti a questo dispositivo di ripetere i pacchetti di rete per gli altri.';
@override
String get settings_clientRepeatFreqWarning =>
'Per la comunicazione fuori rete, è necessario utilizzare frequenze di 433, 869 o 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1359,6 +1365,18 @@ class AppLocalizationsIt extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Gestisci Ripetitore'; String get map_manageRepeater => 'Gestisci Ripetitore';
@override
String get map_tapToAdd => 'Tocca i nodi per aggiungerli al percorso.';
@override
String get map_runTrace => 'Esegui Path Trace';
@override
String get map_removeLast => 'Rimuovi ultimo';
@override
String get map_pathTraceCancelled => 'Tracciamento del percorso annullato.';
@override @override
String get mapCache_title => 'Cache Mappa Offline'; String get mapCache_title => 'Cache Mappa Offline';
@@ -2699,6 +2717,9 @@ class AppLocalizationsIt extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Uno o più dei luppoli mancano di una posizione!'; 'Uno o più dei luppoli mancano di una posizione!';
@override
String get pathTrace_clearTooltip => 'Pulisci percorso';
@override @override
String get contacts_pathTrace => 'Traccia Percorso'; String get contacts_pathTrace => 'Traccia Percorso';
+33 -11
View File
@@ -142,6 +142,16 @@ class AppLocalizationsNl extends AppLocalizations {
@override @override
String get scanner_scan => 'Scan'; String get scanner_scan => 'Scan';
@override
String get scanner_bluetoothOff => 'Bluetooth is uitgeschakeld';
@override
String get scanner_bluetoothOffMessage =>
'Zorg ervoor dat Bluetooth is ingeschakeld om naar apparaten te zoeken.';
@override
String get scanner_enableBluetooth => 'Activeer Bluetooth';
@override @override
String get device_quickSwitch => 'Snelle overschakeling'; String get device_quickSwitch => 'Snelle overschakeling';
@@ -334,15 +344,6 @@ class AppLocalizationsNl extends AppLocalizations {
@override @override
String get settings_presets => 'Presets'; String get settings_presets => 'Presets';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frequentie (MHz)'; String get settings_frequency => 'Frequentie (MHz)';
@@ -371,10 +372,15 @@ class AppLocalizationsNl extends AppLocalizations {
String get settings_txPowerInvalid => 'Ongeldige TX-vermogen (0-22 dBm)'; String get settings_txPowerInvalid => 'Ongeldige TX-vermogen (0-22 dBm)';
@override @override
String get settings_longRange => 'Lange Afstand'; String get settings_clientRepeat => 'Herhalen: Afgekoppeld';
@override @override
String get settings_fastSpeed => 'Hoge Snelheid'; String get settings_clientRepeatSubtitle =>
'Laat dit apparaat de mesh-pakketten opnieuw verzenden voor andere apparaten.';
@override
String get settings_clientRepeatFreqWarning =>
'Om een signaal buiten het netwerk te versturen, zijn frequenties van 433, 869 of 918 MHz vereist.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1355,6 +1361,19 @@ class AppLocalizationsNl extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Beheer Repeater'; String get map_manageRepeater => 'Beheer Repeater';
@override
String get map_tapToAdd =>
'Tik op knooppunten om ze toe te voegen aan het pad';
@override
String get map_runTrace => 'Padeshulp traceren';
@override
String get map_removeLast => 'Verwijder Laatste';
@override
String get map_pathTraceCancelled => 'Pad traceren geannuleerd';
@override @override
String get mapCache_title => 'Offline Kaarten Cache'; String get mapCache_title => 'Offline Kaarten Cache';
@@ -2689,6 +2708,9 @@ class AppLocalizationsNl extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Een of meer van de hops ontbreken een locatie!'; 'Een of meer van de hops ontbreken een locatie!';
@override
String get pathTrace_clearTooltip => 'Weg wissen';
@override @override
String get contacts_pathTrace => 'Pad Traceren'; String get contacts_pathTrace => 'Pad Traceren';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsPl extends AppLocalizations {
@override @override
String get scanner_scan => 'Przeskanuj'; String get scanner_scan => 'Przeskanuj';
@override
String get scanner_bluetoothOff => 'Bluetooth jest wyłączony';
@override
String get scanner_bluetoothOffMessage =>
'Prosimy włączyć Bluetooth, aby przeskanować urządzenia.';
@override
String get scanner_enableBluetooth => 'Włącz Bluetooth';
@override @override
String get device_quickSwitch => 'Szybka zmiana'; String get device_quickSwitch => 'Szybka zmiana';
@@ -337,15 +347,6 @@ class AppLocalizationsPl extends AppLocalizations {
@override @override
String get settings_presets => 'Preset'; String get settings_presets => 'Preset';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Częstotliwość (MHz)'; String get settings_frequency => 'Częstotliwość (MHz)';
@@ -375,10 +376,15 @@ class AppLocalizationsPl extends AppLocalizations {
String get settings_txPowerInvalid => 'Nieprawidłowa moc TX (0-22 dBm)'; String get settings_txPowerInvalid => 'Nieprawidłowa moc TX (0-22 dBm)';
@override @override
String get settings_longRange => 'Długi zasięg'; String get settings_clientRepeat => 'Powtórzenie: Niezależne od sieci';
@override @override
String get settings_fastSpeed => 'Szybka prędkość'; String get settings_clientRepeatSubtitle =>
'Pozwól temu urządzeniu powtarzać pakiety danych dla innych urządzeń.';
@override
String get settings_clientRepeatFreqWarning =>
'Powtórka poza siecią wymaga częstotliwości 433, 869 lub 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1361,6 +1367,18 @@ class AppLocalizationsPl extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Zarządzaj Powtórzami'; String get map_manageRepeater => 'Zarządzaj Powtórzami';
@override
String get map_tapToAdd => 'Kliknij na węzły, aby dodać je do ścieżki.';
@override
String get map_runTrace => 'Uruchom ślad ścieżki';
@override
String get map_removeLast => 'Usuń ostatni';
@override
String get map_pathTraceCancelled => 'Śledzenie ścieżki anulowano.';
@override @override
String get mapCache_title => 'Bufor Map Offline'; String get mapCache_title => 'Bufor Map Offline';
@@ -2697,6 +2715,9 @@ class AppLocalizationsPl extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Jeden lub więcej z chmieli nie ma określonej lokalizacji!'; 'Jeden lub więcej z chmieli nie ma określonej lokalizacji!';
@override
String get pathTrace_clearTooltip => 'Wyczyść ścieżkę';
@override @override
String get contacts_pathTrace => 'Śledzenie Ścieżek'; String get contacts_pathTrace => 'Śledzenie Ścieżek';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsPt extends AppLocalizations {
@override @override
String get scanner_scan => 'Digitalizar'; String get scanner_scan => 'Digitalizar';
@override
String get scanner_bluetoothOff => 'Bluetooth está desativado';
@override
String get scanner_bluetoothOffMessage =>
'Por favor, ative o Bluetooth para escanear por dispositivos.';
@override
String get scanner_enableBluetooth => 'Ative o Bluetooth';
@override @override
String get device_quickSwitch => 'Mudar rapidamente'; String get device_quickSwitch => 'Mudar rapidamente';
@@ -338,15 +348,6 @@ class AppLocalizationsPt extends AppLocalizations {
@override @override
String get settings_presets => 'Presets'; String get settings_presets => 'Presets';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frequência (MHz)'; String get settings_frequency => 'Frequência (MHz)';
@@ -375,10 +376,15 @@ class AppLocalizationsPt extends AppLocalizations {
String get settings_txPowerInvalid => 'Potência de TX inválida (0-22 dBm)'; String get settings_txPowerInvalid => 'Potência de TX inválida (0-22 dBm)';
@override @override
String get settings_longRange => 'Alcance Longo'; String get settings_clientRepeat => 'Repetição sem rede';
@override @override
String get settings_fastSpeed => 'Velocidade Rápida'; String get settings_clientRepeatSubtitle =>
'Permita que este dispositivo repita pacotes de rede para outros dispositivos.';
@override
String get settings_clientRepeatFreqWarning =>
'A repetição fora da rede requer frequências de 433, 869 ou 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1361,6 +1367,18 @@ class AppLocalizationsPt extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Gerenciar Repetidor'; String get map_manageRepeater => 'Gerenciar Repetidor';
@override
String get map_tapToAdd => 'Toque nos nós para adicioná-los ao caminho.';
@override
String get map_runTrace => 'Executar Traçado de Caminho';
@override
String get map_removeLast => 'Remover Último';
@override
String get map_pathTraceCancelled => 'Rastreamento de caminho cancelado.';
@override @override
String get mapCache_title => 'Cache de Mapa Offline'; String get mapCache_title => 'Cache de Mapa Offline';
@@ -2700,6 +2718,9 @@ class AppLocalizationsPt extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Um ou mais dos lúpulos estão sem localização!'; 'Um ou mais dos lúpulos estão sem localização!';
@override
String get pathTrace_clearTooltip => 'Limpar caminho';
@override @override
String get contacts_pathTrace => 'Traçado de Caminho'; String get contacts_pathTrace => 'Traçado de Caminho';
+32 -11
View File
@@ -142,6 +142,16 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get scanner_scan => 'Сканирование'; String get scanner_scan => 'Сканирование';
@override
String get scanner_bluetoothOff => 'Bluetooth выключен';
@override
String get scanner_bluetoothOffMessage =>
'Пожалуйста, включите Bluetooth, чтобы найти устройства.';
@override
String get scanner_enableBluetooth => 'Включите Bluetooth';
@override @override
String get device_quickSwitch => 'Быстрое переключение'; String get device_quickSwitch => 'Быстрое переключение';
@@ -335,15 +345,6 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get settings_presets => 'Пресеты'; String get settings_presets => 'Пресеты';
@override
String get settings_preset915Mhz => '915 МГц';
@override
String get settings_preset868Mhz => '868 МГц';
@override
String get settings_preset433Mhz => '433 МГц';
@override @override
String get settings_frequency => 'Частота (МГц)'; String get settings_frequency => 'Частота (МГц)';
@@ -373,10 +374,15 @@ class AppLocalizationsRu extends AppLocalizations {
'Недопустимая мощность передачи (0–22 дБм)'; 'Недопустимая мощность передачи (0–22 дБм)';
@override @override
String get settings_longRange => 'Дальний радиус'; String get settings_clientRepeat => 'Повторение \"вне сети\"';
@override @override
String get settings_fastSpeed => 'Высокая скорость'; String get settings_clientRepeatSubtitle =>
'Позвольте этому устройству повторять пакеты данных для других устройств.';
@override
String get settings_clientRepeatFreqWarning =>
'Для работы в режиме \"без подключения к сети\" требуется частота 433, 869 или 918 МГц.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1362,6 +1368,18 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Управление репитером'; String get map_manageRepeater => 'Управление репитером';
@override
String get map_tapToAdd => 'Нажимайте на узлы, чтобы добавить их в путь.';
@override
String get map_runTrace => 'Запустить трассировку пути';
@override
String get map_removeLast => 'Удалить последний';
@override
String get map_pathTraceCancelled => 'Отмена трассировки пути';
@override @override
String get mapCache_title => 'Кэш офлайн-карты'; String get mapCache_title => 'Кэш офлайн-карты';
@@ -2702,6 +2720,9 @@ class AppLocalizationsRu extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Одному или нескольким хмелям не указано местоположение!'; 'Одному или нескольким хмелям не указано местоположение!';
@override
String get pathTrace_clearTooltip => 'Очистить путь';
@override @override
String get contacts_pathTrace => 'Трассировка пути'; String get contacts_pathTrace => 'Трассировка пути';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsSk extends AppLocalizations {
@override @override
String get scanner_scan => 'Skončiť'; String get scanner_scan => 'Skončiť';
@override
String get scanner_bluetoothOff => 'Bluetooth je vypnutý';
@override
String get scanner_bluetoothOffMessage =>
'Prosím, zapnite Bluetooth, aby ste mohli skenovať pre zariadenia.';
@override
String get scanner_enableBluetooth => 'Povolte Bluetooth';
@override @override
String get device_quickSwitch => 'Rýchle prepínač'; String get device_quickSwitch => 'Rýchle prepínač';
@@ -334,15 +344,6 @@ class AppLocalizationsSk extends AppLocalizations {
@override @override
String get settings_presets => 'Prednastavenia'; String get settings_presets => 'Prednastavenia';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frekvencia (MHz)'; String get settings_frequency => 'Frekvencia (MHz)';
@@ -371,10 +372,15 @@ class AppLocalizationsSk extends AppLocalizations {
String get settings_txPowerInvalid => 'Neplatná hodnota výkonu TX (0-22 dBm)'; String get settings_txPowerInvalid => 'Neplatná hodnota výkonu TX (0-22 dBm)';
@override @override
String get settings_longRange => 'Dlhý dosah'; String get settings_clientRepeat => 'Opätovné použitie bez elektrickej siete';
@override @override
String get settings_fastSpeed => 'Rýchla rýchlosť'; String get settings_clientRepeatSubtitle =>
'Umožnite, aby toto zariadenie opakovávalo siete pre ostatných.';
@override
String get settings_clientRepeatFreqWarning =>
'Použitie off-grid systému vyžaduje frekvencie 433, 869 alebo 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1356,6 +1362,18 @@ class AppLocalizationsSk extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Spravovať Opakovanie'; String get map_manageRepeater => 'Spravovať Opakovanie';
@override
String get map_tapToAdd => 'Kliknite na uzly, aby ste ich pridali k ceste.';
@override
String get map_runTrace => 'Spustiť trasovaním cesty';
@override
String get map_removeLast => 'Odstrániť posledný';
@override
String get map_pathTraceCancelled => 'Zrušenie stopáže cesty bolo zrušené.';
@override @override
String get mapCache_title => 'Offline Mapa Pamäť'; String get mapCache_title => 'Offline Mapa Pamäť';
@@ -2685,6 +2703,9 @@ class AppLocalizationsSk extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Jedna alebo viac chmeľov chýba lokalita!'; 'Jedna alebo viac chmeľov chýba lokalita!';
@override
String get pathTrace_clearTooltip => 'Zmazať cestu';
@override @override
String get contacts_pathTrace => 'Sledovanie lúčov'; String get contacts_pathTrace => 'Sledovanie lúčov';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsSl extends AppLocalizations {
@override @override
String get scanner_scan => 'Skeniraj'; String get scanner_scan => 'Skeniraj';
@override
String get scanner_bluetoothOff => 'Bluetooth je izklopljen';
@override
String get scanner_bluetoothOffMessage =>
'Prosimo, vklopite Bluetooth, da lahko poiščete naprave.';
@override
String get scanner_enableBluetooth => 'Omogočite Bluetooth';
@override @override
String get device_quickSwitch => 'Hitro preklop'; String get device_quickSwitch => 'Hitro preklop';
@@ -333,15 +343,6 @@ class AppLocalizationsSl extends AppLocalizations {
@override @override
String get settings_presets => 'Prednastavitve'; String get settings_presets => 'Prednastavitve';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frekvenca (MHz)'; String get settings_frequency => 'Frekvenca (MHz)';
@@ -370,10 +371,15 @@ class AppLocalizationsSl extends AppLocalizations {
String get settings_txPowerInvalid => 'Neveljavna TX moč (0-22 dBm)'; String get settings_txPowerInvalid => 'Neveljavna TX moč (0-22 dBm)';
@override @override
String get settings_longRange => 'DDolg doseg'; String get settings_clientRepeat => 'Neovadno ponavljanje';
@override @override
String get settings_fastSpeed => 'Visoka hitrost'; String get settings_clientRepeatSubtitle =>
'Omogočite temu naprave, da ponavlja paketne sporočila za druge.';
@override
String get settings_clientRepeatFreqWarning =>
'Za ponovni prenos na brezžični način so potrebne frekvence 433, 869 ali 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1352,6 +1358,18 @@ class AppLocalizationsSl extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Upravljajte Ponovitve'; String get map_manageRepeater => 'Upravljajte Ponovitve';
@override
String get map_tapToAdd => 'Pritisnite na vozlišča, da jih dodate poti.';
@override
String get map_runTrace => 'Zaženi sledenje poti';
@override
String get map_removeLast => 'Odstrani Zadnji';
@override
String get map_pathTraceCancelled => 'Spremljanje poti je prekinjeno.';
@override @override
String get mapCache_title => String get mapCache_title =>
'Omrezni predpomnilnik zemljeških zemljejevskih slik'; 'Omrezni predpomnilnik zemljeških zemljejevskih slik';
@@ -2688,6 +2706,9 @@ class AppLocalizationsSl extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Ena ali več hmelju manjka lokacija!'; 'Ena ali več hmelju manjka lokacija!';
@override
String get pathTrace_clearTooltip => 'Počisti pot';
@override @override
String get contacts_pathTrace => 'Sledenje poti'; String get contacts_pathTrace => 'Sledenje poti';
+32 -11
View File
@@ -142,6 +142,16 @@ class AppLocalizationsSv extends AppLocalizations {
@override @override
String get scanner_scan => 'Skanna'; String get scanner_scan => 'Skanna';
@override
String get scanner_bluetoothOff => 'Bluetooth är avstängt';
@override
String get scanner_bluetoothOffMessage =>
'Vänligen aktivera Bluetooth för att söka efter enheter.';
@override
String get scanner_enableBluetooth => 'Aktivera Bluetooth';
@override @override
String get device_quickSwitch => 'Snabb växling'; String get device_quickSwitch => 'Snabb växling';
@@ -331,15 +341,6 @@ class AppLocalizationsSv extends AppLocalizations {
@override @override
String get settings_presets => 'Fördefinierade inställningar'; String get settings_presets => 'Fördefinierade inställningar';
@override
String get settings_preset915Mhz => '915 MHz';
@override
String get settings_preset868Mhz => '868 MHz';
@override
String get settings_preset433Mhz => '433 MHz';
@override @override
String get settings_frequency => 'Frekvens (MHz)'; String get settings_frequency => 'Frekvens (MHz)';
@@ -368,10 +369,15 @@ class AppLocalizationsSv extends AppLocalizations {
String get settings_txPowerInvalid => 'Ogiltig TX-effekt (0-22 dBm)'; String get settings_txPowerInvalid => 'Ogiltig TX-effekt (0-22 dBm)';
@override @override
String get settings_longRange => 'Lång räckvidd'; String get settings_clientRepeat => 'Upprepa utan elnät';
@override @override
String get settings_fastSpeed => 'Snabb hastighet'; String get settings_clientRepeatSubtitle =>
'Låt enheten repetera nätpaket för andra användare.';
@override
String get settings_clientRepeatFreqWarning =>
'För att kunna kommunicera utanför elnätet krävs frekvenserna 433, 869 eller 918 MHz.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1348,6 +1354,18 @@ class AppLocalizationsSv extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Hantera Upprepare'; String get map_manageRepeater => 'Hantera Upprepare';
@override
String get map_tapToAdd => 'Tryck på noder för att lägga till dem i banan.';
@override
String get map_runTrace => 'Kör spårsökning';
@override
String get map_removeLast => 'Ta bort sista';
@override
String get map_pathTraceCancelled => 'Sökvägsspårning avbruten.';
@override @override
String get mapCache_title => 'Offline Kartcache'; String get mapCache_title => 'Offline Kartcache';
@@ -2673,6 +2691,9 @@ class AppLocalizationsSv extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'En eller flera av humlen saknar en plats!'; 'En eller flera av humlen saknar en plats!';
@override
String get pathTrace_clearTooltip => 'Rensa väg';
@override @override
String get contacts_pathTrace => 'Path Trace'; String get contacts_pathTrace => 'Path Trace';
+32 -11
View File
@@ -143,6 +143,16 @@ class AppLocalizationsUk extends AppLocalizations {
@override @override
String get scanner_scan => 'Сканувати'; String get scanner_scan => 'Сканувати';
@override
String get scanner_bluetoothOff => 'Bluetooth вимкнено';
@override
String get scanner_bluetoothOffMessage =>
'Будь ласка, увімкніть Bluetooth, щоб сканувати пристрої.';
@override
String get scanner_enableBluetooth => 'Увімкніть Bluetooth';
@override @override
String get device_quickSwitch => 'Швидке перемикання'; String get device_quickSwitch => 'Швидке перемикання';
@@ -336,15 +346,6 @@ class AppLocalizationsUk extends AppLocalizations {
@override @override
String get settings_presets => 'Попередні налаштування'; String get settings_presets => 'Попередні налаштування';
@override
String get settings_preset915Mhz => '915 МГц';
@override
String get settings_preset868Mhz => '868 МГц';
@override
String get settings_preset433Mhz => '433 МГц';
@override @override
String get settings_frequency => 'Частота (МГц)'; String get settings_frequency => 'Частота (МГц)';
@@ -373,10 +374,15 @@ class AppLocalizationsUk extends AppLocalizations {
String get settings_txPowerInvalid => 'Некоректна потужність TX (0-22 дБм)'; String get settings_txPowerInvalid => 'Некоректна потужність TX (0-22 дБм)';
@override @override
String get settings_longRange => 'Дальній діапазон'; String get settings_clientRepeat => 'Автономна система';
@override @override
String get settings_fastSpeed => 'Висока швидкість'; String get settings_clientRepeatSubtitle =>
'Дозвольте цьому пристрою повторювати пакети даних для інших пристроїв.';
@override
String get settings_clientRepeatFreqWarning =>
'Повтор без підключення до мережі вимагає частоти 433, 869 або 918 МГц.';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1361,6 +1367,18 @@ class AppLocalizationsUk extends AppLocalizations {
@override @override
String get map_manageRepeater => 'Керувати ретранслятором'; String get map_manageRepeater => 'Керувати ретранслятором';
@override
String get map_tapToAdd => 'Натисніть на вузли, щоб додати їх до шляху';
@override
String get map_runTrace => 'Виконати трасування шляху';
@override
String get map_removeLast => 'Видалити останній';
@override
String get map_pathTraceCancelled => 'Відмінується трасування шляху';
@override @override
String get mapCache_title => 'Офлайн-кеш карти'; String get mapCache_title => 'Офлайн-кеш карти';
@@ -2709,6 +2727,9 @@ class AppLocalizationsUk extends AppLocalizations {
String get pathTrace_someHopsNoLocation => String get pathTrace_someHopsNoLocation =>
'Одне або більше хмелів відсутнє місце розташування!'; 'Одне або більше хмелів відсутнє місце розташування!';
@override
String get pathTrace_clearTooltip => 'Очистити шлях';
@override @override
String get contacts_pathTrace => 'Трасування шляхів'; String get contacts_pathTrace => 'Трасування шляхів';
+30 -11
View File
@@ -142,6 +142,15 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get scanner_scan => '扫描'; String get scanner_scan => '扫描';
@override
String get scanner_bluetoothOff => '蓝牙已关闭';
@override
String get scanner_bluetoothOffMessage => '请打开蓝牙功能,以便搜索设备。';
@override
String get scanner_enableBluetooth => '启用蓝牙';
@override @override
String get device_quickSwitch => '快速切换'; String get device_quickSwitch => '快速切换';
@@ -322,15 +331,6 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get settings_presets => '预设'; String get settings_presets => '预设';
@override
String get settings_preset915Mhz => '915 兆赫';
@override
String get settings_preset868Mhz => '868 兆赫';
@override
String get settings_preset433Mhz => '433 兆赫';
@override @override
String get settings_frequency => '频率 (MHz)'; String get settings_frequency => '频率 (MHz)';
@@ -359,10 +359,14 @@ class AppLocalizationsZh extends AppLocalizations {
String get settings_txPowerInvalid => '无效的发射功率(0-22 dBm'; String get settings_txPowerInvalid => '无效的发射功率(0-22 dBm';
@override @override
String get settings_longRange => '远距'; String get settings_clientRepeat => '网重复';
@override @override
String get settings_fastSpeed => '高速'; String get settings_clientRepeatSubtitle => '允许此设备重复发送网状数据包给其他设备';
@override
String get settings_clientRepeatFreqWarning =>
'离网重复通信需要使用 433、869 或 918 兆赫兹的频率。';
@override @override
String settings_error(String message) { String settings_error(String message) {
@@ -1301,6 +1305,18 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get map_manageRepeater => '管理重复器'; String get map_manageRepeater => '管理重复器';
@override
String get map_tapToAdd => '点击节点将其添加到路径中';
@override
String get map_runTrace => '运行路径跟踪';
@override
String get map_removeLast => '删除最后一个';
@override
String get map_pathTraceCancelled => '路径跟踪已取消';
@override @override
String get mapCache_title => '离线地图缓存'; String get mapCache_title => '离线地图缓存';
@@ -2557,6 +2573,9 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get pathTrace_someHopsNoLocation => '其中一个或多个啤酒花缺少位置!'; String get pathTrace_someHopsNoLocation => '其中一个或多个啤酒花缺少位置!';
@override
String get pathTrace_clearTooltip => '清除路径';
@override @override
String get contacts_pathTrace => '路径追踪'; String get contacts_pathTrace => '路径追踪';
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Aantal Contacten", "settings_infoContactsCount": "Aantal Contacten",
"settings_infoChannelCount": "Aantal Kanalen", "settings_infoChannelCount": "Aantal Kanalen",
"settings_presets": "Presets", "settings_presets": "Presets",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frequentie (MHz)", "settings_frequency": "Frequentie (MHz)",
"settings_frequencyHelper": "300,0 - 2500,0", "settings_frequencyHelper": "300,0 - 2500,0",
"settings_frequencyInvalid": "Ongeldige frequentie (300-2500 MHz)", "settings_frequencyInvalid": "Ongeldige frequentie (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Vermogen (dBm)", "settings_txPower": "TX Vermogen (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Ongeldige TX-vermogen (0-22 dBm)", "settings_txPowerInvalid": "Ongeldige TX-vermogen (0-22 dBm)",
"settings_longRange": "Lange Afstand",
"settings_fastSpeed": "Hoge Snelheid",
"settings_error": "Fout: {message}", "settings_error": "Fout: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{nieuw knooppunt} other{nieuwe knooppunten}}", "notification_newNodesCount": "{count} {count, plural, =1{nieuw knooppunt} other{nieuwe knooppunten}}",
"notification_newTypeDiscovered": "Nieuw {contactType} ontdekt", "notification_newTypeDiscovered": "Nieuw {contactType} ontdekt",
"notification_receivedNewMessage": "Nieuw bericht ontvangen", "notification_receivedNewMessage": "Nieuw bericht ontvangen",
"contacts_zeroHopContactAdvertFailed": "Mislukt om contact te verzenden",
"settings_gpxExportRepeatersSubtitle": "Exporteert repeaters / roomserver met een locatie naar GPX-bestand.", "settings_gpxExportRepeatersSubtitle": "Exporteert repeaters / roomserver met een locatie naar GPX-bestand.",
"settings_gpxExportRepeaters": "Exporteer repeaters / roomserver naar GPX", "settings_gpxExportRepeaters": "Exporteer repeaters / roomserver naar GPX",
"settings_gpxExportSuccess": "Succesvol GPX-bestand geëxporteerd.", "settings_gpxExportSuccess": "Succesvol GPX-bestand geëxporteerd.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportAllContacts": "Alle contactlocaties", "settings_gpxExportAllContacts": "Alle contactlocaties",
"settings_gpxExportShareText": "Kaartgegevens geëxporteerd uit meshcore-open", "settings_gpxExportShareText": "Kaartgegevens geëxporteerd uit meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open GPX kaartgegevens exporteren", "settings_gpxExportShareSubject": "meshcore-open GPX kaartgegevens exporteren",
"pathTrace_someHopsNoLocation": "Een of meer van de hops ontbreken een locatie!" "pathTrace_someHopsNoLocation": "Een of meer van de hops ontbreken een locatie!",
"map_removeLast": "Verwijder Laatste",
"pathTrace_clearTooltip": "Weg wissen",
"map_pathTraceCancelled": "Pad traceren geannuleerd",
"map_tapToAdd": "Tik op knooppunten om ze toe te voegen aan het pad",
"map_runTrace": "Padeshulp traceren",
"scanner_enableBluetooth": "Activeer Bluetooth",
"scanner_bluetoothOffMessage": "Zorg ervoor dat Bluetooth is ingeschakeld om naar apparaten te zoeken.",
"scanner_bluetoothOff": "Bluetooth is uitgeschakeld",
"settings_clientRepeat": "Herhalen: Afgekoppeld",
"settings_clientRepeatSubtitle": "Laat dit apparaat de mesh-pakketten opnieuw verzenden voor andere apparaten.",
"settings_clientRepeatFreqWarning": "Om een signaal buiten het netwerk te versturen, zijn frequenties van 433, 869 of 918 MHz vereist."
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Liczba kontaktów", "settings_infoContactsCount": "Liczba kontaktów",
"settings_infoChannelCount": "Liczba kanałów", "settings_infoChannelCount": "Liczba kanałów",
"settings_presets": "Preset", "settings_presets": "Preset",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Częstotliwość (MHz)", "settings_frequency": "Częstotliwość (MHz)",
"settings_frequencyHelper": "300,0 - 2500,0", "settings_frequencyHelper": "300,0 - 2500,0",
"settings_frequencyInvalid": "Nieprawidłowa częstotliwość (300-2500 MHz)", "settings_frequencyInvalid": "Nieprawidłowa częstotliwość (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Moc (dBm)", "settings_txPower": "TX Moc (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Nieprawidłowa moc TX (0-22 dBm)", "settings_txPowerInvalid": "Nieprawidłowa moc TX (0-22 dBm)",
"settings_longRange": "Długi zasięg",
"settings_fastSpeed": "Szybka prędkość",
"settings_error": "Błąd: {message}", "settings_error": "Błąd: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{nowy węzeł} few{nowe węzły} many{nowych węzłów} other{nowych węzłów}}", "notification_newNodesCount": "{count} {count, plural, =1{nowy węzeł} few{nowe węzły} many{nowych węzłów} other{nowych węzłów}}",
"notification_newTypeDiscovered": "Nowy {contactType} wykryty", "notification_newTypeDiscovered": "Nowy {contactType} wykryty",
"notification_receivedNewMessage": "Otrzymano nową wiadomość", "notification_receivedNewMessage": "Otrzymano nową wiadomość",
"contacts_zeroHopContactAdvertFailed": "Nie udało się wysłać kontaktu.",
"settings_gpxExportContacts": "Eksportuj towarzyszy do GPX", "settings_gpxExportContacts": "Eksportuj towarzyszy do GPX",
"settings_gpxExportRepeaters": "Eksportuj powtórki / serwer pokojowy do GPX", "settings_gpxExportRepeaters": "Eksportuj powtórki / serwer pokojowy do GPX",
"settings_gpxExportRepeatersSubtitle": "Eksportuje powtarzacze / roomserver z lokalizacją do pliku GPX.", "settings_gpxExportRepeatersSubtitle": "Eksportuje powtarzacze / roomserver z lokalizacją do pliku GPX.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportChat": "Lokalizacje towarzyszy", "settings_gpxExportChat": "Lokalizacje towarzyszy",
"settings_gpxExportShareText": "Dane mapy wyeksportowane z meshcore-open", "settings_gpxExportShareText": "Dane mapy wyeksportowane z meshcore-open",
"settings_gpxExportShareSubject": "Eksport danych mapy GPX meshcore-open", "settings_gpxExportShareSubject": "Eksport danych mapy GPX meshcore-open",
"pathTrace_someHopsNoLocation": "Jeden lub więcej z chmieli nie ma określonej lokalizacji!" "pathTrace_someHopsNoLocation": "Jeden lub więcej z chmieli nie ma określonej lokalizacji!",
"map_pathTraceCancelled": "Śledzenie ścieżki anulowano.",
"map_runTrace": "Uruchom ślad ścieżki",
"pathTrace_clearTooltip": "Wyczyść ścieżkę",
"map_removeLast": "Usuń ostatni",
"map_tapToAdd": "Kliknij na węzły, aby dodać je do ścieżki.",
"scanner_bluetoothOffMessage": "Prosimy włączyć Bluetooth, aby przeskanować urządzenia.",
"scanner_bluetoothOff": "Bluetooth jest wyłączony",
"scanner_enableBluetooth": "Włącz Bluetooth",
"settings_clientRepeatSubtitle": "Pozwól temu urządzeniu powtarzać pakiety danych dla innych urządzeń.",
"settings_clientRepeat": "Powtórzenie: Niezależne od sieci",
"settings_clientRepeatFreqWarning": "Powtórka poza siecią wymaga częstotliwości 433, 869 lub 918 MHz."
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Número de Contatos", "settings_infoContactsCount": "Número de Contatos",
"settings_infoChannelCount": "Número do Canal", "settings_infoChannelCount": "Número do Canal",
"settings_presets": "Presets", "settings_presets": "Presets",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frequência (MHz)", "settings_frequency": "Frequência (MHz)",
"settings_frequencyHelper": "300,0 - 2500,0", "settings_frequencyHelper": "300,0 - 2500,0",
"settings_frequencyInvalid": "Frequência inválida (300-2500 MHz)", "settings_frequencyInvalid": "Frequência inválida (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Potência (dBm)", "settings_txPower": "TX Potência (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Potência de TX inválida (0-22 dBm)", "settings_txPowerInvalid": "Potência de TX inválida (0-22 dBm)",
"settings_longRange": "Alcance Longo",
"settings_fastSpeed": "Velocidade Rápida",
"settings_error": "Erro: {message}", "settings_error": "Erro: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{novo nó} other{novos nós}}", "notification_newNodesCount": "{count} {count, plural, =1{novo nó} other{novos nós}}",
"notification_newTypeDiscovered": "Novo {contactType} descoberto", "notification_newTypeDiscovered": "Novo {contactType} descoberto",
"notification_receivedNewMessage": "Nova mensagem recebida", "notification_receivedNewMessage": "Nova mensagem recebida",
"contacts_zeroHopContactAdvertFailed": "Falha ao enviar contato.",
"settings_gpxExportRepeaters": "Exportar repetidores / servidor de sala para GPX", "settings_gpxExportRepeaters": "Exportar repetidores / servidor de sala para GPX",
"settings_gpxExportRepeatersSubtitle": "Exporta repetidores / roomserver com localização para arquivo GPX.", "settings_gpxExportRepeatersSubtitle": "Exporta repetidores / roomserver com localização para arquivo GPX.",
"settings_gpxExportSuccess": "Arquivo GPX exportado com sucesso.", "settings_gpxExportSuccess": "Arquivo GPX exportado com sucesso.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportAllContacts": "Todos os locais de contatos", "settings_gpxExportAllContacts": "Todos os locais de contatos",
"settings_gpxExportShareText": "Dados do mapa exportados do meshcore-open", "settings_gpxExportShareText": "Dados do mapa exportados do meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open exportação de dados de mapa GPX", "settings_gpxExportShareSubject": "meshcore-open exportação de dados de mapa GPX",
"pathTrace_someHopsNoLocation": "Um ou mais dos lúpulos estão sem localização!" "pathTrace_someHopsNoLocation": "Um ou mais dos lúpulos estão sem localização!",
"map_runTrace": "Executar Traçado de Caminho",
"map_pathTraceCancelled": "Rastreamento de caminho cancelado.",
"pathTrace_clearTooltip": "Limpar caminho",
"map_removeLast": "Remover Último",
"map_tapToAdd": "Toque nos nós para adicioná-los ao caminho.",
"scanner_enableBluetooth": "Ative o Bluetooth",
"scanner_bluetoothOff": "Bluetooth está desativado",
"scanner_bluetoothOffMessage": "Por favor, ative o Bluetooth para escanear por dispositivos.",
"settings_clientRepeatFreqWarning": "A repetição fora da rede requer frequências de 433, 869 ou 918 MHz.",
"settings_clientRepeat": "Repetição sem rede",
"settings_clientRepeatSubtitle": "Permita que este dispositivo repita pacotes de rede para outros dispositivos."
} }
+12 -8
View File
@@ -101,9 +101,6 @@
"settings_infoContactsCount": "Количество контактов", "settings_infoContactsCount": "Количество контактов",
"settings_infoChannelCount": "Количество каналов", "settings_infoChannelCount": "Количество каналов",
"settings_presets": "Пресеты", "settings_presets": "Пресеты",
"settings_preset915Mhz": "915 МГц",
"settings_preset868Mhz": "868 МГц",
"settings_preset433Mhz": "433 МГц",
"settings_frequency": "Частота (МГц)", "settings_frequency": "Частота (МГц)",
"settings_frequencyHelper": "300.0 2500.0", "settings_frequencyHelper": "300.0 2500.0",
"settings_frequencyInvalid": "Недопустимая частота (300–2500 МГц)", "settings_frequencyInvalid": "Недопустимая частота (300–2500 МГц)",
@@ -113,8 +110,6 @@
"settings_txPower": "Мощность передачи (дБм)", "settings_txPower": "Мощность передачи (дБм)",
"settings_txPowerHelper": "0 22", "settings_txPowerHelper": "0 22",
"settings_txPowerInvalid": "Недопустимая мощность передачи (0–22 дБм)", "settings_txPowerInvalid": "Недопустимая мощность передачи (0–22 дБм)",
"settings_longRange": "Дальний радиус",
"settings_fastSpeed": "Высокая скорость",
"settings_error": "Ошибка: {message}", "settings_error": "Ошибка: {message}",
"appSettings_title": "Настройки приложения", "appSettings_title": "Настройки приложения",
"appSettings_appearance": "Внешний вид", "appSettings_appearance": "Внешний вид",
@@ -815,7 +810,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{новый узел} few{новых узла} many{новых узлов} other{новых узлов}}", "notification_newNodesCount": "{count} {count, plural, =1{новый узел} few{новых узла} many{новых узлов} other{новых узлов}}",
"notification_newTypeDiscovered": "Обнаружен новый {contactType}", "notification_newTypeDiscovered": "Обнаружен новый {contactType}",
"notification_receivedNewMessage": "Получено новое сообщение", "notification_receivedNewMessage": "Получено новое сообщение",
"contacts_zeroHopContactAdvertSent": "Отправлено сообщение по объявлению.",
"settings_gpxExportRepeaters": "Экспортировать рипитеры / сервер комнаты в GPX", "settings_gpxExportRepeaters": "Экспортировать рипитеры / сервер комнаты в GPX",
"settings_gpxExportRepeatersSubtitle": "Экспортирует ретрансляторы / сервер комнат с местоположением в файл GPX.", "settings_gpxExportRepeatersSubtitle": "Экспортирует ретрансляторы / сервер комнат с местоположением в файл GPX.",
"settings_gpxExportContacts": "Экспортировать спутников в GPX", "settings_gpxExportContacts": "Экспортировать спутников в GPX",
@@ -831,6 +825,16 @@
"settings_gpxExportNoContacts": "Нет контактов для экспорта.", "settings_gpxExportNoContacts": "Нет контактов для экспорта.",
"settings_gpxExportShareText": "Данные карты экспортированы из meshcore-open", "settings_gpxExportShareText": "Данные карты экспортированы из meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open экспорт данных карты GPX", "settings_gpxExportShareSubject": "meshcore-open экспорт данных карты GPX",
"pathTrace_someHopsNoLocation": "Одному или нескольким хмелям не указано местоположение!" "pathTrace_someHopsNoLocation": "Одному или нескольким хмелям не указано местоположение!",
"map_tapToAdd": "Нажимайте на узлы, чтобы добавить их в путь.",
"map_removeLast": "Удалить последний",
"map_pathTraceCancelled": "Отмена трассировки пути",
"pathTrace_clearTooltip": "Очистить путь",
"map_runTrace": "Запустить трассировку пути",
"scanner_enableBluetooth": "Включите Bluetooth",
"scanner_bluetoothOff": "Bluetooth выключен",
"scanner_bluetoothOffMessage": "Пожалуйста, включите Bluetooth, чтобы найти устройства.",
"settings_clientRepeatFreqWarning": "Для работы в режиме \"без подключения к сети\" требуется частота 433, 869 или 918 МГц.",
"settings_clientRepeatSubtitle": "Позвольте этому устройству повторять пакеты данных для других устройств.",
"settings_clientRepeat": "Повторение \"вне сети\""
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Počet kontaktov", "settings_infoContactsCount": "Počet kontaktov",
"settings_infoChannelCount": "Počet kanálov", "settings_infoChannelCount": "Počet kanálov",
"settings_presets": "Prednastavenia", "settings_presets": "Prednastavenia",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frekvencia (MHz)", "settings_frequency": "Frekvencia (MHz)",
"settings_frequencyHelper": "300,0 2500,0", "settings_frequencyHelper": "300,0 2500,0",
"settings_frequencyInvalid": "Neplatná frekvencia (300-2500 MHz)", "settings_frequencyInvalid": "Neplatná frekvencia (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Výkon (dBm)", "settings_txPower": "TX Výkon (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Neplatná hodnota výkonu TX (0-22 dBm)", "settings_txPowerInvalid": "Neplatná hodnota výkonu TX (0-22 dBm)",
"settings_longRange": "Dlhý dosah",
"settings_fastSpeed": "Rýchla rýchlosť",
"settings_error": "Chyba: {message}", "settings_error": "Chyba: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{nový uzol} few{nové uzly} other{nových uzlov}}", "notification_newNodesCount": "{count} {count, plural, =1{nový uzol} few{nové uzly} other{nových uzlov}}",
"notification_newTypeDiscovered": "Nový {contactType} objavený", "notification_newTypeDiscovered": "Nový {contactType} objavený",
"notification_receivedNewMessage": "Prijatá nová správa", "notification_receivedNewMessage": "Prijatá nová správa",
"contacts_ShareContact": "Kopírovať kontakt do schránky",
"settings_gpxExportRepeatersSubtitle": "Exportuje repeater / roomserver s lokalitou do súboru GPX.", "settings_gpxExportRepeatersSubtitle": "Exportuje repeater / roomserver s lokalitou do súboru GPX.",
"settings_gpxExportContacts": "Export sprievodcov do GPX", "settings_gpxExportContacts": "Export sprievodcov do GPX",
"settings_gpxExportSuccess": "Úspešne exportovaný súbor GPX.", "settings_gpxExportSuccess": "Úspešne exportovaný súbor GPX.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportChat": "Lokácie sprievodcov", "settings_gpxExportChat": "Lokácie sprievodcov",
"settings_gpxExportShareText": "Mapové údaje exportované z meshcore-open", "settings_gpxExportShareText": "Mapové údaje exportované z meshcore-open",
"settings_gpxExportShareSubject": "meshcore-open export dát GPX mapových údajov", "settings_gpxExportShareSubject": "meshcore-open export dát GPX mapových údajov",
"pathTrace_someHopsNoLocation": "Jedna alebo viac chmeľov chýba lokalita!" "pathTrace_someHopsNoLocation": "Jedna alebo viac chmeľov chýba lokalita!",
"pathTrace_clearTooltip": "Zmazať cestu",
"map_tapToAdd": "Kliknite na uzly, aby ste ich pridali k ceste.",
"map_removeLast": "Odstrániť posledný",
"map_runTrace": "Spustiť trasovaním cesty",
"map_pathTraceCancelled": "Zrušenie stopáže cesty bolo zrušené.",
"scanner_bluetoothOffMessage": "Prosím, zapnite Bluetooth, aby ste mohli skenovať pre zariadenia.",
"scanner_bluetoothOff": "Bluetooth je vypnutý",
"scanner_enableBluetooth": "Povolte Bluetooth",
"settings_clientRepeat": "Opätovné použitie bez elektrickej siete",
"settings_clientRepeatFreqWarning": "Použitie off-grid systému vyžaduje frekvencie 433, 869 alebo 918 MHz.",
"settings_clientRepeatSubtitle": "Umožnite, aby toto zariadenie opakovávalo siete pre ostatných."
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Število stikov", "settings_infoContactsCount": "Število stikov",
"settings_infoChannelCount": "Število kanalov", "settings_infoChannelCount": "Število kanalov",
"settings_presets": "Prednastavitve", "settings_presets": "Prednastavitve",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frekvenca (MHz)", "settings_frequency": "Frekvenca (MHz)",
"settings_frequencyHelper": "300,00 - 2500,00", "settings_frequencyHelper": "300,00 - 2500,00",
"settings_frequencyInvalid": "Neveljavna frekvenca (300-2500 MHz)", "settings_frequencyInvalid": "Neveljavna frekvenca (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX Moč (dBm)", "settings_txPower": "TX Moč (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Neveljavna TX moč (0-22 dBm)", "settings_txPowerInvalid": "Neveljavna TX moč (0-22 dBm)",
"settings_longRange": "DDolg doseg",
"settings_fastSpeed": "Visoka hitrost",
"settings_error": "Napaka: {message}", "settings_error": "Napaka: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{novo vozlišče} =2{novi vozlišči} few{nova vozlišča} other{novih vozlišč}}", "notification_newNodesCount": "{count} {count, plural, =1{novo vozlišče} =2{novi vozlišči} few{nova vozlišča} other{novih vozlišč}}",
"notification_newTypeDiscovered": "Odkrito novo {contactType}", "notification_newTypeDiscovered": "Odkrito novo {contactType}",
"notification_receivedNewMessage": "Prejeto novo sporočilo", "notification_receivedNewMessage": "Prejeto novo sporočilo",
"contacts_ShareContact": "Kopiraj stik v Odložišče",
"settings_gpxExportAll": "Izvozi vse kontakte v GPX", "settings_gpxExportAll": "Izvozi vse kontakte v GPX",
"settings_gpxExportContacts": "Izvoz spremljevalcev v GPX", "settings_gpxExportContacts": "Izvoz spremljevalcev v GPX",
"settings_gpxExportRepeatersSubtitle": "Izvozi ponovljene oddajnike / strežnik sobe z lokacijo v datoteko GPX.", "settings_gpxExportRepeatersSubtitle": "Izvozi ponovljene oddajnike / strežnik sobe z lokacijo v datoteko GPX.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportNoContacts": "Ni stikov za izvoz.", "settings_gpxExportNoContacts": "Ni stikov za izvoz.",
"settings_gpxExportNotAvailable": "Ni podprto na vašem napravi/operacijskem sistemu", "settings_gpxExportNotAvailable": "Ni podprto na vašem napravi/operacijskem sistemu",
"settings_gpxExportShareSubject": "meshcore-open izvoz podatkov GPX karte", "settings_gpxExportShareSubject": "meshcore-open izvoz podatkov GPX karte",
"pathTrace_someHopsNoLocation": "Ena ali več hmelju manjka lokacija!" "pathTrace_someHopsNoLocation": "Ena ali več hmelju manjka lokacija!",
"map_tapToAdd": "Pritisnite na vozlišča, da jih dodate poti.",
"map_removeLast": "Odstrani Zadnji",
"map_runTrace": "Zaženi sledenje poti",
"pathTrace_clearTooltip": "Počisti pot",
"map_pathTraceCancelled": "Spremljanje poti je prekinjeno.",
"scanner_enableBluetooth": "Omogočite Bluetooth",
"scanner_bluetoothOffMessage": "Prosimo, vklopite Bluetooth, da lahko poiščete naprave.",
"scanner_bluetoothOff": "Bluetooth je izklopljen",
"settings_clientRepeatFreqWarning": "Za ponovni prenos na brezžični način so potrebne frekvence 433, 869 ali 918 MHz.",
"settings_clientRepeatSubtitle": "Omogočite temu naprave, da ponavlja paketne sporočila za druge.",
"settings_clientRepeat": "Neovadno ponavljanje"
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Kontakterantal", "settings_infoContactsCount": "Kontakterantal",
"settings_infoChannelCount": "Kanalantal", "settings_infoChannelCount": "Kanalantal",
"settings_presets": "Fördefinierade inställningar", "settings_presets": "Fördefinierade inställningar",
"settings_preset915Mhz": "915 MHz",
"settings_preset868Mhz": "868 MHz",
"settings_preset433Mhz": "433 MHz",
"settings_frequency": "Frekvens (MHz)", "settings_frequency": "Frekvens (MHz)",
"settings_frequencyHelper": "300,0 - 2500,0", "settings_frequencyHelper": "300,0 - 2500,0",
"settings_frequencyInvalid": "Ogiltig frekvens (300-2500 MHz)", "settings_frequencyInvalid": "Ogiltig frekvens (300-2500 MHz)",
@@ -143,8 +140,6 @@
"settings_txPower": "TX-effekt (dBm)", "settings_txPower": "TX-effekt (dBm)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Ogiltig TX-effekt (0-22 dBm)", "settings_txPowerInvalid": "Ogiltig TX-effekt (0-22 dBm)",
"settings_longRange": "Lång räckvidd",
"settings_fastSpeed": "Snabb hastighet",
"settings_error": "Fel: {message}", "settings_error": "Fel: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{ny nod} other{nya noder}}", "notification_newNodesCount": "{count} {count, plural, =1{ny nod} other{nya noder}}",
"notification_newTypeDiscovered": "Ny {contactType} upptäckt", "notification_newTypeDiscovered": "Ny {contactType} upptäckt",
"notification_receivedNewMessage": "Nytt meddelande mottaget", "notification_receivedNewMessage": "Nytt meddelande mottaget",
"contacts_ShareContactZeroHop": "Dela kontakt via annons",
"settings_gpxExportAll": "Exportera alla kontakter till GPX", "settings_gpxExportAll": "Exportera alla kontakter till GPX",
"settings_gpxExportRepeatersSubtitle": "Exporterar repeater / roomserver med plats till GPX-fil.", "settings_gpxExportRepeatersSubtitle": "Exporterar repeater / roomserver med plats till GPX-fil.",
"settings_gpxExportSuccess": "Har exporterat GPX-fil med framgång", "settings_gpxExportSuccess": "Har exporterat GPX-fil med framgång",
@@ -1591,6 +1585,16 @@
"settings_gpxExportAllContacts": "Alla kontakters platser", "settings_gpxExportAllContacts": "Alla kontakters platser",
"settings_gpxExportShareSubject": "meshcore-open export av GPX-kartdata", "settings_gpxExportShareSubject": "meshcore-open export av GPX-kartdata",
"settings_gpxExportShareText": "Kartdata exporterad från meshcore-open", "settings_gpxExportShareText": "Kartdata exporterad från meshcore-open",
"pathTrace_someHopsNoLocation": "En eller flera av humlen saknar en plats!" "pathTrace_someHopsNoLocation": "En eller flera av humlen saknar en plats!",
"pathTrace_clearTooltip": "Rensa väg",
"map_pathTraceCancelled": "Sökvägsspårning avbruten.",
"map_runTrace": "Kör spårsökning",
"map_tapToAdd": "Tryck på noder för att lägga till dem i banan.",
"map_removeLast": "Ta bort sista",
"scanner_enableBluetooth": "Aktivera Bluetooth",
"scanner_bluetoothOffMessage": "Vänligen aktivera Bluetooth för att söka efter enheter.",
"scanner_bluetoothOff": "Bluetooth är avstängt",
"settings_clientRepeatSubtitle": "Låt enheten repetera nätpaket för andra användare.",
"settings_clientRepeat": "Upprepa utan elnät",
"settings_clientRepeatFreqWarning": "För att kunna kommunicera utanför elnätet krävs frekvenserna 433, 869 eller 918 MHz."
} }
+12 -8
View File
@@ -131,9 +131,6 @@
"settings_infoContactsCount": "Кількість контактів", "settings_infoContactsCount": "Кількість контактів",
"settings_infoChannelCount": "Кількість каналів", "settings_infoChannelCount": "Кількість каналів",
"settings_presets": "Попередні налаштування", "settings_presets": "Попередні налаштування",
"settings_preset915Mhz": "915 МГц",
"settings_preset868Mhz": "868 МГц",
"settings_preset433Mhz": "433 МГц",
"settings_frequency": "Частота (МГц)", "settings_frequency": "Частота (МГц)",
"settings_frequencyHelper": "300.0 - 2500.0", "settings_frequencyHelper": "300.0 - 2500.0",
"settings_frequencyInvalid": "Некоректна частота (300-2500 МГц)", "settings_frequencyInvalid": "Некоректна частота (300-2500 МГц)",
@@ -143,8 +140,6 @@
"settings_txPower": "Потужність TX (дБм)", "settings_txPower": "Потужність TX (дБм)",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "Некоректна потужність TX (0-22 дБм)", "settings_txPowerInvalid": "Некоректна потужність TX (0-22 дБм)",
"settings_longRange": "Дальній діапазон",
"settings_fastSpeed": "Висока швидкість",
"settings_error": "Помилка: {message}", "settings_error": "Помилка: {message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} {count, plural, =1{новий вузол} few{нових вузли} many{нових вузлів} other{нових вузлів}}", "notification_newNodesCount": "{count} {count, plural, =1{новий вузол} few{нових вузли} many{нових вузлів} other{нових вузлів}}",
"notification_newTypeDiscovered": "Виявлено новий {contactType}", "notification_newTypeDiscovered": "Виявлено новий {contactType}",
"notification_receivedNewMessage": "Отримано нове повідомлення", "notification_receivedNewMessage": "Отримано нове повідомлення",
"contacts_ShareContactZeroHop": "Поділитися контактом за оголошенням",
"settings_gpxExportRepeaters": "Експортувати ретранслятори / сервер кімнати до GPX", "settings_gpxExportRepeaters": "Експортувати ретранслятори / сервер кімнати до GPX",
"settings_gpxExportRepeatersSubtitle": "Експортує ретранслятори / сервер кімнати з місцезнаходженням у файл GPX.", "settings_gpxExportRepeatersSubtitle": "Експортує ретранслятори / сервер кімнати з місцезнаходженням у файл GPX.",
"settings_gpxExportSuccess": "Успішно експортовано файл GPX.", "settings_gpxExportSuccess": "Успішно експортовано файл GPX.",
@@ -1591,6 +1585,16 @@
"settings_gpxExportShareText": "Дані карти експортовані з meshcore-open", "settings_gpxExportShareText": "Дані карти експортовані з meshcore-open",
"settings_gpxExportAllContacts": "Усі місця контактів", "settings_gpxExportAllContacts": "Усі місця контактів",
"settings_gpxExportShareSubject": "експорт даних карти meshcore-open у форматі GPX", "settings_gpxExportShareSubject": "експорт даних карти meshcore-open у форматі GPX",
"pathTrace_someHopsNoLocation": "Одне або більше хмелів відсутнє місце розташування!" "pathTrace_someHopsNoLocation": "Одне або більше хмелів відсутнє місце розташування!",
"map_tapToAdd": "Натисніть на вузли, щоб додати їх до шляху",
"map_runTrace": "Виконати трасування шляху",
"pathTrace_clearTooltip": "Очистити шлях",
"map_removeLast": "Видалити останній",
"map_pathTraceCancelled": "Відмінується трасування шляху",
"scanner_enableBluetooth": "Увімкніть Bluetooth",
"scanner_bluetoothOffMessage": "Будь ласка, увімкніть Bluetooth, щоб сканувати пристрої.",
"scanner_bluetoothOff": "Bluetooth вимкнено",
"settings_clientRepeatFreqWarning": "Повтор без підключення до мережі вимагає частоти 433, 869 або 918 МГц.",
"settings_clientRepeatSubtitle": "Дозвольте цьому пристрою повторювати пакети даних для інших пристроїв.",
"settings_clientRepeat": "Автономна система"
} }
+12 -8
View File
@@ -136,9 +136,6 @@
"settings_infoContactsCount": "联系人数量", "settings_infoContactsCount": "联系人数量",
"settings_infoChannelCount": "通道数量", "settings_infoChannelCount": "通道数量",
"settings_presets": "预设", "settings_presets": "预设",
"settings_preset915Mhz": "915 兆赫",
"settings_preset868Mhz": "868 兆赫",
"settings_preset433Mhz": "433 兆赫",
"settings_frequency": "频率 (MHz)", "settings_frequency": "频率 (MHz)",
"settings_frequencyHelper": "300.0 - 2500.0", "settings_frequencyHelper": "300.0 - 2500.0",
"settings_frequencyInvalid": "无效频率(300-2500 MHz", "settings_frequencyInvalid": "无效频率(300-2500 MHz",
@@ -148,8 +145,6 @@
"settings_txPower": "TX 功率(dBm", "settings_txPower": "TX 功率(dBm",
"settings_txPowerHelper": "0 - 22", "settings_txPowerHelper": "0 - 22",
"settings_txPowerInvalid": "无效的发射功率(0-22 dBm", "settings_txPowerInvalid": "无效的发射功率(0-22 dBm",
"settings_longRange": "远距离",
"settings_fastSpeed": "高速",
"settings_error": "[保存:{message}]\n错误:{message}", "settings_error": "[保存:{message}]\n错误:{message}",
"@settings_error": { "@settings_error": {
"placeholders": { "placeholders": {
@@ -1575,7 +1570,6 @@
"notification_newNodesCount": "{count} 个新节点", "notification_newNodesCount": "{count} 个新节点",
"notification_newTypeDiscovered": "发现新 {contactType}", "notification_newTypeDiscovered": "发现新 {contactType}",
"notification_receivedNewMessage": "收到新消息", "notification_receivedNewMessage": "收到新消息",
"contacts_contactAdvertCopyFailed": "将广告复制到剪贴板操作失败。",
"settings_gpxExportRepeaters": "导出重复器/房间服务器到GPX", "settings_gpxExportRepeaters": "导出重复器/房间服务器到GPX",
"settings_gpxExportRepeatersSubtitle": "导出带有位置的重复器/房间服务器到GPX文件。", "settings_gpxExportRepeatersSubtitle": "导出带有位置的重复器/房间服务器到GPX文件。",
"settings_gpxExportContactsSubtitle": "导出带有位置的伙伴到GPX文件。", "settings_gpxExportContactsSubtitle": "导出带有位置的伙伴到GPX文件。",
@@ -1591,6 +1585,16 @@
"settings_gpxExportNoContacts": "没有联系人可导出", "settings_gpxExportNoContacts": "没有联系人可导出",
"settings_gpxExportShareText": "来自meshcore-open的导出地图数据", "settings_gpxExportShareText": "来自meshcore-open的导出地图数据",
"settings_gpxExportShareSubject": "meshcore-open GPX 地图数据导出", "settings_gpxExportShareSubject": "meshcore-open GPX 地图数据导出",
"pathTrace_someHopsNoLocation": "其中一个或多个啤酒花缺少位置!" "pathTrace_someHopsNoLocation": "其中一个或多个啤酒花缺少位置!",
"map_tapToAdd": "点击节点将其添加到路径中",
"pathTrace_clearTooltip": "清除路径",
"map_pathTraceCancelled": "路径跟踪已取消",
"map_removeLast": "删除最后一个",
"map_runTrace": "运行路径跟踪",
"scanner_bluetoothOffMessage": "请打开蓝牙功能,以便搜索设备。",
"scanner_bluetoothOff": "蓝牙已关闭",
"scanner_enableBluetooth": "启用蓝牙",
"settings_clientRepeat": "离网重复",
"settings_clientRepeatSubtitle": "允许此设备重复发送网状数据包给其他设备",
"settings_clientRepeatFreqWarning": "离网重复通信需要使用 433、869 或 918 兆赫兹的频率。"
} }
+1 -6
View File
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:meshcore_open/services/sparse_location_logger.dart';
import 'l10n/app_localizations.dart'; import 'l10n/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -34,7 +33,7 @@ void main() async {
final appDebugLogService = AppDebugLogService(); final appDebugLogService = AppDebugLogService();
final backgroundService = BackgroundService(); final backgroundService = BackgroundService();
final mapTileCacheService = MapTileCacheService(); final mapTileCacheService = MapTileCacheService();
final sparseLocationLogger = SparseLocationLogger();
// Load settings // Load settings
await appSettingsService.loadSettings(); await appSettingsService.loadSettings();
@@ -57,7 +56,6 @@ void main() async {
bleDebugLogService: bleDebugLogService, bleDebugLogService: bleDebugLogService,
appDebugLogService: appDebugLogService, appDebugLogService: appDebugLogService,
backgroundService: backgroundService, backgroundService: backgroundService,
sparseLocationLogger: sparseLocationLogger,
); );
await connector.loadContactCache(); await connector.loadContactCache();
@@ -78,7 +76,6 @@ void main() async {
bleDebugLogService: bleDebugLogService, bleDebugLogService: bleDebugLogService,
appDebugLogService: appDebugLogService, appDebugLogService: appDebugLogService,
mapTileCacheService: mapTileCacheService, mapTileCacheService: mapTileCacheService,
sparseLocationLogger: sparseLocationLogger,
), ),
); );
} }
@@ -92,7 +89,6 @@ class MeshCoreApp extends StatelessWidget {
final BleDebugLogService bleDebugLogService; final BleDebugLogService bleDebugLogService;
final AppDebugLogService appDebugLogService; final AppDebugLogService appDebugLogService;
final MapTileCacheService mapTileCacheService; final MapTileCacheService mapTileCacheService;
final SparseLocationLogger sparseLocationLogger;
const MeshCoreApp({ const MeshCoreApp({
super.key, super.key,
@@ -104,7 +100,6 @@ class MeshCoreApp extends StatelessWidget {
required this.bleDebugLogService, required this.bleDebugLogService,
required this.appDebugLogService, required this.appDebugLogService,
required this.mapTileCacheService, required this.mapTileCacheService,
required this.sparseLocationLogger,
}); });
@override @override
+194 -40
View File
@@ -59,46 +59,200 @@ class RadioSettings {
required this.txPowerDbm, required this.txPowerDbm,
}); });
// Preset configurations // Regional preset configurations
static RadioSettings get preset915MHz => RadioSettings( static final List<(String, RadioSettings)> presets = [
frequencyMHz: 915.0, (
bandwidth: LoRaBandwidth.bw125, 'Australia',
spreadingFactor: LoRaSpreadingFactor.sf7, RadioSettings(
codingRate: LoRaCodingRate.cr4_5, frequencyMHz: 915.8,
txPowerDbm: 20, bandwidth: LoRaBandwidth.bw250,
); spreadingFactor: LoRaSpreadingFactor.sf10,
codingRate: LoRaCodingRate.cr4_5,
static RadioSettings get preset868MHz => RadioSettings( txPowerDbm: 20,
frequencyMHz: 868.0, ),
bandwidth: LoRaBandwidth.bw125, ),
spreadingFactor: LoRaSpreadingFactor.sf7, (
codingRate: LoRaCodingRate.cr4_5, 'Australia (Narrow)',
txPowerDbm: 14, RadioSettings(
); frequencyMHz: 916.575,
bandwidth: LoRaBandwidth.bw62_5,
static RadioSettings get preset433MHz => RadioSettings( spreadingFactor: LoRaSpreadingFactor.sf7,
frequencyMHz: 433.0, codingRate: LoRaCodingRate.cr4_5,
bandwidth: LoRaBandwidth.bw125, txPowerDbm: 20,
spreadingFactor: LoRaSpreadingFactor.sf7, ),
codingRate: LoRaCodingRate.cr4_5, ),
txPowerDbm: 20, (
); 'Australia SA, WA, QLD',
RadioSettings(
static RadioSettings get presetLongRange => RadioSettings( frequencyMHz: 923.125,
frequencyMHz: 915.0, bandwidth: LoRaBandwidth.bw62_5,
bandwidth: LoRaBandwidth.bw125, spreadingFactor: LoRaSpreadingFactor.sf8,
spreadingFactor: LoRaSpreadingFactor.sf12, codingRate: LoRaCodingRate.cr4_5,
codingRate: LoRaCodingRate.cr4_8, txPowerDbm: 20,
txPowerDbm: 20, ),
); ),
(
static RadioSettings get presetFastSpeed => RadioSettings( 'Czech Republic',
frequencyMHz: 915.0, RadioSettings(
bandwidth: LoRaBandwidth.bw500, frequencyMHz: 869.432,
spreadingFactor: LoRaSpreadingFactor.sf7, bandwidth: LoRaBandwidth.bw62_5,
codingRate: LoRaCodingRate.cr4_5, spreadingFactor: LoRaSpreadingFactor.sf7,
txPowerDbm: 20, codingRate: LoRaCodingRate.cr4_5,
); txPowerDbm: 14,
),
),
(
'EU 433MHz',
RadioSettings(
frequencyMHz: 433.650,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'EU/UK (Long Range)',
RadioSettings(
frequencyMHz: 869.525,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 14,
),
),
(
'EU/UK (Medium Range)',
RadioSettings(
frequencyMHz: 869.525,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf10,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 14,
),
),
(
'EU/UK (Narrow)',
RadioSettings(
frequencyMHz: 869.618,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf8,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 14,
),
),
(
'New Zealand',
RadioSettings(
frequencyMHz: 917.375,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'New Zealand (Narrow)',
RadioSettings(
frequencyMHz: 917.375,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf7,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'Portugal 433',
RadioSettings(
frequencyMHz: 433.375,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf9,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'Portugal 869',
RadioSettings(
frequencyMHz: 869.618,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf7,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 14,
),
),
(
'Switzerland',
RadioSettings(
frequencyMHz: 869.618,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf8,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 14,
),
),
(
'USA Arizona',
RadioSettings(
frequencyMHz: 908.205,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf10,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'USA/Canada',
RadioSettings(
frequencyMHz: 910.525,
bandwidth: LoRaBandwidth.bw62_5,
spreadingFactor: LoRaSpreadingFactor.sf7,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'Vietnam',
RadioSettings(
frequencyMHz: 920.250,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
// Off-grid repeat presets (valid client_repeat frequencies)
(
'Off-Grid 433',
RadioSettings(
frequencyMHz: 433.0,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
(
'Off-Grid 869',
RadioSettings(
frequencyMHz: 869.0,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 14,
),
),
(
'Off-Grid 918',
RadioSettings(
frequencyMHz: 918.0,
bandwidth: LoRaBandwidth.bw250,
spreadingFactor: LoRaSpreadingFactor.sf11,
codingRate: LoRaCodingRate.cr4_5,
txPowerDbm: 20,
),
),
];
int get frequencyHz => (frequencyMHz * 1000).round(); int get frequencyHz => (frequencyMHz * 1000).round();
int get bandwidthHz => bandwidth.hz; int get bandwidthHz => bandwidth.hz;
+1 -1
View File
@@ -55,7 +55,7 @@ class AppDebugLogScreen extends StatelessWidget {
child: hasEntries child: hasEntries
? ListView.separated( ? ListView.separated(
itemCount: entries.length, itemCount: entries.length,
separatorBuilder: (_, __) => const Divider(height: 1), separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final entry = entries[index]; final entry = entries[index];
return ListTile( return ListTile(
+1 -1
View File
@@ -100,7 +100,7 @@ class _BleDebugLogScreenState extends State<BleDebugLogScreen> {
itemCount: showingFrames itemCount: showingFrames
? entries.length ? entries.length
: rawEntries.length, : rawEntries.length,
separatorBuilder: (_, __) => const Divider(height: 1), separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (showingFrames) { if (showingFrames) {
final entry = entries[index]; final entry = entries[index];
+1 -1
View File
@@ -594,7 +594,7 @@ class _ChannelMessagePathMapScreenState
: ListView.separated( : ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 4), padding: const EdgeInsets.symmetric(vertical: 4),
itemCount: hops.length, itemCount: hops.length,
separatorBuilder: (_, __) => const Divider(height: 1), separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final hop = hops[index]; final hop = hops[index];
return ListTile( return ListTile(
+149 -16
View File
@@ -1,8 +1,10 @@
import 'dart:math'; import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart'; import 'package:latlong2/latlong.dart';
import 'package:meshcore_open/screens/path_trace_map.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../connector/meshcore_connector.dart'; import '../connector/meshcore_connector.dart';
@@ -48,9 +50,13 @@ class _MapScreenState extends State<MapScreen> {
final MapMarkerService _markerService = MapMarkerService(); final MapMarkerService _markerService = MapMarkerService();
final Set<String> _hiddenMarkerIds = {}; final Set<String> _hiddenMarkerIds = {};
Set<String> _removedMarkerIds = {}; Set<String> _removedMarkerIds = {};
bool _isBuildingPathTrace = false;
bool _isSelectingPoi = false; bool _isSelectingPoi = false;
bool _hasInitializedMap = false; bool _hasInitializedMap = false;
bool _removedMarkersLoaded = false; bool _removedMarkersLoaded = false;
final List<int> _pathTrace = [];
final List<LatLng> _points = [];
final List<Polyline> _polylines = [];
bool _legendExpanded = false; bool _legendExpanded = false;
@override @override
@@ -148,6 +154,19 @@ class _MapScreenState extends State<MapScreen> {
.where((c) => c.hasLocation) .where((c) => c.hasLocation)
.toList(); .toList();
_polylines.clear();
_polylines.addAll(
_points.length > 1
? [
Polyline(
points: _points,
strokeWidth: 4,
color: Colors.blueAccent,
),
]
: <Polyline>[],
);
// Calculate center and zoom of all nodes, or default to (0, 0) // Calculate center and zoom of all nodes, or default to (0, 0)
LatLng center = const LatLng(0, 0); LatLng center = const LatLng(0, 0);
double initialZoom = 10.0; double initialZoom = 10.0;
@@ -248,6 +267,12 @@ class _MapScreenState extends State<MapScreen> {
centerTitle: true, centerTitle: true,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
actions: [ actions: [
if (!_isBuildingPathTrace)
IconButton(
icon: const Icon(Icons.radar),
onPressed: () => _startPath(),
tooltip: context.l10n.contacts_pathTrace,
),
PopupMenuButton( PopupMenuButton(
itemBuilder: (context) => [ itemBuilder: (context) => [
PopupMenuItem( PopupMenuItem(
@@ -275,17 +300,6 @@ class _MapScreenState extends State<MapScreen> {
), ),
), ),
), ),
PopupMenuItem(
child: Row(
children: [
const Icon(Icons.refresh),
const SizedBox(width: 8),
Text(context.l10n.map_updateMyLocation),
],
),
onTap: () =>
connector.sparseLocationLogger?.updateMyLocation(),
),
], ],
icon: const Icon(Icons.more_vert), icon: const Icon(Icons.more_vert),
), ),
@@ -346,6 +360,8 @@ class _MapScreenState extends State<MapScreen> {
MapTileCacheService.userAgentPackageName, MapTileCacheService.userAgentPackageName,
maxZoom: 19, maxZoom: 19,
), ),
if (_polylines.isNotEmpty && _isBuildingPathTrace)
PolylineLayer(polylines: _polylines),
MarkerLayer( MarkerLayer(
markers: [ markers: [
if (highlightPosition != null) if (highlightPosition != null)
@@ -368,8 +384,8 @@ class _MapScreenState extends State<MapScreen> {
connector.selfLatitude!, connector.selfLatitude!,
connector.selfLongitude!, connector.selfLongitude!,
), ),
width: 40, width: 35,
height: 40, height: 35,
child: Container( child: Container(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -402,7 +418,12 @@ class _MapScreenState extends State<MapScreen> {
), ),
], ],
), ),
_buildLegend(contactsWithLocation.length, sharedMarkers.length), if (!_isBuildingPathTrace)
_buildLegend(
contactsWithLocation.length,
sharedMarkers.length,
),
if (_isBuildingPathTrace) _buildPathTraceOverlay(),
], ],
), ),
bottomNavigationBar: SafeArea( bottomNavigationBar: SafeArea(
@@ -446,7 +467,11 @@ class _MapScreenState extends State<MapScreen> {
width: 35, width: 35,
height: 35, height: 35,
child: GestureDetector( child: GestureDetector(
onTap: () => _showNodeInfo(context, contact), onLongPress: () =>
_isBuildingPathTrace ? _showNodeInfo(context, contact) : null,
onTap: () => _isBuildingPathTrace
? _addToPath(context, contact)
: _showNodeInfo(context, contact),
child: Column( child: Column(
children: [ children: [
Container( Container(
@@ -618,7 +643,7 @@ class _MapScreenState extends State<MapScreen> {
Widget _buildLegendItem(IconData icon, String label, Color color) { Widget _buildLegendItem(IconData icon, String label, Color color) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.symmetric(vertical: 1.0),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@@ -1466,6 +1491,114 @@ class _MapScreenState extends State<MapScreen> {
return context.l10n.time_allTime; return context.l10n.time_allTime;
} }
} }
void _addToPath(BuildContext context, Contact contact) {
setState(() {
_pathTrace.add(
contact.publicKey[0],
); // Add first 16 bytes of public key to path trace
_points.add(LatLng(contact.latitude!, contact.longitude!));
});
}
void _startPath() {
setState(() {
_isBuildingPathTrace = true;
_pathTrace.clear();
_points.clear();
_polylines.clear();
});
}
void _removePath() {
setState(() {
_pathTrace.removeLast(); // Remove last node from path trace
_points.removeLast(); // Remove last point from points list
_polylines.clear(); // Clear polylines
});
}
Widget _buildPathTraceOverlay() {
final l10n = context.l10n;
return Positioned(
top: 16,
left: 16,
right: 16,
child: Card(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
l10n.contacts_pathTrace,
style: TextStyle(fontWeight: FontWeight.bold),
),
if (_pathTrace.isEmpty) const SizedBox(height: 8),
if (_pathTrace.isEmpty)
Text(l10n.map_tapToAdd, style: TextStyle(fontSize: 12)),
const SizedBox(height: 6),
if (_pathTrace.isNotEmpty)
Text(
"${l10n.path_currentPathLabel} ${formatDistance(getPathDistanceMeters(_points))}",
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
),
SelectableText(
_pathTrace
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join(','),
style: TextStyle(fontSize: 18),
),
const SizedBox(height: 6),
Row(
mainAxisSize: MainAxisSize.min,
children: [
if (_pathTrace.isNotEmpty)
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PathTraceMapScreen(
title: l10n.contacts_pathTrace,
path: Uint8List.fromList(_pathTrace),
),
),
);
setState(() {
_isBuildingPathTrace = false;
});
},
child: Text(l10n.map_runTrace),
),
if (_pathTrace.isNotEmpty)
ElevatedButton(
onPressed: _removePath,
child: Text(l10n.map_removeLast),
),
if (_pathTrace.isEmpty)
ElevatedButton(
onPressed: () {
setState(() {
_isBuildingPathTrace = false;
_pathTrace.clear();
_points.clear();
_polylines.clear();
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.map_pathTraceCancelled)),
);
},
child: Text(l10n.common_cancel),
),
],
),
],
),
),
),
);
}
} }
class _MarkerPayload { class _MarkerPayload {
+81 -74
View File
@@ -13,6 +13,23 @@ import 'package:meshcore_open/services/map_tile_cache_service.dart';
import 'package:meshcore_open/widgets/snr_indicator.dart'; import 'package:meshcore_open/widgets/snr_indicator.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
double getPathDistanceMeters(List<LatLng> points) {
if (points.length <= 1) return 0.0;
double distanceMeters = 0.0;
final distanceCalculator = Distance();
for (int i = 0; i < points.length - 1; i++) {
distanceMeters += distanceCalculator(points[i], points[i + 1]);
}
return distanceMeters;
}
String formatDistance(double distanceMeters) {
return '(${(distanceMeters / 1609.34).toStringAsFixed(2)} Miles / ${(distanceMeters / 1000).toStringAsFixed(2)} Km)';
}
class PathTraceData { class PathTraceData {
final Uint8List pathData; final Uint8List pathData;
final Uint8List snrData; final Uint8List snrData;
@@ -50,7 +67,6 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
bool _isLoading = false; bool _isLoading = false;
bool _failed2Loaded = false; bool _failed2Loaded = false;
bool _hasData = false; bool _hasData = false;
bool _noLocationErr = false;
PathTraceData? _traceData; PathTraceData? _traceData;
List<LatLng> _points = <LatLng>[]; List<LatLng> _points = <LatLng>[];
List<Polyline> _polylines = []; List<Polyline> _polylines = [];
@@ -58,7 +74,7 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
double _initialZoom = 2.0; double _initialZoom = 2.0;
LatLngBounds? _bounds; LatLngBounds? _bounds;
ValueKey<String> _mapKey = const ValueKey('initial'); ValueKey<String> _mapKey = const ValueKey('initial');
double _pathDistance = 0.0; double _pathDistanceMeters = 0.0;
String _formatPathPrefixes(Uint8List pathBytes) { String _formatPathPrefixes(Uint8List pathBytes) {
return pathBytes return pathBytes
@@ -93,23 +109,11 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
return traceBytes; return traceBytes;
} }
double getPathDistance() {
double totalDistance = 0.0;
final distanceCalculator = Distance();
for (int i = 0; i < _points.length - 1; i++) {
totalDistance += distanceCalculator(_points[i], _points[i + 1]);
}
return totalDistance;
}
Future<void> _doPathTrace() async { Future<void> _doPathTrace() async {
if (mounted) { if (mounted) {
setState(() { setState(() {
_isLoading = true; _isLoading = true;
_failed2Loaded = false; _failed2Loaded = false;
_noLocationErr = false;
}); });
} }
@@ -160,6 +164,14 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
}); });
} }
if (code == respCodeErr) {
_timeoutTimer?.cancel();
if (!mounted) return;
setState(() {
_isLoading = false;
_failed2Loaded = true;
});
}
// Check if it's a binary response // Check if it's a binary response
if (frame.length > 8 && if (frame.length > 8 &&
code == pushCodeTraceData && code == pushCodeTraceData &&
@@ -215,8 +227,6 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
contact.latitude != null && contact.latitude != null &&
contact.longitude != null) { contact.longitude != null) {
_points.add(LatLng(contact.latitude!, contact.longitude!)); _points.add(LatLng(contact.latitude!, contact.longitude!));
} else {
_noLocationErr = true;
} }
} }
_polylines = _points.length > 1 _polylines = _points.length > 1
@@ -235,7 +245,7 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
_mapKey = ValueKey( _mapKey = ValueKey(
'${context.l10n.pathTrace_you},${_formatPathPrefixes(_traceData!.pathData)}', '${context.l10n.pathTrace_you},${_formatPathPrefixes(_traceData!.pathData)}',
); );
_pathDistance = getPathDistance(); _pathDistanceMeters = getPathDistanceMeters(_points);
}); });
} }
@@ -279,20 +289,7 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
top: false, top: false,
child: Stack( child: Stack(
children: [ children: [
if (_noLocationErr) if (!_hasData)
Center(
child: Card(
color: Colors.red,
child: Padding(
padding: EdgeInsets.all(12),
child: Text(
context.l10n.pathTrace_someHopsNoLocation,
style: TextStyle(color: Colors.white),
),
),
),
),
if (!_hasData && !_noLocationErr)
Center( Center(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -304,43 +301,11 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
], ],
), ),
), ),
if (_hasData && !_noLocationErr) if (_hasData) _buildMapPathTrace(context, tileCache),
FlutterMap(
key: _mapKey,
options: MapOptions(
initialCenter: _initialCenter!,
initialZoom: _initialZoom,
initialCameraFit: _bounds == null
? null
: CameraFit.bounds(
bounds: _bounds!,
padding: const EdgeInsets.all(64),
maxZoom: 16,
),
minZoom: 2.0,
maxZoom: 18.0,
),
children: [
TileLayer(
urlTemplate: kMapTileUrlTemplate,
tileProvider: tileCache.tileProvider,
userAgentPackageName:
MapTileCacheService.userAgentPackageName,
maxZoom: 19,
),
if (_polylines.isNotEmpty)
PolylineLayer(polylines: _polylines),
if (_traceData!.pathData.isNotEmpty)
MarkerLayer(
markers: _buildHopMarkers(_traceData!.pathData),
),
],
),
if (_points.isEmpty && if (_points.isEmpty &&
!_hasData && !_hasData &&
!_isLoading && !_isLoading &&
!_failed2Loaded && !_failed2Loaded)
!_noLocationErr)
Center( Center(
child: Card( child: Card(
color: Colors.white.withValues(alpha: 0.9), color: Colors.white.withValues(alpha: 0.9),
@@ -352,8 +317,7 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
), ),
), ),
), ),
if (_hasData && !_noLocationErr) if (_hasData) _buildLegendCard(context, _traceData!),
_buildLegendCard(context, _traceData!),
], ],
), ),
), ),
@@ -365,7 +329,8 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
List<Marker> _buildHopMarkers(List<int> pathData) { List<Marker> _buildHopMarkers(List<int> pathData) {
return [ return [
for (final hop in pathData) for (final hop in pathData)
if (_traceData!.pathContacts[hop]!.hasLocation) if (_traceData!.pathContacts[hop] != null &&
_traceData!.pathContacts[hop]!.hasLocation)
Marker( Marker(
point: LatLng( point: LatLng(
_traceData!.pathContacts[hop]!.latitude!, _traceData!.pathContacts[hop]!.latitude!,
@@ -453,7 +418,9 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
.toRadixString(16) .toRadixString(16)
.padLeft(2, '0') .padLeft(2, '0')
.toUpperCase(); .toUpperCase();
return contactName != null ? "$hex: $contactName" : hex; return contactName != null
? "$hex: $contactName"
: "$hex: ${context.l10n.channelPath_unknownRepeater}";
} }
} else { } else {
final contactName = final contactName =
@@ -462,7 +429,9 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
.toRadixString(16) .toRadixString(16)
.padLeft(2, '0') .padLeft(2, '0')
.toUpperCase(); .toUpperCase();
return contactName != null ? "$hex: $contactName" : hex; return contactName != null
? "$hex: $contactName"
: "$hex: ${context.l10n.channelPath_unknownRepeater}";
} }
} }
@@ -475,7 +444,9 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
.toRadixString(16) .toRadixString(16)
.padLeft(2, '0') .padLeft(2, '0')
.toUpperCase(); .toUpperCase();
return contactName != null ? "$hex: $contactName" : hex; return contactName != null
? "$hex: $contactName"
: "$hex: ${context.l10n.channelPath_unknownRepeater}";
} else { } else {
return context.l10n.pathTrace_you; return context.l10n.pathTrace_you;
} }
@@ -486,10 +457,46 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
.toRadixString(16) .toRadixString(16)
.padLeft(2, '0') .padLeft(2, '0')
.toUpperCase(); .toUpperCase();
return contactName != null ? "$hex: $contactName" : hex; return contactName != null
? "$hex: $contactName"
: "$hex: ${context.l10n.channelPath_unknownRepeater}";
} }
} }
Widget _buildMapPathTrace(
BuildContext context,
MapTileCacheService tileCache,
) {
return FlutterMap(
key: _mapKey,
options: MapOptions(
interactionOptions: InteractionOptions(flags: ~InteractiveFlag.rotate),
initialCenter: _initialCenter!,
initialZoom: _initialZoom,
initialCameraFit: _bounds == null
? null
: CameraFit.bounds(
bounds: _bounds!,
padding: const EdgeInsets.all(64),
maxZoom: 16,
),
minZoom: 2.0,
maxZoom: 18.0,
),
children: [
TileLayer(
urlTemplate: kMapTileUrlTemplate,
tileProvider: tileCache.tileProvider,
userAgentPackageName: MapTileCacheService.userAgentPackageName,
maxZoom: 19,
),
if (_polylines.isNotEmpty) PolylineLayer(polylines: _polylines),
if (_traceData!.pathData.isNotEmpty)
MarkerLayer(markers: _buildHopMarkers(_traceData!.pathData)),
],
);
}
Widget _buildLegendCard(BuildContext context, PathTraceData pathTraceData) { Widget _buildLegendCard(BuildContext context, PathTraceData pathTraceData) {
final l10n = context.l10n; final l10n = context.l10n;
final maxHeight = MediaQuery.of(context).size.height * 0.35; final maxHeight = MediaQuery.of(context).size.height * 0.35;
@@ -509,7 +516,7 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
Padding( Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Text( child: Text(
'${l10n.channelPath_repeaterHops} (${(_pathDistance / 1609.34).toStringAsFixed(2)} Miles / ${(_pathDistance / 1000).toStringAsFixed(2)} Km)', '${l10n.channelPath_repeaterHops} ${formatDistance(_pathDistanceMeters)}',
style: const TextStyle(fontWeight: FontWeight.w600), style: const TextStyle(fontWeight: FontWeight.w600),
), ),
), ),
@@ -523,7 +530,7 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
child: ListView.separated( child: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 4), padding: const EdgeInsets.symmetric(vertical: 4),
itemCount: pathTraceData.pathData.length + 1, itemCount: pathTraceData.pathData.length + 1,
separatorBuilder: (_, __) => const Divider(height: 1), separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Column( return Column(
children: [ children: [
+75 -7
View File
@@ -1,3 +1,6 @@
import 'dart:async';
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -18,6 +21,8 @@ class ScannerScreen extends StatefulWidget {
class _ScannerScreenState extends State<ScannerScreen> { class _ScannerScreenState extends State<ScannerScreen> {
bool _changedNavigation = false; bool _changedNavigation = false;
late final VoidCallback _connectionListener; late final VoidCallback _connectionListener;
BluetoothAdapterState _bluetoothState = BluetoothAdapterState.unknown;
late StreamSubscription<BluetoothAdapterState> _bluetoothStateSubscription;
@override @override
void initState() { void initState() {
@@ -39,12 +44,25 @@ class _ScannerScreenState extends State<ScannerScreen> {
}; };
connector.addListener(_connectionListener); connector.addListener(_connectionListener);
_bluetoothStateSubscription = FlutterBluePlus.adapterState.listen((state) {
if (mounted) {
setState(() {
_bluetoothState = state;
});
// Cancel scan if Bluetooth turns off while scanning
if (state != BluetoothAdapterState.on) {
unawaited(connector.stopScan());
}
}
});
} }
@override @override
void dispose() { void dispose() {
final connector = Provider.of<MeshCoreConnector>(context, listen: false); final connector = Provider.of<MeshCoreConnector>(context, listen: false);
connector.removeListener(_connectionListener); connector.removeListener(_connectionListener);
unawaited(_bluetoothStateSubscription.cancel());
super.dispose(); super.dispose();
} }
@@ -62,6 +80,10 @@ class _ScannerScreenState extends State<ScannerScreen> {
builder: (context, connector, child) { builder: (context, connector, child) {
return Column( return Column(
children: [ children: [
// Bluetooth off warning
if (_bluetoothState == BluetoothAdapterState.off)
_bluetoothOffWarning(context),
// Status bar // Status bar
_buildStatusBar(context, connector), _buildStatusBar(context, connector),
@@ -76,15 +98,18 @@ class _ScannerScreenState extends State<ScannerScreen> {
builder: (context, connector, child) { builder: (context, connector, child) {
final isScanning = final isScanning =
connector.state == MeshCoreConnectionState.scanning; connector.state == MeshCoreConnectionState.scanning;
final isBluetoothOff = _bluetoothState == BluetoothAdapterState.off;
return FloatingActionButton.extended( return FloatingActionButton.extended(
onPressed: () { onPressed: isBluetoothOff
if (isScanning) { ? null
connector.stopScan(); : () {
} else { if (isScanning) {
connector.startScan(); connector.stopScan();
} } else {
}, connector.startScan();
}
},
icon: isScanning icon: isScanning
? const SizedBox( ? const SizedBox(
width: 20, width: 20,
@@ -205,4 +230,47 @@ class _ScannerScreenState extends State<ScannerScreen> {
} }
} }
} }
Widget _bluetoothOffWarning(BuildContext context) {
final errorColor = Theme.of(context).colorScheme.error;
return Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
color: errorColor.withValues(alpha: 0.15),
child: Row(
children: [
Icon(Icons.bluetooth_disabled, size: 24, color: errorColor),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.l10n.scanner_bluetoothOff,
style: TextStyle(
color: errorColor,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
const SizedBox(height: 4),
Text(
context.l10n.scanner_bluetoothOffMessage,
style: TextStyle(
color: errorColor.withValues(alpha: 0.85),
fontSize: 12,
),
),
],
),
),
if (Platform.isAndroid)
TextButton(
onPressed: () => FlutterBluePlus.turnOn(),
child: Text(context.l10n.scanner_enableBluetooth),
),
],
),
);
}
} }
+53 -60
View File
@@ -490,8 +490,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
final latController = TextEditingController(); final latController = TextEditingController();
final lonController = TextEditingController(); final lonController = TextEditingController();
final intervalController = TextEditingController(); final intervalController = TextEditingController();
bool isLogging = connector.sparseLocationLogger?.isLogging() ?? false;
latController.text = connector.selfLatitude?.toStringAsFixed(6) ?? ''; latController.text = connector.selfLatitude?.toStringAsFixed(6) ?? '';
lonController.text = connector.selfLongitude?.toStringAsFixed(6) ?? ''; lonController.text = connector.selfLongitude?.toStringAsFixed(6) ?? '';
@@ -536,20 +534,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
signed: true, signed: true,
), ),
), ),
const SizedBox(height: 16),
FeatureToggleRow(
title: "GPS Logging",
subtitle: "Enable GPS logging on the device",
value: isLogging,
onChanged: (value) async {
setDialogState(() => isLogging = value);
if (value) {
await connector.sparseLocationLogger?.startLogging();
} else {
await connector.sparseLocationLogger?.stopLogging();
}
},
),
if (hasGPS) ...[ if (hasGPS) ...[
const SizedBox(height: 16), const SizedBox(height: 16),
TextField( TextField(
@@ -758,7 +742,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
); );
} }
_gpxExport( Future<void> _gpxExport(
GpxExport exporter, GpxExport exporter,
String name, String name,
String description, String description,
@@ -798,7 +782,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
} }
} }
_buildExportCard(MeshCoreConnector connector) { Widget _buildExportCard(MeshCoreConnector connector) {
final l10n = context.l10n; final l10n = context.l10n;
return Card( return Card(
child: Column( child: Column(
@@ -878,6 +862,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
LoRaSpreadingFactor _spreadingFactor = LoRaSpreadingFactor.sf7; LoRaSpreadingFactor _spreadingFactor = LoRaSpreadingFactor.sf7;
LoRaCodingRate _codingRate = LoRaCodingRate.cr4_5; LoRaCodingRate _codingRate = LoRaCodingRate.cr4_5;
final _txPowerController = TextEditingController(text: '20'); final _txPowerController = TextEditingController(text: '20');
bool _clientRepeat = false;
@override @override
void initState() { void initState() {
@@ -927,6 +912,8 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
if (widget.connector.currentTxPower != null) { if (widget.connector.currentTxPower != null) {
_txPowerController.text = widget.connector.currentTxPower.toString(); _txPowerController.text = widget.connector.currentTxPower.toString();
} }
_clientRepeat = widget.connector.clientRepeat ?? false;
} }
@override @override
@@ -976,9 +963,29 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
widget.connector.currentCr, widget.connector.currentCr,
); );
// if the client repeat isnt null then we know its supported
//otherwise we leave it out of the frame to avoid accidentally enabling
final knownRepeat = widget.connector.clientRepeat != null;
if (knownRepeat) {
const validRepeatFreqsKHz = {433000, 869000, 918000};
if (_clientRepeat && !validRepeatFreqsKHz.contains(freqHz)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.settings_clientRepeatFreqWarning)),
);
return;
}
}
try { try {
await widget.connector.sendFrame( await widget.connector.sendFrame(
buildSetRadioParamsFrame(freqHz, bwHz, sf, cr), buildSetRadioParamsFrame(
freqHz,
bwHz,
sf,
cr,
clientRepeat: knownRepeat ? _clientRepeat : null,
),
); );
await widget.connector.sendFrame(buildSetRadioTxPowerFrame(txPower)); await widget.connector.sendFrame(buildSetRadioTxPowerFrame(txPower));
await widget.connector.refreshDeviceInfo(); await widget.connector.refreshDeviceInfo();
@@ -1017,37 +1024,25 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( DropdownButtonFormField<int>(
l10n.settings_presets, decoration: InputDecoration(
style: const TextStyle(fontWeight: FontWeight.bold), labelText: l10n.settings_presets,
), border: const OutlineInputBorder(),
const SizedBox(height: 8), ),
Wrap( items: [
spacing: 8, for (var i = 0; i < RadioSettings.presets.length; i++)
children: [ DropdownMenuItem(
_PresetChip( value: i,
label: l10n.settings_preset915Mhz, child: Text(RadioSettings.presets[i].$1),
onTap: () => _applyPreset(RadioSettings.preset915MHz), ),
),
_PresetChip(
label: l10n.settings_preset868Mhz,
onTap: () => _applyPreset(RadioSettings.preset868MHz),
),
_PresetChip(
label: l10n.settings_preset433Mhz,
onTap: () => _applyPreset(RadioSettings.preset433MHz),
),
_PresetChip(
label: l10n.settings_longRange,
onTap: () => _applyPreset(RadioSettings.presetLongRange),
),
_PresetChip(
label: l10n.settings_fastSpeed,
onTap: () => _applyPreset(RadioSettings.presetFastSpeed),
),
], ],
onChanged: (index) {
if (index != null) {
_applyPreset(RadioSettings.presets[index].$2);
}
},
), ),
const SizedBox(height: 24), const SizedBox(height: 16),
TextField( TextField(
controller: _frequencyController, controller: _frequencyController,
decoration: InputDecoration( decoration: InputDecoration(
@@ -1119,6 +1114,16 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
), ),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
), ),
if (widget.connector.clientRepeat != null) ...[
const SizedBox(height: 16),
SwitchListTile(
title: Text(l10n.settings_clientRepeat),
subtitle: Text(l10n.settings_clientRepeatSubtitle),
value: _clientRepeat,
onChanged: (value) => setState(() => _clientRepeat = value),
contentPadding: EdgeInsets.zero,
),
],
], ],
), ),
), ),
@@ -1132,15 +1137,3 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
); );
} }
} }
class _PresetChip extends StatelessWidget {
final String label;
final VoidCallback onTap;
const _PresetChip({required this.label, required this.onTap});
@override
Widget build(BuildContext context) {
return ActionChip(label: Text(label), onPressed: onTap);
}
}
+5 -11
View File
@@ -1,4 +1,3 @@
import 'dart:isolate';
import 'dart:io'; import 'dart:io';
import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart';
@@ -15,18 +14,13 @@ class BackgroundService {
channelDescription: 'Keeps MeshCore running in the background.', channelDescription: 'Keeps MeshCore running in the background.',
channelImportance: NotificationChannelImportance.LOW, channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW, priority: NotificationPriority.LOW,
iconData: const NotificationIconData(
resType: ResourceType.mipmap,
resPrefix: ResourcePrefix.ic,
name: 'launcher',
),
), ),
iosNotificationOptions: const IOSNotificationOptions( iosNotificationOptions: const IOSNotificationOptions(
showNotification: false, showNotification: false,
playSound: false, playSound: false,
), ),
foregroundTaskOptions: const ForegroundTaskOptions( foregroundTaskOptions: ForegroundTaskOptions(
interval: 5000, eventAction: ForegroundTaskEventAction.repeat(5000),
autoRunOnBoot: false, autoRunOnBoot: false,
allowWifiLock: false, allowWifiLock: false,
), ),
@@ -63,13 +57,13 @@ void startCallback() {
class _MeshCoreTaskHandler extends TaskHandler { class _MeshCoreTaskHandler extends TaskHandler {
@override @override
void onStart(DateTime timestamp, SendPort? sendPort) {} Future<void> onStart(DateTime timestamp, TaskStarter starter) async {}
@override @override
void onRepeatEvent(DateTime timestamp, SendPort? sendPort) {} void onRepeatEvent(DateTime timestamp) {}
@override @override
void onDestroy(DateTime timestamp, SendPort? sendPort) {} Future<void> onDestroy(DateTime timestamp, bool isTimeout) async {}
@override @override
void onNotificationButtonPressed(String id) {} void onNotificationButtonPressed(String id) {}
+18 -18
View File
@@ -67,7 +67,7 @@ class NotificationService {
try { try {
await _notifications.initialize( await _notifications.initialize(
initSettings, settings: initSettings,
onDidReceiveNotificationResponse: _onNotificationTapped, onDidReceiveNotificationResponse: _onNotificationTapped,
); );
_isInitialized = true; _isInitialized = true;
@@ -149,10 +149,10 @@ class NotificationService {
); );
await _notifications.show( await _notifications.show(
contactId?.hashCode ?? 0, id: contactId?.hashCode ?? 0,
contactName, title: contactName,
message, body: message,
notificationDetails, notificationDetails: notificationDetails,
payload: 'message:$contactId', payload: 'message:$contactId',
); );
} }
@@ -194,10 +194,10 @@ class NotificationService {
); );
await _notifications.show( await _notifications.show(
contactId?.hashCode ?? DateTime.now().millisecondsSinceEpoch, id: contactId?.hashCode ?? DateTime.now().millisecondsSinceEpoch,
_l10n.notification_newTypeDiscovered(contactType), title: _l10n.notification_newTypeDiscovered(contactType),
contactName, body: contactName,
notificationDetails, notificationDetails: notificationDetails,
payload: 'advert:$contactId', payload: 'advert:$contactId',
); );
} }
@@ -248,10 +248,10 @@ class NotificationService {
: preview; : preview;
await _notifications.show( await _notifications.show(
channelIndex?.hashCode ?? DateTime.now().millisecondsSinceEpoch, id: channelIndex?.hashCode ?? DateTime.now().millisecondsSinceEpoch,
channelName, title: channelName,
body, body: body,
notificationDetails, notificationDetails: notificationDetails,
payload: 'channel:$channelIndex', payload: 'channel:$channelIndex',
); );
} }
@@ -285,7 +285,7 @@ class NotificationService {
} }
Future<void> cancel(int id) async { Future<void> cancel(int id) async {
await _notifications.cancel(id); await _notifications.cancel(id: id);
} }
// //
@@ -469,10 +469,10 @@ class NotificationService {
const notificationDetails = NotificationDetails(android: androidDetails); const notificationDetails = NotificationDetails(android: androidDetails);
await _notifications.show( await _notifications.show(
'batch_summary'.hashCode, id: 'batch_summary'.hashCode,
_l10n.notification_activityTitle, title: _l10n.notification_activityTitle,
parts.join(', '), body: parts.join(', '),
notificationDetails, notificationDetails: notificationDetails,
payload: 'batch', payload: 'batch',
); );
} }
-244
View File
@@ -1,244 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/widgets.dart';
import 'package:geolocator/geolocator.dart';
import 'package:gpx/gpx.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:share_plus/share_plus.dart';
class SparseLocationLogger {
static const double distanceThresholdMiles = 0.25;
static const double distanceThresholdMeters =
distanceThresholdMiles * 1609.34;
static const double headingChangeThresholdDeg = 35.0;
static const double minSpeedForTurnKmh = 8.0;
static const double minTime = 120.0; // seconds
Position? _lastLoggedPosition;
double? _lastHeading;
DateTime? _lastLoggedTime;
StreamSubscription<Position>? _positionStream;
Timer? _timer;
Function(Position position)? _onNewLogPoint;
// GPX structures
final Gpx _gpx = Gpx();
Trkseg _currentSegment = Trkseg(); // one segment for the whole session
File? _gpxFile;
bool _isInitialized = false;
void initialize(Function(Position position) onNewLogPoint) {
_onNewLogPoint = onNewLogPoint;
}
Future<bool> getPremissons() async {
// Permissions & service check (same as before)
var status = await Permission.location.request();
if (!status.isGranted) {
debugPrint('Location permission denied');
return false;
}
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
debugPrint('Location services disabled');
return false;
}
return true;
}
Future<void> startLogging() async {
if (!await getPremissons()) {
return;
}
// Prepare files
final directory = await getApplicationDocumentsDirectory();
final timestamp = DateTime.now()
.toIso8601String()
.replaceAll(':', '-')
.split('.')
.first;
_gpxFile = File('${directory.path}/track_$timestamp.gpx');
// Init GPX metadata
_gpx.metadata = Metadata(
name: 'Sparse Track ${DateTime.now().toString().split(' ').first}',
desc: 'Sparse GPS log: ~every 1.5 mi or significant turns',
time: DateTime.now(),
);
// Add one track with one segment
final track = Trk(name: 'Main Track');
_currentSegment = Trkseg();
track.trksegs.add(_currentSegment);
_gpx.trks.add(track);
_isInitialized = true;
// Start location stream
_positionStream = Geolocator.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 152, // meters (~0.16 mi) - helps battery
),
).listen(_onPositionReceived);
// Also poll via timer as fallback
_timer = Timer.periodic(Duration(seconds: (minTime / 2).toInt()), (
_,
) async {
final position = await Geolocator.getCurrentPosition();
await _onPositionReceived(position);
});
_lastLoggedPosition = null;
_lastHeading = null;
_lastLoggedTime = null;
debugPrint('Sparse GPX logging started → ${_gpxFile?.path}');
}
Future<void> stopLogging() async {
await _positionStream?.cancel();
_positionStream = null;
_timer?.cancel();
_timer = null;
if (_isInitialized && _currentSegment.trkpts.isNotEmpty) {
// Write GPX file on stop
final xmlString = GpxWriter().asString(_gpx, pretty: true);
await _gpxFile?.writeAsString(xmlString);
await SharePlus.instance.share(
ShareParams(
text: 'Sparse GPS track',
subject: 'Sparse GPS track',
files: [XFile(_gpxFile?.path ?? '')],
),
);
await _gpxFile?.delete();
}
debugPrint('Logging stopped');
}
Future<void> updateMyLocation() async {
if (!await getPremissons()) {
return;
}
try {
final position = await Geolocator.getCurrentPosition();
_onNewLogPoint?.call(position);
} catch (e) {
debugPrint('Error updating location: $e');
}
}
Future<void> _onPositionReceived(Position position) async {
final now = DateTime.now();
final speedKmh = position.speed * 3.6;
final heading = position.heading;
bool shouldLog = false;
String reason = '';
if (_lastLoggedPosition == null) {
shouldLog = true;
reason = 'start';
} else {
final distanceMeters = Geolocator.distanceBetween(
_lastLoggedPosition!.latitude,
_lastLoggedPosition!.longitude,
position.latitude,
position.longitude,
);
if (distanceMeters >= distanceThresholdMeters) {
shouldLog = true;
reason =
'distance (${(distanceMeters / 1609.34).toStringAsFixed(2)} mi)';
} else if (speedKmh > minSpeedForTurnKmh && _lastHeading != null) {
double delta = (heading - _lastHeading!).abs();
delta = math.min(delta, 360 - delta);
if (delta > headingChangeThresholdDeg) {
shouldLog = true;
reason = 'turn (${delta.toStringAsFixed(1)}°)';
}
} else if (_lastLoggedTime != null) {
final elapsed = now.difference(_lastLoggedTime!).inSeconds;
if (elapsed >= minTime && distanceMeters >= distanceThresholdMeters) {
shouldLog = true;
reason = 'time (${elapsed}s)';
}
}
}
if (shouldLog) {
// Create GPX Waypoint (trkpt)
final pt = Wpt(
lat: position.latitude,
lon: position.longitude,
ele: position.altitude, // if available
time: now,
extensions: {
"course": ?heading.isFinite ? heading : null,
"speed": ?speedKmh > 0 ? speedKmh / 3.6 : null, // GPX speed in m/s
},
// You can add hdop, vdop, etc. from position if desired
);
_currentSegment.trkpts.add(pt);
_onNewLogPoint?.call(position);
debugPrint('Logged point: ${pt.lat}, ${pt.lon} ($reason)');
_lastLoggedPosition = position;
_lastHeading = heading;
_lastLoggedTime = now;
} else {
debugPrint('Skipped point: ${position.latitude}, ${position.longitude}');
}
}
Position snapToGridCenter({
required Position position,
required double cellSizeMeters,
}) {
Position snappedPosition = position;
// Snap latitude
final latFloor =
(position.latitude / cellSizeMeters).floor() * cellSizeMeters;
final snappedLat = latFloor + (cellSizeMeters / 2);
// Snap longitude
final lonFloor =
(position.longitude / cellSizeMeters).floor() * cellSizeMeters;
final snappedLon = lonFloor + (cellSizeMeters / 2);
snappedPosition = Position(
latitude: snappedLat,
longitude: snappedLon,
altitude: position.altitude,
accuracy: position.accuracy,
heading: position.heading,
speed: position.speed,
speedAccuracy: position.speedAccuracy,
altitudeAccuracy: position.altitudeAccuracy,
headingAccuracy: position.headingAccuracy,
timestamp: position.timestamp,
);
return snappedPosition;
}
Future<String> getGpxFilePath() async => _gpxFile?.path ?? 'Not started';
bool isLogging() => _positionStream != null;
int getPointCount() => _currentSegment.trkpts.length;
}
+1 -1
View File
@@ -156,7 +156,7 @@ class _QrScannerWidgetState extends State<QrScannerWidget>
MobileScanner( MobileScanner(
controller: _controller, controller: _controller,
onDetect: _handleDetection, onDetect: _handleDetection,
errorBuilder: (context, error, child) { errorBuilder: (context, error) {
return _buildErrorWidget(context, error); return _buildErrorWidget(context, error);
}, },
), ),
@@ -7,7 +7,6 @@ import Foundation
import flutter_blue_plus_darwin import flutter_blue_plus_darwin
import flutter_local_notifications import flutter_local_notifications
import geolocator_apple
import mobile_scanner import mobile_scanner
import package_info_plus import package_info_plus
import share_plus import share_plus
@@ -19,7 +18,6 @@ import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterBluePlusPlugin.register(with: registry.registrar(forPlugin: "FlutterBluePlusPlugin")) FlutterBluePlusPlugin.register(with: registry.registrar(forPlugin: "FlutterBluePlusPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
+58 -178
View File
@@ -153,14 +153,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
dart_polylabel2:
dependency: transitive
description:
name: dart_polylabel2
sha256: "7eeab15ce72894e4bdba6a8765712231fc81be0bd95247de4ad9966abc57adc6"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
dbus: dbus:
dependency: transitive dependency: transitive
description: description:
name: dbus name: dbus
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.11" version: "0.7.12"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@@ -173,10 +181,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.5" version: "2.2.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@@ -202,10 +210,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_blue_plus name: flutter_blue_plus
sha256: "399b3dbc15562ef59749f04e43a99ccbb91540022380d5f269aff3c2787534e4" sha256: "88a65ead7dea67ddcc03e6ca846163c6b6cc09a2dcebdb8bb601fcd654ea9382"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.1.1"
flutter_blue_plus_android: flutter_blue_plus_android:
dependency: transitive dependency: transitive
description: description:
@@ -218,10 +226,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_blue_plus_darwin name: flutter_blue_plus_darwin
sha256: d160a8128e3a016fa58dd65ab6dac05cbc73e0fa799a1f24211d041641ed63ba sha256: "52b155d868e17c1c8ad85520a0912d447d92aedccb5a5e234d3edc98ebd1307a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.0" version: "8.1.1"
flutter_blue_plus_linux: flutter_blue_plus_linux:
dependency: transitive dependency: transitive
description: description:
@@ -250,10 +258,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_blue_plus_winrt name: flutter_blue_plus_winrt
sha256: "34be2d8e23d5881b46accebb0e71025f7d52869d72ea98b5082c20764e06aa80" sha256: ed894f0ab341f4cece8fa33edc381d46424a7c5bfd0e841d933d0f8c34c86521
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.0.16" version: "0.0.18"
flutter_cache_manager: flutter_cache_manager:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -266,18 +274,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_foreground_task name: flutter_foreground_task
sha256: "6cf10a27f5e344cd2ecad0752d3a5f4ec32846d82fda8753b3fe2480ebb832a3" sha256: "48ea45056155a99fb30b15f14f4039a044d925bc85f381ed0b2d3b00a60b99de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.5.0" version: "9.2.0"
flutter_launcher_icons: flutter_launcher_icons:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_launcher_icons name: flutter_launcher_icons
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.13.1" version: "0.14.4"
flutter_linkify: flutter_linkify:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -290,34 +298,42 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "6.0.0"
flutter_local_notifications: flutter_local_notifications:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_local_notifications name: flutter_local_notifications
sha256: ef41ae901e7529e52934feba19ed82827b11baa67336829564aeab3129460610 sha256: "2b50e938a275e1ad77352d6a25e25770f4130baa61eaf02de7a9a884680954ad"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "18.0.1" version: "20.1.0"
flutter_local_notifications_linux: flutter_local_notifications_linux:
dependency: transitive dependency: transitive
description: description:
name: flutter_local_notifications_linux name: flutter_local_notifications_linux
sha256: "8f685642876742c941b29c32030f6f4f6dacd0e4eaecb3efbb187d6a3812ca01" sha256: dce0116868cedd2cdf768af0365fc37ff1cbef7c02c4f51d0587482e625868d0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "7.0.0"
flutter_local_notifications_platform_interface: flutter_local_notifications_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: flutter_local_notifications_platform_interface name: flutter_local_notifications_platform_interface
sha256: "6c5b83c86bf819cdb177a9247a3722067dd8cc6313827ce7c77a4b238a26fd52" sha256: "23de31678a48c084169d7ae95866df9de5c9d2a44be3e5915a2ff067aeeba899"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.0.0" version: "10.0.0"
flutter_local_notifications_windows:
dependency: transitive
description:
name: flutter_local_notifications_windows
sha256: e97a1a3016512437d9c0b12fae7d1491c3c7b9aa7f03a69b974308840656b02a
url: "https://pub.dev"
source: hosted
version: "2.0.1"
flutter_localizations: flutter_localizations:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@@ -327,10 +343,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_map name: flutter_map
sha256: "2ecb34619a4be19df6f40c2f8dce1591675b4eff7a6857bd8f533706977385da" sha256: "391e7dc95cc3f5190748210a69d4cfeb5d8f84dcdfa9c3235d0a9d7742ccb3f8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.2" version: "8.2.2"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -341,70 +357,6 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
geoclue:
dependency: transitive
description:
name: geoclue
sha256: c2a998c77474fc57aa00c6baa2928e58f4b267649057a1c76738656e9dbd2a7f
url: "https://pub.dev"
source: hosted
version: "0.1.1"
geolocator:
dependency: "direct main"
description:
name: geolocator
sha256: "79939537046c9025be47ec645f35c8090ecadb6fe98eba146a0d25e8c1357516"
url: "https://pub.dev"
source: hosted
version: "14.0.2"
geolocator_android:
dependency: transitive
description:
name: geolocator_android
sha256: "179c3cb66dfa674fc9ccbf2be872a02658724d1c067634e2c427cf6df7df901a"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
geolocator_apple:
dependency: transitive
description:
name: geolocator_apple
sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22
url: "https://pub.dev"
source: hosted
version: "2.3.13"
geolocator_linux:
dependency: transitive
description:
name: geolocator_linux
sha256: c4e966f0a7a87e70049eac7a2617f9e16fd4c585a26e4330bdfc3a71e6a721f3
url: "https://pub.dev"
source: hosted
version: "0.2.3"
geolocator_platform_interface:
dependency: transitive
description:
name: geolocator_platform_interface
sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67"
url: "https://pub.dev"
source: hosted
version: "4.2.6"
geolocator_web:
dependency: transitive
description:
name: geolocator_web
sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172
url: "https://pub.dev"
source: hosted
version: "4.1.3"
geolocator_windows:
dependency: transitive
description:
name: geolocator_windows
sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6"
url: "https://pub.dev"
source: hosted
version: "0.2.5"
glob: glob:
dependency: transitive dependency: transitive
description: description:
@@ -421,22 +373,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
gsettings:
dependency: transitive
description:
name: gsettings
sha256: "1b0ce661f5436d2db1e51f3c4295a49849f03d304003a7ba177d01e3a858249c"
url: "https://pub.dev"
source: hosted
version: "0.2.8"
hooks: hooks:
dependency: transitive dependency: transitive
description: description:
name: hooks name: hooks
sha256: "5d309c86e7ce34cd8e37aa71cb30cb652d3829b900ab145e4d9da564b31d59f7" sha256: "7a08a0d684cb3b8fb604b78455d5d352f502b68079f7b80b831c62220ab0a4f6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -469,14 +413,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.20.2" version: "0.20.2"
js:
dependency: transitive
description:
name: js
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
@@ -529,10 +465,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.1" version: "6.1.0"
lists: lists:
dependency: transitive dependency: transitive
description: description:
@@ -601,10 +537,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: mobile_scanner name: mobile_scanner
sha256: "0b466a0a8a211b366c2e87f3345715faef9b6011c7147556ad22f37de6ba3173" sha256: c6184bf2913dd66be244108c9c27ca04b01caf726321c44b0e7a7a1e32d41044
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.11" version: "7.1.4"
native_toolchain_c: native_toolchain_c:
dependency: transitive dependency: transitive
description: description:
@@ -625,10 +561,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: objective_c name: objective_c
sha256: "983c7fa1501f6dcc0cb7af4e42072e9993cb28d73604d25ebf4dab08165d997e" sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.2.5" version: "9.3.0"
octo_image: octo_image:
dependency: transitive dependency: transitive
description: description:
@@ -641,10 +577,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.3.1" version: "9.0.0"
package_info_plus_platform_interface: package_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -709,54 +645,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
url: "https://pub.dev"
source: hosted
version: "12.0.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
url: "https://pub.dev"
source: hosted
version: "13.0.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
url: "https://pub.dev"
source: hosted
version: "9.4.7"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
url: "https://pub.dev"
source: hosted
version: "0.1.3+5"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
url: "https://pub.dev"
source: hosted
version: "4.3.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
petitparser: petitparser:
dependency: transitive dependency: transitive
description: description:
@@ -785,18 +673,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: pointycastle name: pointycastle
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.9.1" version: "4.0.0"
polylabel:
dependency: transitive
description:
name: polylabel
sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
posix: posix:
dependency: transitive dependency: transitive
description: description:
@@ -942,10 +822,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.1" version: "1.10.2"
sqflite: sqflite:
dependency: transitive dependency: transitive
description: description:
@@ -1078,10 +958,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.6" version: "6.4.1"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
@@ -1150,10 +1030,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: wakelock_plus name: wakelock_plus
sha256: "61713aa82b7f85c21c9f4cd0a148abd75f38a74ec645fcb1e446f882c82fd09b" sha256: "9296d40c9adbedaba95d1e704f4e0b434be446e2792948d0e4aa977048104228"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.3" version: "1.4.0"
wakelock_plus_platform_interface: wakelock_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
+9 -11
View File
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 6.0.0+1 version: 6.0.0+7
environment: environment:
sdk: ^3.9.2 sdk: ^3.9.2
@@ -41,27 +41,25 @@ dependencies:
provider: ^6.1.5+1 provider: ^6.1.5+1
shared_preferences: ^2.2.2 shared_preferences: ^2.2.2
uuid: ^4.3.3 uuid: ^4.3.3
flutter_map: ^7.0.2 flutter_map: ^8.2.2
latlong2: ^0.9.1 latlong2: ^0.9.1
flutter_local_notifications: ^18.0.1 flutter_local_notifications: ^20.1.0
crypto: ^3.0.3 crypto: ^3.0.3
pointycastle: ^3.7.4 pointycastle: ^4.0.0
http: ^1.2.0 http: ^1.2.0
cached_network_image: ^3.4.1 cached_network_image: ^3.4.1
flutter_cache_manager: ^3.4.1 flutter_cache_manager: ^3.4.1
flutter_foreground_task: ^6.1.2 flutter_foreground_task: ^9.2.0
wakelock_plus: ^1.2.8 wakelock_plus: ^1.2.8
characters: ^1.4.0 characters: ^1.4.0
package_info_plus: ^8.0.0 package_info_plus: ^9.0.0
mobile_scanner: ^6.0.0 # QR/barcode scanning mobile_scanner: ^7.1.4 # QR/barcode scanning
qr_flutter: ^4.1.0 # QR code generation qr_flutter: ^4.1.0 # QR code generation
url_launcher: ^6.3.0 # Launch URLs in system browser url_launcher: ^6.3.0 # Launch URLs in system browser
flutter_linkify: ^6.0.0 # Auto-detect and linkify URLs in text flutter_linkify: ^6.0.0 # Auto-detect and linkify URLs in text
gpx: ^2.3.0 gpx: ^2.3.0
path_provider: ^2.1.5 path_provider: ^2.1.5
share_plus: ^12.0.1 share_plus: ^12.0.1
geolocator: ^14.0.2
permission_handler: ^12.0.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@@ -72,8 +70,8 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^5.0.0 flutter_lints: ^6.0.0
flutter_launcher_icons: ^0.13.1 flutter_launcher_icons: ^0.14.4
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
@@ -7,18 +7,12 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <flutter_blue_plus_winrt/flutter_blue_plus_plugin.h> #include <flutter_blue_plus_winrt/flutter_blue_plus_plugin.h>
#include <geolocator_windows/geolocator_windows.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <share_plus/share_plus_windows_plugin_c_api.h> #include <share_plus/share_plus_windows_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FlutterBluePlusPluginRegisterWithRegistrar( FlutterBluePlusPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterBluePlusPlugin")); registry->GetRegistrarForPlugin("FlutterBluePlusPlugin"));
GeolocatorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GeolocatorWindows"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
SharePlusWindowsPluginCApiRegisterWithRegistrar( SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
+1 -2
View File
@@ -4,13 +4,12 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
flutter_blue_plus_winrt flutter_blue_plus_winrt
geolocator_windows
permission_handler_windows
share_plus share_plus
url_launcher_windows url_launcher_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
flutter_local_notifications_windows
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)