mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-12 03:27:06 +10:00
Add UI for setting repeater identity keys
This adds a simple UI in repeater management settings for remotely setting a repeater's private key. A key can be pasted from an external key generator, or a random one can be generated here, optionally with a specified prefix. If a prefix is specified, searching is done in 30ms batches in order to keep the UI responsive and show the progress indicator animation smoothly. Searches can be interrupted. An estimation of search length is given as expected number of generated key pairs. (A future improvement would be to observe keys per second performance and give time estimates based on that.) When it generates a new private key on your behalf, it can tell you what the corresponding public key will be. Unfortunately, if you paste one in from another source, it can't compute the corresponding public key. This is because the standard Dart crypto library doesn't provide that capability, nor does it give access to the elliptic curve functions it implements so we could do it ourselves. Our only recourse would be to copy the source for all those things, and I didn't think it was worth it. This will not check the validity of a pasted key, but the remote repeater will. It does limit it to the correct length and hexadecimal charset. Prefixes are limited to 4 characters. There's no technical reason for this, but users are unlikely to want more, and I think it would just be a bad experience to allow more and spin for a very long time. If someone really wants a longer one, they can use an external generator like they do now. Possible TODO: rewrite background processing using isolates. Closes #142.
This commit is contained in:
+21
-1
@@ -1409,6 +1409,26 @@
|
|||||||
"repeater_advancedSettingsSubtitle": "Tuning knobs for experienced operators",
|
"repeater_advancedSettingsSubtitle": "Tuning knobs for experienced operators",
|
||||||
"repeater_pathHashMode": "Path hash mode",
|
"repeater_pathHashMode": "Path hash mode",
|
||||||
"repeater_pathHashModeHelper": "Bytes used to encode this repeater's ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.",
|
"repeater_pathHashModeHelper": "Bytes used to encode this repeater's ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.",
|
||||||
|
"repeater_keySettings": "Change Identity Keys",
|
||||||
|
"repeater_keySettingsSubtitle": "Change the public/private keypair",
|
||||||
|
"repeater_prvKey": "Private key",
|
||||||
|
"repeater_prvKeyHelper": "A new private key for the repeater, a 128-character hex string.",
|
||||||
|
"repeater_generatePrvKey": "Generate a random keypair",
|
||||||
|
"repeater_stopGeneratingPrvKey": "Interrupt search for keypair",
|
||||||
|
"repeater_pubKey": "Public key",
|
||||||
|
"repeater_pubKeyHelper": "This is the public key that goes with the generated private key. You can't set this directly.",
|
||||||
|
"repeater_pubKeyPrefix": "Desired prefix",
|
||||||
|
"repeater_pubKeyPrefixHelper": "Find a public key that starts with these hex digits. Expected tries needed: {tries}.",
|
||||||
|
"@repeater_pubKeyPrefixHelper": {
|
||||||
|
"placeholders": {
|
||||||
|
"tries": {
|
||||||
|
"type": "int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"repeater_txDelay": "Flood TX delay",
|
"repeater_txDelay": "Flood TX delay",
|
||||||
"repeater_txDelayHelper": "Retransmit spacing for flood traffic, as a multiplier of the packet's airtime (0-2, default 0.5). Higher = fewer collisions but slower delivery.",
|
"repeater_txDelayHelper": "Retransmit spacing for flood traffic, as a multiplier of the packet's airtime (0-2, default 0.5). Higher = fewer collisions but slower delivery.",
|
||||||
"repeater_directTxDelay": "Direct TX delay",
|
"repeater_directTxDelay": "Direct TX delay",
|
||||||
@@ -1589,7 +1609,7 @@
|
|||||||
"repeater_cliHelpPowersavingOnOff": "Enables or disables powersaving mode (where supported).",
|
"repeater_cliHelpPowersavingOnOff": "Enables or disables powersaving mode (where supported).",
|
||||||
"repeater_cliHelpErase": "(Serial only) Formats the device file system. Wipes all settings and contacts.",
|
"repeater_cliHelpErase": "(Serial only) Formats the device file system. Wipes all settings and contacts.",
|
||||||
"repeater_cliHelpSetDutyCycle": "Sets the maximum allowed transmit duty cycle as a percentage (1-100). Internally adjusts the airtime factor.",
|
"repeater_cliHelpSetDutyCycle": "Sets the maximum allowed transmit duty cycle as a percentage (1-100). Internally adjusts the airtime factor.",
|
||||||
"repeater_cliHelpSetPrvKey": "(Serial only) Replaces the device identity private key. Reboot required to apply. Generates a new public key.",
|
"repeater_cliHelpSetPrvKey": "Replaces the device identity private key. Reboot required to apply. Generates a new public key.",
|
||||||
"repeater_cliHelpSetRadioRxGain": "(SX126x only) Toggles boosted RX gain for improved sensitivity at higher current draw.",
|
"repeater_cliHelpSetRadioRxGain": "(SX126x only) Toggles boosted RX gain for improved sensitivity at higher current draw.",
|
||||||
"repeater_cliHelpSetOwnerInfo": "Sets the owner contact info string included in adverts. Use '|' for newlines.",
|
"repeater_cliHelpSetOwnerInfo": "Sets the owner contact info string included in adverts. Use '|' for newlines.",
|
||||||
"repeater_cliHelpSetPathHashMode": "Sets the path-hash mode. 0 = legacy, 1 = standard, 2 = strict. Affects how routing paths are matched.",
|
"repeater_cliHelpSetPathHashMode": "Sets the path-hash mode. 0 = legacy, 1 = standard, 2 = strict. Affects how routing paths are matched.",
|
||||||
|
|||||||
@@ -4748,6 +4748,66 @@ abstract class AppLocalizations {
|
|||||||
/// **'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.'**
|
/// **'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.'**
|
||||||
String get repeater_pathHashModeHelper;
|
String get repeater_pathHashModeHelper;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_keySettings.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Change Identity Keys'**
|
||||||
|
String get repeater_keySettings;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_keySettingsSubtitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Change the public/private keypair'**
|
||||||
|
String get repeater_keySettingsSubtitle;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_prvKey.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Private key'**
|
||||||
|
String get repeater_prvKey;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_prvKeyHelper.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'A new private key for the repeater, a 128-character hex string.'**
|
||||||
|
String get repeater_prvKeyHelper;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_generatePrvKey.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Generate a random keypair'**
|
||||||
|
String get repeater_generatePrvKey;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_stopGeneratingPrvKey.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Interrupt search for keypair'**
|
||||||
|
String get repeater_stopGeneratingPrvKey;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_pubKey.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Public key'**
|
||||||
|
String get repeater_pubKey;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_pubKeyHelper.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'This is the public key that goes with the generated private key. You can\'t set this directly.'**
|
||||||
|
String get repeater_pubKeyHelper;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_pubKeyPrefix.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Desired prefix'**
|
||||||
|
String get repeater_pubKeyPrefix;
|
||||||
|
|
||||||
|
/// No description provided for @repeater_pubKeyPrefixHelper.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Find a public key that starts with these hex digits. Expected tries needed: {tries}.'**
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries);
|
||||||
|
|
||||||
/// No description provided for @repeater_txDelay.
|
/// No description provided for @repeater_txDelay.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -5519,7 +5579,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @repeater_cliHelpSetPrvKey.
|
/// No description provided for @repeater_cliHelpSetPrvKey.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'(Serial only) Replaces the device identity private key. Reboot required to apply. Generates a new public key.'**
|
/// **'Replaces the device identity private key. Reboot required to apply. Generates a new public key.'**
|
||||||
String get repeater_cliHelpSetPrvKey;
|
String get repeater_cliHelpSetPrvKey;
|
||||||
|
|
||||||
/// No description provided for @repeater_cliHelpSetRadioRxGain.
|
/// No description provided for @repeater_cliHelpSetRadioRxGain.
|
||||||
|
|||||||
@@ -2641,6 +2641,41 @@ class AppLocalizationsBg extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Забавяне на Flood TX';
|
String get repeater_txDelay => 'Забавяне на Flood TX';
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelayHelper =>
|
String get repeater_txDelayHelper =>
|
||||||
|
|||||||
@@ -2635,6 +2635,41 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Bytes, die zur Kodierung der ID dieses Repeaters in Flood-Pfad-/Schleifen-Erkennung-Tags verwendet werden. 0 = 1 Byte (256 IDs, bis zu 64 Hops), 1 = 2 Bytes (65.000 IDs, bis zu 32 Hops), 2 = 3 Bytes (16 Millionen IDs, bis zu 21 Hops). Firmware-Versionen 1.13 und älter verwenden mehrstellige Pfade – ab Version 1.14+ wird nur ein Pfad erstellt, sobald das Netzwerk aktiv ist.';
|
'Bytes, die zur Kodierung der ID dieses Repeaters in Flood-Pfad-/Schleifen-Erkennung-Tags verwendet werden. 0 = 1 Byte (256 IDs, bis zu 64 Hops), 1 = 2 Bytes (65.000 IDs, bis zu 32 Hops), 2 = 3 Bytes (16 Millionen IDs, bis zu 21 Hops). Firmware-Versionen 1.13 und älter verwenden mehrstellige Pfade – ab Version 1.14+ wird nur ein Pfad erstellt, sobald das Netzwerk aktiv ist.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Flood-TX-Verzögerung';
|
String get repeater_txDelay => 'Flood-TX-Verzögerung';
|
||||||
|
|
||||||
|
|||||||
@@ -2589,6 +2589,41 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.';
|
'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Flood TX delay';
|
String get repeater_txDelay => 'Flood TX delay';
|
||||||
|
|
||||||
@@ -3059,7 +3094,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_cliHelpSetPrvKey =>
|
String get repeater_cliHelpSetPrvKey =>
|
||||||
'(Serial only) Replaces the device identity private key. Reboot required to apply. Generates a new public key.';
|
'Replaces the device identity private key. Reboot required to apply. Generates a new public key.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_cliHelpSetRadioRxGain =>
|
String get repeater_cliHelpSetRadioRxGain =>
|
||||||
|
|||||||
@@ -2634,6 +2634,41 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Bytes utilizados para codificar el ID de este repetidor en las etiquetas de ruta/detección de bucles. 0=1 byte (256 IDs, hasta 64 saltos), 1=2 bytes (65.000 IDs, hasta 32 saltos), 2=3 bytes (16 millones de IDs, hasta 21 saltos). Las versiones 1.13 y anteriores de firmware eliminan rutas de múltiples bytes; solo se detectan una vez que la red está activa en la versión 1.14 o posterior.';
|
'Bytes utilizados para codificar el ID de este repetidor en las etiquetas de ruta/detección de bucles. 0=1 byte (256 IDs, hasta 64 saltos), 1=2 bytes (65.000 IDs, hasta 32 saltos), 2=3 bytes (16 millones de IDs, hasta 21 saltos). Las versiones 1.13 y anteriores de firmware eliminan rutas de múltiples bytes; solo se detectan una vez que la red está activa en la versión 1.14 o posterior.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Retraso TX por inundación';
|
String get repeater_txDelay => 'Retraso TX por inundación';
|
||||||
|
|
||||||
|
|||||||
@@ -2645,6 +2645,41 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Octets utilisés pour encoder l\'ID de ce routeur dans les balises de détection de flux/boucles. 0 = 1 octet (256 ID, jusqu\'à 64 sauts), 1 = 2 octets (65 000 ID, jusqu\'à 32 sauts), 2 = 3 octets (16 millions d\'ID, jusqu\'à 21 sauts). Les versions 1.13 et antérieures utilisent des chemins multi-octets ; à partir de la version 1.14, cela n\'est plus nécessaire.';
|
'Octets utilisés pour encoder l\'ID de ce routeur dans les balises de détection de flux/boucles. 0 = 1 octet (256 ID, jusqu\'à 64 sauts), 1 = 2 octets (65 000 ID, jusqu\'à 32 sauts), 2 = 3 octets (16 millions d\'ID, jusqu\'à 21 sauts). Les versions 1.13 et antérieures utilisent des chemins multi-octets ; à partir de la version 1.14, cela n\'est plus nécessaire.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Délai de transmission en flood';
|
String get repeater_txDelay => 'Délai de transmission en flood';
|
||||||
|
|
||||||
|
|||||||
@@ -2628,6 +2628,41 @@ class AppLocalizationsHu extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Az átjátszó azonosítójának elárasztási útvonal/hurokészlelési címkékbe való kódolására használt bájtok. 0 = 1 bájt (256 azonosító, legfeljebb 64 ugrás), 1 = 2 bájt (65 000 azonosító, legfeljebb 32 ugrás), 2 = 3 bájt (16 millió azonosító, legfeljebb 21 ugrás). A v1.13 és régebbi firmware eldobja a többbájtos elérési utat – csak akkor emelje meg, ha a hálózat a v1.14+ verziót használja.';
|
'Az átjátszó azonosítójának elárasztási útvonal/hurokészlelési címkékbe való kódolására használt bájtok. 0 = 1 bájt (256 azonosító, legfeljebb 64 ugrás), 1 = 2 bájt (65 000 azonosító, legfeljebb 32 ugrás), 2 = 3 bájt (16 millió azonosító, legfeljebb 21 ugrás). A v1.13 és régebbi firmware eldobja a többbájtos elérési utat – csak akkor emelje meg, ha a hálózat a v1.14+ verziót használja.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Áradási TX késleltetés';
|
String get repeater_txDelay => 'Áradási TX késleltetés';
|
||||||
|
|
||||||
|
|||||||
@@ -2636,6 +2636,41 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Byte utilizzati per codificare l\'ID di questo ripetitore nei tag per il rilevamento del percorso/loop. 0=1 byte (256 ID, fino a 64 salti), 1=2 byte (65.000 ID, fino a 32 salti), 2=3 byte (16 milioni di ID, fino a 21 salti). Le versioni 1.13 e precedenti utilizzano percorsi multi-byte: è necessario attivare la rete prima di utilizzare questa funzionalità (a partire dalla versione 1.14).';
|
'Byte utilizzati per codificare l\'ID di questo ripetitore nei tag per il rilevamento del percorso/loop. 0=1 byte (256 ID, fino a 64 salti), 1=2 byte (65.000 ID, fino a 32 salti), 2=3 byte (16 milioni di ID, fino a 21 salti). Le versioni 1.13 e precedenti utilizzano percorsi multi-byte: è necessario attivare la rete prima di utilizzare questa funzionalità (a partire dalla versione 1.14).';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Ritardo a Flood, TX';
|
String get repeater_txDelay => 'Ritardo a Flood, TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2519,6 +2519,41 @@ class AppLocalizationsJa extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'このリピータのIDをフローパス/ループ検出タグにエンコードするために使用されるバイト数。 0=1バイト (256個のID、最大64ホップ)、1=2バイト (65,000個のID、最大32ホップ)、2=3バイト (160万個のID、最大21ホップ)。 v1.13およびそれ以前のファームウェアでは、マルチバイトパスがサポートされていません。 v1.14以降のバージョンでは、一度ネットワークが起動されると、パスが一度だけ検出されます。';
|
'このリピータのIDをフローパス/ループ検出タグにエンコードするために使用されるバイト数。 0=1バイト (256個のID、最大64ホップ)、1=2バイト (65,000個のID、最大32ホップ)、2=3バイト (160万個のID、最大21ホップ)。 v1.13およびそれ以前のファームウェアでは、マルチバイトパスがサポートされていません。 v1.14以降のバージョンでは、一度ネットワークが起動されると、パスが一度だけ検出されます。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'フロイド・TXでの遅延';
|
String get repeater_txDelay => 'フロイド・TXでの遅延';
|
||||||
|
|
||||||
|
|||||||
@@ -2524,6 +2524,41 @@ class AppLocalizationsKo extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'이 리피터의 ID를 플러드 경로/루프 감지 태그에 인코딩하는 데 사용되는 바이트 수: 0=1 바이트 (256개의 ID, 최대 64개의 홉), 1=2 바이트 (65,000개의 ID, 최대 32개의 홉), 2=3 바이트 (16백만 개의 ID, 최대 21개의 홉). v1.13 및 이전 버전의 펌웨어는 다중 바이트 경로를 지원하지 않으며, 네트워크가 v1.14 이상으로 업그레이드되면 한 번만 감지합니다.';
|
'이 리피터의 ID를 플러드 경로/루프 감지 태그에 인코딩하는 데 사용되는 바이트 수: 0=1 바이트 (256개의 ID, 최대 64개의 홉), 1=2 바이트 (65,000개의 ID, 최대 32개의 홉), 2=3 바이트 (16백만 개의 ID, 최대 21개의 홉). v1.13 및 이전 버전의 펌웨어는 다중 바이트 경로를 지원하지 않으며, 네트워크가 v1.14 이상으로 업그레이드되면 한 번만 감지합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => '플러드 TX 지연';
|
String get repeater_txDelay => '플러드 TX 지연';
|
||||||
|
|
||||||
|
|||||||
@@ -2617,6 +2617,41 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Bytes die gebruikt worden om de ID van deze repeater te coderen in flood-pad/lusdetectietags. 0=1 byte (256 ID\'s, tot 64 hops), 1=2 bytes (65.000 ID\'s, tot 32 hops), 2=3 bytes (16 miljoen ID\'s, tot 21 hops). Versies 1.13 en ouder gebruiken multi-byte paden – alleen na het activeren van het netwerk.';
|
'Bytes die gebruikt worden om de ID van deze repeater te coderen in flood-pad/lusdetectietags. 0=1 byte (256 ID\'s, tot 64 hops), 1=2 bytes (65.000 ID\'s, tot 32 hops), 2=3 bytes (16 miljoen ID\'s, tot 21 hops). Versies 1.13 en ouder gebruiken multi-byte paden – alleen na het activeren van het netwerk.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Vertraging bij Flood TX';
|
String get repeater_txDelay => 'Vertraging bij Flood TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2650,6 +2650,41 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Bity wykorzystywane do kodowania identyfikatora tego urządzenia w tagach ścieżek/detekcji pętli. 0=1 bity (256 identyfikatorów, do 64 skoków), 1=2 bity (65 000 identyfikatorów, do 32 skoków), 2=3 bity (1 600 000 identyfikatorów, do 21 skoków). Wersje 1.13 i wcześniejsze nie obsługują ścieżek wielobitowych – wykrywają tylko jedną, gdy sieć jest w wersji 1.14 lub nowszej.';
|
'Bity wykorzystywane do kodowania identyfikatora tego urządzenia w tagach ścieżek/detekcji pętli. 0=1 bity (256 identyfikatorów, do 64 skoków), 1=2 bity (65 000 identyfikatorów, do 32 skoków), 2=3 bity (1 600 000 identyfikatorów, do 21 skoków). Wersje 1.13 i wcześniejsze nie obsługują ścieżek wielobitowych – wykrywają tylko jedną, gdy sieć jest w wersji 1.14 lub nowszej.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Opóźnienie w Flood, TX';
|
String get repeater_txDelay => 'Opóźnienie w Flood, TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2635,6 +2635,41 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Bytes utilizados para codificar o ID deste repetidor nas tags de caminho/detecção de loop. 0=1 byte (256 IDs, até 64 saltos), 1=2 bytes (65.000 IDs, até 32 saltos), 2=3 bytes (16 milhões de IDs, até 21 saltos). As versões 1.13 e anteriores do firmware não suportam caminhos multi-byte — apenas funcionam uma vez após a ativação da rede (a partir da versão 1.14+).';
|
'Bytes utilizados para codificar o ID deste repetidor nas tags de caminho/detecção de loop. 0=1 byte (256 IDs, até 64 saltos), 1=2 bytes (65.000 IDs, até 32 saltos), 2=3 bytes (16 milhões de IDs, até 21 saltos). As versões 1.13 e anteriores do firmware não suportam caminhos multi-byte — apenas funcionam uma vez após a ativação da rede (a partir da versão 1.14+).';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Atraso na entrega em Flood, TX';
|
String get repeater_txDelay => 'Atraso na entrega em Flood, TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2640,6 +2640,41 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Байты, используемые для кодирования идентификатора этого ретранслятора в тегах для обнаружения потоков/циклов. 0 = 1 байт (256 идентификаторов, до 64 переходов), 1 = 2 байта (65 000 идентификаторов, до 32 переходов), 2 = 3 байта (1 600 000 идентификаторов, до 21 перехода). Версии прошивки v1.13 и более ранние версии не поддерживают многобайтовые пути — они поднимаются только после того, как ваша сеть будет обновлена до версии v1.14 и выше.';
|
'Байты, используемые для кодирования идентификатора этого ретранслятора в тегах для обнаружения потоков/циклов. 0 = 1 байт (256 идентификаторов, до 64 переходов), 1 = 2 байта (65 000 идентификаторов, до 32 переходов), 2 = 3 байта (1 600 000 идентификаторов, до 21 перехода). Версии прошивки v1.13 и более ранние версии не поддерживают многобайтовые пути — они поднимаются только после того, как ваша сеть будет обновлена до версии v1.14 и выше.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Задержка в работе системы Flood TX';
|
String get repeater_txDelay => 'Задержка в работе системы Flood TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2621,6 +2621,41 @@ class AppLocalizationsSk extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Byty použité na zakódovanie ID tohto opakovača v tagoch pre trasu/detekciu slučky. 0 = 1 bytu (256 ID, až 64 skokov), 1 = 2 byty (65 000 ID, až 32 skokov), 2 = 3 byty (16 miliónov ID, až 21 skokov). Verzie 1.13 a staršie nepodporujú viacbytové trasy – fungujú len, keď je sieť aktivovaná.';
|
'Byty použité na zakódovanie ID tohto opakovača v tagoch pre trasu/detekciu slučky. 0 = 1 bytu (256 ID, až 64 skokov), 1 = 2 byty (65 000 ID, až 32 skokov), 2 = 3 byty (16 miliónov ID, až 21 skokov). Verzie 1.13 a staršie nepodporujú viacbytové trasy – fungujú len, keď je sieť aktivovaná.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Zpoždanie v Flood, TX';
|
String get repeater_txDelay => 'Zpoždanie v Flood, TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2617,6 +2617,41 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Biti, ki so bila uporabljena za kodiranje ID-ja tega releja v oznakah za zaznavanje pot/kroga, imajo naslednje velikosti: 0=1 bit (256 ID-jev, do 64 skokov), 1=2 biti (65.000 ID-jev, do 32 skokov), 2=3 biti (16 milijonov ID-jev, do 21 skokov). V različicah 1.13 in starejših se ustvarjajo večbitne poti – vendar se to zgodi šele, ko je omrežje vklopljeno v različicah 1.14 in kasnejših.';
|
'Biti, ki so bila uporabljena za kodiranje ID-ja tega releja v oznakah za zaznavanje pot/kroga, imajo naslednje velikosti: 0=1 bit (256 ID-jev, do 64 skokov), 1=2 biti (65.000 ID-jev, do 32 skokov), 2=3 biti (16 milijonov ID-jev, do 21 skokov). V različicah 1.13 in starejših se ustvarjajo večbitne poti – vendar se to zgodi šele, ko je omrežje vklopljeno v različicah 1.14 in kasnejših.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Zatemnitevanje zaradi poplav v Texasu';
|
String get repeater_txDelay => 'Zatemnitevanje zaradi poplav v Texasu';
|
||||||
|
|
||||||
|
|||||||
@@ -2605,6 +2605,41 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Byte används för att koda denna repeaters ID i taggar för att upptäcka loopar/flödesvägar. 0=1 byte (256 ID:n, upp till 64 hopp), 1=2 byte (65 000 ID:n, upp till 32 hopp), 2=3 byte (16 miljoner ID:n, upp till 21 hopp). Versioner 1.13 och äldre har stöd för multi-byte-vägar – endast en gång när nätverket är aktiverat (från och med version 1.14).';
|
'Byte används för att koda denna repeaters ID i taggar för att upptäcka loopar/flödesvägar. 0=1 byte (256 ID:n, upp till 64 hopp), 1=2 byte (65 000 ID:n, upp till 32 hopp), 2=3 byte (16 miljoner ID:n, upp till 21 hopp). Versioner 1.13 och äldre har stöd för multi-byte-vägar – endast en gång när nätverket är aktiverat (från och med version 1.14).';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Försening i Flood TX';
|
String get repeater_txDelay => 'Försening i Flood TX';
|
||||||
|
|
||||||
|
|||||||
@@ -2637,6 +2637,41 @@ class AppLocalizationsUk extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'Байти, що використовуються для кодування ідентифікатора цього ретранслятора в тегах для виявлення потоків/петлі. 0=1 байт (256 ідентифікаторів, до 64 перехідів), 1=2 байти (65 000 ідентифікаторів, до 32 перехідів), 2=3 байти (16 мільйонів ідентифікаторів, до 21 переходу). Версії 1.13 та старіші не підтримують багатобайтні шляхи — вони активуються лише після того, як мережа буде оновлена до версії 1.14+.';
|
'Байти, що використовуються для кодування ідентифікатора цього ретранслятора в тегах для виявлення потоків/петлі. 0=1 байт (256 ідентифікаторів, до 64 перехідів), 1=2 байти (65 000 ідентифікаторів, до 32 перехідів), 2=3 байти (16 мільйонів ідентифікаторів, до 21 переходу). Версії 1.13 та старіші не підтримують багатобайтні шляхи — вони активуються лише після того, як мережа буде оновлена до версії 1.14+.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => 'Затримка у Flood, штат Техас';
|
String get repeater_txDelay => 'Затримка у Flood, штат Техас';
|
||||||
|
|
||||||
|
|||||||
@@ -2494,6 +2494,41 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
String get repeater_pathHashModeHelper =>
|
String get repeater_pathHashModeHelper =>
|
||||||
'用于编码此复用器的 ID 的字节数,在“洪流路径/环检测”标签中使用。 0=1 字节(256 个 ID,最多 64 个跳跃),1=2 字节(65K 个 ID,最多 32 个跳跃),2=3 字节(16M 个 ID,最多 21 个跳跃)。 v1.13 及更早版本的固件会使用多字节路径——只有在您的网络升级到 v1.14 或更高版本后才会生效。';
|
'用于编码此复用器的 ID 的字节数,在“洪流路径/环检测”标签中使用。 0=1 字节(256 个 ID,最多 64 个跳跃),1=2 字节(65K 个 ID,最多 32 个跳跃),2=3 字节(16M 个 ID,最多 21 个跳跃)。 v1.13 及更早版本的固件会使用多字节路径——只有在您的网络升级到 v1.14 或更高版本后才会生效。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettings => 'Change Identity Keys';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_keySettingsSubtitle =>
|
||||||
|
'Change the public/private keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKey => 'Private key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_prvKeyHelper =>
|
||||||
|
'A new private key for the repeater, a 128-character hex string.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_generatePrvKey => 'Generate a random keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_stopGeneratingPrvKey => 'Interrupt search for keypair';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKey => 'Public key';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyHelper =>
|
||||||
|
'This is the public key that goes with the generated private key. You can\'t set this directly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater_pubKeyPrefix => 'Desired prefix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String repeater_pubKeyPrefixHelper(int tries) {
|
||||||
|
return 'Find a public key that starts with these hex digits. Expected tries needed: $tries.';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_txDelay => '洪水(德克萨斯州)延误';
|
String get repeater_txDelay => '洪水(德克萨斯州)延误';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:crypto/crypto.dart' as crypto;
|
import 'package:crypto/crypto.dart' as crypto;
|
||||||
|
import 'package:meshcore_open/utils/keys.dart';
|
||||||
|
|
||||||
import 'channel.dart';
|
import 'channel.dart';
|
||||||
|
|
||||||
@@ -37,11 +37,7 @@ class Community {
|
|||||||
|
|
||||||
/// Generate a new community with a random 32-byte secret
|
/// Generate a new community with a random 32-byte secret
|
||||||
factory Community.create({required String id, required String name}) {
|
factory Community.create({required String id, required String name}) {
|
||||||
final random = Random.secure();
|
final secret = randomBytes(32);
|
||||||
final secret = Uint8List(32);
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
secret[i] = random.nextInt(256);
|
|
||||||
}
|
|
||||||
return Community(
|
return Community(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
@@ -210,12 +206,7 @@ class Community {
|
|||||||
|
|
||||||
/// Create a copy of this community with a regenerated random secret
|
/// Create a copy of this community with a regenerated random secret
|
||||||
Community withRegeneratedSecret() {
|
Community withRegeneratedSecret() {
|
||||||
final random = Random.secure();
|
return withNewSecret(randomBytes(32));
|
||||||
final newSecret = Uint8List(32);
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
newSecret[i] = random.nextInt(256);
|
|
||||||
}
|
|
||||||
return withNewSecret(newSecret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract secret from QR data (for updating existing community)
|
/// Extract secret from QR data (for updating existing community)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:meshcore_open/storage/channel_message_store.dart';
|
import 'package:meshcore_open/storage/channel_message_store.dart';
|
||||||
|
import 'package:meshcore_open/utils/keys.dart';
|
||||||
import 'package:meshcore_open/utils/platform_info.dart';
|
import 'package:meshcore_open/utils/platform_info.dart';
|
||||||
import 'package:meshcore_open/widgets/app_bar.dart';
|
import 'package:meshcore_open/widgets/app_bar.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -938,11 +938,7 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final random = Random.secure();
|
final psk = randomBytes(16);
|
||||||
final psk = Uint8List(16);
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
psk[i] = random.nextInt(256);
|
|
||||||
}
|
|
||||||
Navigator.pop(sheetContext);
|
Navigator.pop(sheetContext);
|
||||||
await connector.setChannel(
|
await connector.setChannel(
|
||||||
nextIndex,
|
nextIndex,
|
||||||
@@ -1571,11 +1567,7 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
|||||||
icon: const Icon(Icons.casino),
|
icon: const Icon(Icons.casino),
|
||||||
tooltip: sheetContext.l10n.channels_generateRandomPsk,
|
tooltip: sheetContext.l10n.channels_generateRandomPsk,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final random = Random.secure();
|
final bytes = randomBytes(16);
|
||||||
final bytes = Uint8List(16);
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
bytes[i] = random.nextInt(256);
|
|
||||||
}
|
|
||||||
pskController.text = Channel.formatPskHex(bytes);
|
pskController.text = Channel.formatPskHex(bytes);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:typed_data';
|
import 'dart:math';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../models/contact.dart';
|
import '../models/contact.dart';
|
||||||
@@ -11,6 +12,7 @@ import '../services/storage_service.dart';
|
|||||||
import '../theme/mesh_theme.dart';
|
import '../theme/mesh_theme.dart';
|
||||||
import '../widgets/mesh_ui.dart';
|
import '../widgets/mesh_ui.dart';
|
||||||
import '../widgets/routing_sheet.dart';
|
import '../widgets/routing_sheet.dart';
|
||||||
|
import '../utils/keys.dart';
|
||||||
import '../helpers/snack_bar_builder.dart';
|
import '../helpers/snack_bar_builder.dart';
|
||||||
|
|
||||||
class RepeaterSettingsScreen extends StatefulWidget {
|
class RepeaterSettingsScreen extends StatefulWidget {
|
||||||
@@ -44,6 +46,7 @@ enum _SettingField {
|
|||||||
advertInterval,
|
advertInterval,
|
||||||
floodAdvertInterval,
|
floodAdvertInterval,
|
||||||
pathHashMode,
|
pathHashMode,
|
||||||
|
prvKey,
|
||||||
txDelay,
|
txDelay,
|
||||||
directTxDelay,
|
directTxDelay,
|
||||||
intThresh,
|
intThresh,
|
||||||
@@ -109,6 +112,8 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
bool _refreshingIntThresh = false;
|
bool _refreshingIntThresh = false;
|
||||||
bool _refreshingAgcResetInterval = false;
|
bool _refreshingAgcResetInterval = false;
|
||||||
bool _runningAction = false;
|
bool _runningAction = false;
|
||||||
|
bool _searchingForKeyPair = false;
|
||||||
|
bool _stopSearchingForKeyPair = false;
|
||||||
StreamSubscription<Uint8List>? _frameSubscription;
|
StreamSubscription<Uint8List>? _frameSubscription;
|
||||||
RepeaterCommandService? _commandService;
|
RepeaterCommandService? _commandService;
|
||||||
|
|
||||||
@@ -154,6 +159,11 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
|
|
||||||
// Advanced
|
// Advanced
|
||||||
int _pathHashMode = 0; // 0-2
|
int _pathHashMode = 0; // 0-2
|
||||||
|
final TextEditingController _prvKeyController = TextEditingController();
|
||||||
|
final TextEditingController _pubKeyController = TextEditingController();
|
||||||
|
final TextEditingController _prvKeyPrefixController = TextEditingController();
|
||||||
|
final KeyPairSearcher _keyPairSearcher = KeyPairSearcher();
|
||||||
|
final int _searchChunkTime = 30; // time in ms to search before yielding
|
||||||
final TextEditingController _txDelayController = TextEditingController();
|
final TextEditingController _txDelayController = TextEditingController();
|
||||||
final TextEditingController _directTxDelayController =
|
final TextEditingController _directTxDelayController =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
@@ -860,6 +870,12 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
command: 'set path.hash.mode $_pathHashMode',
|
command: 'set path.hash.mode $_pathHashMode',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if (_dirtyFields.contains(_SettingField.prvKey)) {
|
||||||
|
final v = _prvKeyController.text.trim();
|
||||||
|
if (v != "") {
|
||||||
|
pending.add((field: _SettingField.prvKey, command: 'set prv.key $v'));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (_dirtyFields.contains(_SettingField.txDelay) &&
|
if (_dirtyFields.contains(_SettingField.txDelay) &&
|
||||||
_txDelayController.text.isNotEmpty) {
|
_txDelayController.text.isNotEmpty) {
|
||||||
final v = double.tryParse(_txDelayController.text.trim());
|
final v = double.tryParse(_txDelayController.text.trim());
|
||||||
@@ -1005,6 +1021,36 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _startSearchingForKeyPair() async {
|
||||||
|
if (_searchingForKeyPair) return;
|
||||||
|
setState(() {
|
||||||
|
_searchingForKeyPair = true;
|
||||||
|
_stopSearchingForKeyPair = false;
|
||||||
|
});
|
||||||
|
_searchForKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _searchForKeyPair() async {
|
||||||
|
if (_stopSearchingForKeyPair) {
|
||||||
|
setState(() => _searchingForKeyPair = false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final String prefix = _prvKeyPrefixController.text.trim();
|
||||||
|
MCKeyPair? keys = await _keyPairSearcher.findMatchingKeyPair(
|
||||||
|
prefix,
|
||||||
|
_searchChunkTime,
|
||||||
|
);
|
||||||
|
if (keys == null) {
|
||||||
|
// Ran out of time; schedule another attempt.
|
||||||
|
Timer.run(_searchForKeyPair);
|
||||||
|
} else {
|
||||||
|
setState(() => _searchingForKeyPair = false);
|
||||||
|
_prvKeyController.text = pubKeyToHex(keys.private);
|
||||||
|
_pubKeyController.text = pubKeyToHex(keys.public);
|
||||||
|
_markChanged(_SettingField.prvKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildInlineRefreshButton({
|
Widget _buildInlineRefreshButton({
|
||||||
required bool isRefreshing,
|
required bool isRefreshing,
|
||||||
required VoidCallback onRefresh,
|
required VoidCallback onRefresh,
|
||||||
@@ -1069,6 +1115,7 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
_buildOwnerInfoCard(),
|
_buildOwnerInfoCard(),
|
||||||
_buildActionsCard(),
|
_buildActionsCard(),
|
||||||
_buildAdvancedCard(),
|
_buildAdvancedCard(),
|
||||||
|
_buildKeysCard(),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildDangerZoneCard(),
|
_buildDangerZoneCard(),
|
||||||
],
|
],
|
||||||
@@ -1984,6 +2031,127 @@ class _RepeaterSettingsScreenState extends State<RepeaterSettingsScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildKeysCard() {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
return MeshCard(
|
||||||
|
child: ExpansionTile(
|
||||||
|
leading: const Icon(Icons.vpn_key),
|
||||||
|
title: Text(
|
||||||
|
l10n.repeater_keySettings,
|
||||||
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
subtitle: Text(l10n.repeater_keySettingsSubtitle),
|
||||||
|
childrenPadding: const EdgeInsets.fromLTRB(0, 8, 0, 4),
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: _prvKeyController,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp("[0-9a-fA-F]")),
|
||||||
|
],
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: l10n.repeater_prvKey,
|
||||||
|
helperText: l10n.repeater_prvKeyHelper,
|
||||||
|
helperMaxLines: 3,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
onChanged: (_) {
|
||||||
|
_pubKeyController.text = "";
|
||||||
|
if (_prvKeyController.text.isNotEmpty) {
|
||||||
|
_markChanged(_SettingField.prvKey);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: _searchingForKeyPair
|
||||||
|
? IconButton(
|
||||||
|
icon: const Icon(Icons.cancel, size: 24),
|
||||||
|
onPressed: (() => _stopSearchingForKeyPair = true),
|
||||||
|
tooltip: l10n.repeater_stopGeneratingPrvKey,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
)
|
||||||
|
: IconButton(
|
||||||
|
icon: const Icon(Icons.casino_rounded, size: 24),
|
||||||
|
onPressed: () {
|
||||||
|
_startSearchingForKeyPair();
|
||||||
|
},
|
||||||
|
tooltip: l10n.repeater_generatePrvKey,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
readOnly: true,
|
||||||
|
controller: _pubKeyController,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.headlineSmall?.color?.withValues(alpha: 0.6),
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: l10n.repeater_pubKey,
|
||||||
|
helperText: l10n.repeater_pubKeyHelper,
|
||||||
|
helperMaxLines: 3,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 12),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
child: _searchingForKeyPair
|
||||||
|
? CircularProgressIndicator(strokeWidth: 2)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: _prvKeyPrefixController,
|
||||||
|
maxLength: 4,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp("[0-9a-fA-F]")),
|
||||||
|
],
|
||||||
|
onChanged: (_) => setState(() => {}), // updates helper text
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: l10n.repeater_pubKeyPrefix,
|
||||||
|
helperText: l10n.repeater_pubKeyPrefixHelper(
|
||||||
|
pow(16, _prvKeyPrefixController.text.length).toInt(),
|
||||||
|
),
|
||||||
|
helperMaxLines: 3,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 48),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildDangerZoneCard() {
|
Widget _buildDangerZoneCard() {
|
||||||
final l10n = context.l10n;
|
final l10n = context.l10n;
|
||||||
return MeshCard(
|
return MeshCard(
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:convert/convert.dart';
|
||||||
|
import 'package:cryptography/cryptography.dart';
|
||||||
|
|
||||||
|
Uint8List randomBytes(int length) {
|
||||||
|
final random = Random.secure();
|
||||||
|
final bytes = Uint8List(32);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
bytes[i] = random.nextInt(256);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MCKeyPair {
|
||||||
|
final Uint8List public;
|
||||||
|
final Uint8List private;
|
||||||
|
MCKeyPair(this.public, this.private);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<MCKeyPair> generateKeyPair() async {
|
||||||
|
final algo = Ed25519();
|
||||||
|
final seed = randomBytes(32);
|
||||||
|
final SimpleKeyPair keys = await algo.newKeyPairFromSeed(seed);
|
||||||
|
final Uint8List pubKeyBytes = Uint8List.fromList(
|
||||||
|
(await keys.extractPublicKey()).bytes,
|
||||||
|
);
|
||||||
|
// Ed25519 gives 32-byte public and private keys, but MeshCore
|
||||||
|
// uses an expanded 64-byte private key, so we have to make it
|
||||||
|
// ourselves. Luckily, we can do it such that it has the same public
|
||||||
|
// key, which we'd otherwise be unable to compute, since although the
|
||||||
|
// crypto library implements the elliptic curve computations we need,
|
||||||
|
// it doesn't make them available.
|
||||||
|
final Uint8List hash = Uint8List.fromList((await Sha512().hash(seed)).bytes);
|
||||||
|
hash[0] &= 248; // Clamp the scalar. This keeps the chosen point in the
|
||||||
|
hash[31] &= 63; // large elliptic curve subgroup, and is demanded both by
|
||||||
|
hash[31] |= 64; // Ed25519 and by the MeshCore repeater key validation code.
|
||||||
|
return MCKeyPair(pubKeyBytes, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _KeyHashPrefix {
|
||||||
|
Uint8List _bytes = Uint8List(0);
|
||||||
|
Uint8List _mask = Uint8List(0);
|
||||||
|
_KeyHashPrefix(String prefix) {
|
||||||
|
final bool lengthIsOdd = (prefix.length % 2 == 1) ? true : false;
|
||||||
|
final String decodableString = lengthIsOdd ? "${prefix}0" : prefix;
|
||||||
|
_bytes = hex.decoder.convert(decodableString);
|
||||||
|
_mask = Uint8List(_bytes.length);
|
||||||
|
for (var i = 0; i < _mask.length; i++) {
|
||||||
|
_mask[i] = 0xff;
|
||||||
|
}
|
||||||
|
if (lengthIsOdd) {
|
||||||
|
_mask[_mask.length - 1] = 0xf0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(List<int> keyBytes) {
|
||||||
|
if (keyBytes.length < _bytes.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < _bytes.length; i++) {
|
||||||
|
if (keyBytes[i] & _mask[i] != _bytes[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeyPairSearcher {
|
||||||
|
Future<MCKeyPair?> findMatchingKeyPair(
|
||||||
|
String prefixStr,
|
||||||
|
int maxMilliseconds,
|
||||||
|
) async {
|
||||||
|
final int now = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
final int endTime = now + maxMilliseconds;
|
||||||
|
final _KeyHashPrefix keyHashPrefix = _KeyHashPrefix(prefixStr);
|
||||||
|
while (DateTime.now().millisecondsSinceEpoch < endTime) {
|
||||||
|
final MCKeyPair keys = await generateKeyPair();
|
||||||
|
if (keyHashPrefix.matches(keys.public)) {
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
flserial
|
flserial
|
||||||
|
jni
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import cryptography_flutter
|
||||||
import flutter_blue_plus_darwin
|
import flutter_blue_plus_darwin
|
||||||
import flutter_local_notifications
|
import flutter_local_notifications
|
||||||
import mobile_scanner
|
import mobile_scanner
|
||||||
@@ -15,6 +16,7 @@ import sqflite_darwin
|
|||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
CryptographyFlutterPlugin.register(with: registry.registrar(forPlugin: "CryptographyFlutterPlugin"))
|
||||||
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"))
|
||||||
MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
|
MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ dependencies:
|
|||||||
ml_dataframe: ^1.0.0
|
ml_dataframe: ^1.0.0
|
||||||
llamadart: ^0.8.0
|
llamadart: ^0.8.0
|
||||||
flutter_langdetect: ^0.0.1
|
flutter_langdetect: ^0.0.1
|
||||||
|
cryptography: ^2.9.0
|
||||||
|
cryptography_flutter: ^2.3.4
|
||||||
|
convert: ^3.1.2
|
||||||
|
|
||||||
hooks:
|
hooks:
|
||||||
user_defines:
|
user_defines:
|
||||||
|
|||||||
+187
-17
@@ -15,13 +15,33 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"de": [
|
"de": [
|
||||||
"settings_regionFetchRegions",
|
"settings_regionFetchRegions",
|
||||||
"settings_regionFetchRegionsFail",
|
"settings_regionFetchRegionsFail",
|
||||||
"settings_regionFetchRegionsAlreadyExists"
|
"settings_regionFetchRegionsAlreadyExists",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"es": [
|
"es": [
|
||||||
@@ -40,7 +60,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"fr": [
|
"fr": [
|
||||||
@@ -59,7 +89,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"hu": [
|
"hu": [
|
||||||
@@ -78,7 +118,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"it": [
|
"it": [
|
||||||
@@ -97,7 +147,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ja": [
|
"ja": [
|
||||||
@@ -116,7 +176,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ko": [
|
"ko": [
|
||||||
@@ -135,7 +205,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"nl": [
|
"nl": [
|
||||||
@@ -154,7 +234,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"pl": [
|
"pl": [
|
||||||
@@ -173,7 +263,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"pt": [
|
"pt": [
|
||||||
@@ -192,7 +292,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ru": [
|
"ru": [
|
||||||
@@ -211,7 +321,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"sk": [
|
"sk": [
|
||||||
@@ -230,7 +350,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"sl": [
|
"sl": [
|
||||||
@@ -249,7 +379,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"sv": [
|
"sv": [
|
||||||
@@ -268,7 +408,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"uk": [
|
"uk": [
|
||||||
@@ -287,7 +437,17 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
],
|
],
|
||||||
|
|
||||||
"zh": [
|
"zh": [
|
||||||
@@ -306,6 +466,16 @@
|
|||||||
"channels_regionSetTo",
|
"channels_regionSetTo",
|
||||||
"channels_regionNotSet",
|
"channels_regionNotSet",
|
||||||
"channels_regionSelect_Title",
|
"channels_regionSelect_Title",
|
||||||
"channels_clearRegion"
|
"channels_clearRegion",
|
||||||
|
"repeater_keySettings",
|
||||||
|
"repeater_keySettingsSubtitle",
|
||||||
|
"repeater_prvKey",
|
||||||
|
"repeater_prvKeyHelper",
|
||||||
|
"repeater_generatePrvKey",
|
||||||
|
"repeater_stopGeneratingPrvKey",
|
||||||
|
"repeater_pubKey",
|
||||||
|
"repeater_pubKeyHelper",
|
||||||
|
"repeater_pubKeyPrefix",
|
||||||
|
"repeater_pubKeyPrefixHelper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
flserial
|
flserial
|
||||||
flutter_local_notifications_windows
|
flutter_local_notifications_windows
|
||||||
|
jni
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
Reference in New Issue
Block a user