diff --git a/deploy/apps/lang/bg.lang b/deploy/apps/lang/bg.lang index da2d269..959997e 100644 --- a/deploy/apps/lang/bg.lang +++ b/deploy/apps/lang/bg.lang @@ -282,6 +282,7 @@ End time Краен час Enter SSID first Първо въведете SSID Enter a name Въведете име Enter a network name Въведете име на мрежа +Enter a region name Enter a region name Enter adds a new line Enter добавя нов ред Enter exactly 32 hex characters. Въведете точно 32 hex знака. Enter key sends message Клавишът Enter изпраща съобщението @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Клавиатурна навиг.: WASDZ вкл. Keyboard nav: off Клавиатурна навиг.: изкл. Keyboard navigation Навигация с клавиатура Keys +Known regions Known regions LOS → %s Пряка видимост → %s Landscape (desktop) Пейзаж (десктоп) Landscape set - applies when remote mode starts. Пейзажът е зададен - прилага се при стартиране на отдалечения режим. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Няма намерени мрежи (само No onboard GPS Няма вграден GPS No other networks found Не са открити други мрежи No position yet. A cold start needs a clear view of the sky and can take several minutes. Още няма позиция. Студен старт изисква чисто небе и може да отнеме няколко минути. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Няма отговор от %s No reply. Check password, server,\nor device clock (device: %s) Няма отговор. Проверете паролата, сървъра\nили часовника на устройството (устройство: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Тук няма запазени плочки.\n\nСвържете се с Wi-Fi (Настройки → Wi-Fi),\nза да изтеглите този район.\nЗапазените плочки остават достъпни офлайн. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Наскоро чути Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Форматиране на SD като MESHCOMOD (FAT32)?\nВСИЧКИ данни на картата ще бъдат изтрити. Region & scope Регион и обхват +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Регионален обхват (#tag) за този канал.\nПразно = обхват по подразбиране. Region scope (#tag), blank = default. Обхват на регион (#tag), празно = по подразбиране. Region scope (#tag, blank = none) Регионален обхват (#tag, празно = няма) diff --git a/deploy/apps/lang/de.lang b/deploy/apps/lang/de.lang index 7150f9d..2ea2b6d 100644 --- a/deploy/apps/lang/de.lang +++ b/deploy/apps/lang/de.lang @@ -282,6 +282,7 @@ End time Endzeit Enter SSID first Zuerst SSID eingeben Enter a name Namen eingeben Enter a network name Netzwerknamen eingeben +Enter a region name Enter a region name Enter adds a new line Enter fügt neue Zeile ein Enter exactly 32 hex characters. Genau 32 Hex-Zeichen eingeben. Enter key sends message Enter-Taste sendet Nachricht @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Tastaturnav.: WASDZ an Keyboard nav: off Tastaturnav.: aus Keyboard navigation Tastaturnavigation Keys Tasten +Known regions Known regions LOS → %s Sichtlinie → %s Landscape (desktop) Querformat (Desktop) Landscape set - applies when remote mode starts. Querformat gesetzt - gilt beim Start des Fernmodus. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Keine Netzwerke gefunden (nur 2,4 GHz) No onboard GPS Kein integriertes GPS No other networks found Keine anderen Netzwerke gefunden No position yet. A cold start needs a clear view of the sky and can take several minutes. Noch keine Position. Ein Kaltstart braucht freie Sicht zum Himmel und kann mehrere Minuten dauern. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Keine Antwort von %s No reply. Check password, server,\nor device clock (device: %s) Keine Antwort. Prüfe Passwort, Server\noder Geräteuhr (Gerät: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Hier keine gespeicherten Kacheln.\n\nMit Wi-Fi verbinden (Einstellungen → Wi-Fi),\num dieses Gebiet zu laden.\nGespeicherte Kacheln bleiben offline verfügbar. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Kürzlich gehört Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. SD als MESHCOMOD (FAT32) neu formatieren?\nALLE Daten auf der Karte werden gelöscht. Region & scope Region & Reichweite +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Regionsbereich (#tag) für diesen Kanal.\nLeer = Standardbereich verwenden. Region scope (#tag), blank = default. Regionsbereich (#tag), leer = Standard. Region scope (#tag, blank = none) Regionsbereich (#tag, leer = keiner) diff --git a/deploy/apps/lang/el.lang b/deploy/apps/lang/el.lang index 96784df..e5f8d8f 100644 --- a/deploy/apps/lang/el.lang +++ b/deploy/apps/lang/el.lang @@ -282,6 +282,7 @@ End time Ώρα λήξης Enter SSID first Εισαγάγετε πρώτα το SSID Enter a name Εισαγάγετε όνομα Enter a network name Εισαγάγετε όνομα δικτύου +Enter a region name Enter a region name Enter adds a new line Το Enter προσθέτει γραμμή Enter exactly 32 hex characters. Εισαγάγετε ακριβώς 32 hex χαρακτήρες. Enter key sends message Το πλήκτρο Enter στέλνει το μήνυμα @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Πλοήγηση πληκτρ.: WASDZ ενεργό Keyboard nav: off Πλοήγηση πληκτρ.: κλειστό Keyboard navigation Πλοήγηση με πληκτρολόγιο Keys +Known regions Known regions LOS → %s Οπτική επαφή → %s Landscape (desktop) Οριζόντια (desktop) Landscape set - applies when remote mode starts. Ορίστηκε οριζόντια - ισχύει όταν ξεκινήσει η απομακρυσμένη λειτουργία. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Δεν βρέθηκαν δίκτυα (μόνο No onboard GPS Χωρίς ενσωματωμένο GPS No other networks found Δεν βρέθηκαν άλλα δίκτυα No position yet. A cold start needs a clear view of the sky and can take several minutes. Δεν υπάρχει ακόμη θέση. Η ψυχρή εκκίνηση θέλει ανοιχτό ουρανό και μπορεί να πάρει λεπτά. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Καμία απάντηση από %s No reply. Check password, server,\nor device clock (device: %s) Καμία απάντηση. Ελέγξτε κωδικό, διακομιστή\nή ρολόι συσκευής (συσκευή: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Δεν υπάρχουν αποθηκευμένα πλακίδια εδώ.\n\nΣυνδεθείτε στο Wi-Fi (Ρυθμίσεις → Wi-Fi)\nγια λήψη αυτής της περιοχής.\nΤα αποθηκευμένα πλακίδια μένουν διαθέσιμα εκτός σύνδεσης. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Ακούστηκε πρόσφατα Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Επαναδιαμόρφωση SD ως MESHCOMOD (FAT32);\nΟΛΑ τα δεδομένα στην κάρτα θα διαγραφούν. Region & scope Περιοχή & εμβέλεια +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Εύρος περιοχής (#tag) για αυτό το κανάλι.\nΚενό = προεπιλεγμένο εύρος. Region scope (#tag), blank = default. Εύρος περιοχής (#tag), κενό = προεπιλογή. Region scope (#tag, blank = none) Εύρος περιοχής (#tag, κενό = κανένα) diff --git a/deploy/apps/lang/es.lang b/deploy/apps/lang/es.lang index f45b340..f4e686c 100644 --- a/deploy/apps/lang/es.lang +++ b/deploy/apps/lang/es.lang @@ -282,6 +282,7 @@ End time Hora de fin Enter SSID first Introduce primero el SSID Enter a name Introduce un nombre Enter a network name Introduce un nombre de red +Enter a region name Enter a region name Enter adds a new line Enter añade una línea Enter exactly 32 hex characters. Introduce exactamente 32 caracteres hex. Enter key sends message La tecla Enter envía el mensaje @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Nav. teclado: WASDZ act. Keyboard nav: off Nav. teclado: desact. Keyboard navigation Navegación por teclado Keys +Known regions Known regions LOS → %s Línea de vista → %s Landscape (desktop) Horizontal (escritorio) Landscape set - applies when remote mode starts. Horizontal fijado - se aplica al iniciar el modo remoto. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) No se encontraron redes (solo 2.4 GHz) No onboard GPS Sin GPS integrado No other networks found No se encontraron otras redes No position yet. A cold start needs a clear view of the sky and can take several minutes. Aún sin posición. Un arranque en frío necesita cielo despejado y puede tardar varios minutos. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Sin respuesta de %s No reply. Check password, server,\nor device clock (device: %s) Sin respuesta. Revisa contraseña, servidor\no reloj del dispositivo (dispositivo: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. No hay teselas guardadas aquí.\n\nConéctate a Wi-Fi (Ajustes → Wi-Fi)\npara descargar esta zona.\nLas teselas guardadas quedan disponibles sin conexión. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Escuchado hace poco Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. ¿Reformatear la SD como MESHCOMOD (FAT32)?\nSe borrarán TODOS los datos de la tarjeta. Region & scope Región y alcance +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Alcance de región (#tag) para este canal.\nVacío = alcance predeterminado. Region scope (#tag), blank = default. Ámbito de región (#tag), vacío = predeterminado. Region scope (#tag, blank = none) Alcance de región (#tag, vacío = ninguno) diff --git a/deploy/apps/lang/fr.lang b/deploy/apps/lang/fr.lang index 9b29cc8..5f497fe 100644 --- a/deploy/apps/lang/fr.lang +++ b/deploy/apps/lang/fr.lang @@ -282,6 +282,7 @@ End time Heure de fin Enter SSID first Saisissez d'abord le SSID Enter a name Saisissez un nom Enter a network name Saisir un nom de réseau +Enter a region name Enter a region name Enter adds a new line Entrée ajoute une ligne Enter exactly 32 hex characters. Saisissez exactement 32 caractères hex. Enter key sends message La touche Entrée envoie le message @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Nav. clavier : WASDZ activé Keyboard nav: off Nav. clavier : désactivé Keyboard navigation Navigation clavier Keys +Known regions Known regions LOS → %s Vue directe → %s Landscape (desktop) Paysage (bureau) Landscape set - applies when remote mode starts. Paysage défini - s'applique au démarrage du mode distant. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Aucun réseau trouvé (2,4 GHz uniquement) No onboard GPS Pas de GPS intégré No other networks found Aucun autre réseau trouvé No position yet. A cold start needs a clear view of the sky and can take several minutes. Pas encore de position. Un démarrage à froid demande un ciel dégagé et peut prendre plusieurs minutes. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Pas de réponse de %s No reply. Check password, server,\nor device clock (device: %s) Pas de réponse. Vérifiez mot de passe, serveur\nou horloge de l'appareil (appareil : %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Aucune tuile enregistrée ici.\n\nConnectez-vous au Wi-Fi (Réglages → Wi-Fi)\npour télécharger cette zone.\nLes tuiles enregistrées restent hors ligne. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Entendu récemment Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Reformater la SD en MESHCOMOD (FAT32) ?\nTOUTES les données de la carte seront effacées. Region & scope Région et portée +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Portée régionale (#tag) pour ce canal.\nVide = portée par défaut. Region scope (#tag), blank = default. Portée de région (#tag), vide = défaut. Region scope (#tag, blank = none) Portée régionale (#tag, vide = aucune) diff --git a/deploy/apps/lang/hu.lang b/deploy/apps/lang/hu.lang index bffac43..779fb59 100644 --- a/deploy/apps/lang/hu.lang +++ b/deploy/apps/lang/hu.lang @@ -286,6 +286,7 @@ End time Befejezés Enter SSID first Először adja meg az SSID-t Enter a name Írjon be egy nevet Enter a network name Adjon meg egy hálózatnevet +Enter a region name Enter a region name Enter adds a new line Az Enter új sort ad hozzá Enter exactly 32 hex characters. Pontosan 32 hex karaktert adjon meg. Enter key sends message Az Enter billentyű elküldi az üzenetet @@ -412,6 +413,7 @@ Keyboard nav: WASDZ on Billentyűzet navigáció: WASDZ bekapcsolva Keyboard nav: off Billentyűzetnavigáció: kikapcsolva Keyboard navigation Billentyűzetnavigáció Keys Kulcsok +Known regions Known regions LOS → %s Rálátás → %s Landscape (desktop) Fekvő (asztali) Landscape set - applies when remote mode starts. Fekvő beállítva - a távoli mód indulásakor lép életbe. @@ -539,6 +541,7 @@ No networks found (2.4 GHz only) Nem található hálózat (csak 2,4 GHz) No onboard GPS Nincs beépített GPS No other networks found Nem található más hálózat No position yet. A cold start needs a clear view of the sky and can take several minutes. Még nincs pozíció. A hidegindításhoz szabad égbolt kell, és több percig is tarthat. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Nincs válasz %s-tól No reply. Check password, server,\nor device clock (device: %s) Nincs válasz. Ellenőrizze a jelszót, a szervert,\nvagy az eszköz óráját (eszköz: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Nincsenek mentett térképszeletek. \n\nCsatlakozzon Wi-Fi-hez (Beállítások → Wi-Fi) a terület letöltéséhez.\nA mentett szeletek offline is elérhetők maradnak. @@ -649,6 +652,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Nemrég hallottam Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Újraformázza az SD kártyát MESHCOMOD (FAT32) formátumban?\nA kártyán lévő ÖSSZES adat törlődik. Region & scope Régió és hatókör +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Régió hatóköre (#tag) ehhez a csatornához.\nÜres = az alapértelmezett hatókör használata. Region scope (#tag), blank = default. Régió hatóköre (#tag), üres = alapértelmezett. Region scope (#tag, blank = none) Régió hatóköre (#címke, üres = nincs) diff --git a/deploy/apps/lang/it.lang b/deploy/apps/lang/it.lang index 94c9765..5ac1b30 100644 --- a/deploy/apps/lang/it.lang +++ b/deploy/apps/lang/it.lang @@ -282,6 +282,7 @@ End time Ora di fine Enter SSID first Inserisci prima l'SSID Enter a name Inserisci un nome Enter a network name Inserisci un nome di rete +Enter a region name Enter a region name Enter adds a new line Invio aggiunge una riga Enter exactly 32 hex characters. Inserisci esattamente 32 caratteri hex. Enter key sends message Il tasto Invio invia il messaggio @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Nav. tastiera: WASDZ on Keyboard nav: off Nav. tastiera: off Keyboard navigation Navigazione da tastiera Keys +Known regions Known regions LOS → %s Vista diretta → %s Landscape (desktop) Orizzontale (desktop) Landscape set - applies when remote mode starts. Orizzontale impostato - vale all'avvio della modalità remota. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Nessuna rete trovata (solo 2.4 GHz) No onboard GPS Nessun GPS integrato No other networks found Nessun'altra rete trovata No position yet. A cold start needs a clear view of the sky and can take several minutes. Ancora nessuna posizione. Un avvio a freddo richiede cielo libero e può durare diversi minuti. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Nessuna risposta da %s No reply. Check password, server,\nor device clock (device: %s) Nessuna risposta. Controlla password, server\no orologio del dispositivo (dispositivo: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Nessuna tessera salvata qui.\n\nConnettiti al Wi-Fi (Impostazioni → Wi-Fi)\nper scaricare quest'area.\nLe tessere salvate restano disponibili offline. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Sentito di recente Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Riformattare la SD come MESHCOMOD (FAT32)?\nTUTTI i dati sulla scheda saranno cancellati. Region & scope Regione e ambito +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Ambito regione (#tag) per questo canale.\nVuoto = ambito predefinito. Region scope (#tag), blank = default. Ambito regione (#tag), vuoto = predefinito. Region scope (#tag, blank = none) Ambito regione (#tag, vuoto = nessuno) diff --git a/deploy/apps/lang/nl.lang b/deploy/apps/lang/nl.lang index 36ec892..33d63b6 100644 --- a/deploy/apps/lang/nl.lang +++ b/deploy/apps/lang/nl.lang @@ -282,6 +282,7 @@ End time Eindtijd Enter SSID first Voer eerst SSID in Enter a name Voer een naam in Enter a network name Voer een netwerknaam in +Enter a region name Enter a region name Enter adds a new line Enter voegt een nieuwe regel toe Enter exactly 32 hex characters. Voer precies 32 hex-tekens in. Enter key sends message Enter verstuurt bericht @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Toetsenbordnav.: WASDZ aan Keyboard nav: off Toetsenbordnav.: uit Keyboard navigation Toetsenbordnavigatie Keys Toetsen +Known regions Known regions LOS → %s Zichtlijn → %s Landscape (desktop) Liggend (desktop) Landscape set - applies when remote mode starts. Liggend ingesteld - geldt zodra de externe modus start. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Geen netwerken gevonden (alleen 2.4 GHz) No onboard GPS Geen ingebouwde GPS No other networks found Geen andere netwerken gevonden No position yet. A cold start needs a clear view of the sky and can take several minutes. Nog geen positie. Een koude start heeft vrij zicht op de lucht nodig en kan enkele minuten duren. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Geen antwoord van %s No reply. Check password, server,\nor device clock (device: %s) Geen antwoord. Controleer wachtwoord, server,\nof apparaatklok (apparaat: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Hier geen opgeslagen kaarttegels.\n\nMaak verbinding met Wi-Fi (Instellingen → Wi-Fi)\nom dit gebied te downloaden.\nOpgeslagen tegels blijven offline beschikbaar. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Recent gehoord Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. SD herformatteren als MESHCOMOD (FAT32)?\nALLE data op de kaart wordt gewist. Region & scope Regio en bereik +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Regiobereik (#tag) voor dit kanaal.\nLeeg = standaardbereik gebruiken. Region scope (#tag), blank = default. Regiobereik (#tag), leeg = standaard. Region scope (#tag, blank = none) Regiobereik (#tag, leeg = geen) diff --git a/deploy/apps/lang/pt-br.lang b/deploy/apps/lang/pt-br.lang index 61af65e..7494a31 100644 --- a/deploy/apps/lang/pt-br.lang +++ b/deploy/apps/lang/pt-br.lang @@ -282,6 +282,7 @@ End time Hora de término Enter SSID first Digite o SSID primeiro Enter a name Digite um nome Enter a network name Digite um nome de rede +Enter a region name Enter a region name Enter adds a new line Enter adiciona uma linha Enter exactly 32 hex characters. Digite exatamente 32 caracteres hex. Enter key sends message A tecla Enter envia a mensagem @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Nav. teclado: WASDZ ligado Keyboard nav: off Nav. teclado: desligado Keyboard navigation Navegação por teclado Keys +Known regions Known regions LOS → %s Linha de visada → %s Landscape (desktop) Paisagem (desktop) Landscape set - applies when remote mode starts. Paisagem definida - vale quando o modo remoto iniciar. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Nenhuma rede encontrada (só 2.4 GHz) No onboard GPS Sem GPS integrado No other networks found Nenhuma outra rede encontrada No position yet. A cold start needs a clear view of the sky and can take several minutes. Ainda sem posição. Uma partida a frio precisa de céu aberto e pode levar vários minutos. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Sem resposta de %s No reply. Check password, server,\nor device clock (device: %s) Sem resposta. Verifique senha, servidor\nou relógio do dispositivo (dispositivo: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Sem blocos salvos aqui.\n\nConecte-se ao Wi-Fi (Ajustes → Wi-Fi)\npara baixar esta área.\nOs blocos salvos ficam disponíveis offline. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Ouvido recentemente Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Reformatar o SD como MESHCOMOD (FAT32)?\nTODOS os dados do cartão serão apagados. Region & scope Região e alcance +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Escopo de região (#tag) para este canal.\nVazio = usar o escopo padrão. Region scope (#tag), blank = default. Escopo da região (#tag), vazio = padrão. Region scope (#tag, blank = none) Escopo de região (#tag, vazio = nenhum) diff --git a/deploy/apps/lang/ro.lang b/deploy/apps/lang/ro.lang index ef1d3ac..183b11d 100644 --- a/deploy/apps/lang/ro.lang +++ b/deploy/apps/lang/ro.lang @@ -282,6 +282,7 @@ End time Ora de sfârşit Enter SSID first Introdu mai întâi SSID-ul Enter a name Introdu un nume Enter a network name Introdu un nume de reţea +Enter a region name Enter a region name Enter adds a new line Enter adaugă un rând nou Enter exactly 32 hex characters. Introdu exact 32 caractere hex. Enter key sends message Tasta Enter trimite mesajul @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Navigare tastatură: WASDZ pornit Keyboard nav: off Navigare tastatură: oprită Keyboard navigation Navigare cu tastatura Keys +Known regions Known regions LOS → %s Linie vizuală → %s Landscape (desktop) Peisaj (desktop) Landscape set - applies when remote mode starts. Peisaj setat - se aplică la pornirea modului la distanţă. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Nicio reţea găsită (doar 2,4 GHz) No onboard GPS Fără GPS integrat No other networks found Nicio altă reţea găsită No position yet. A cold start needs a clear view of the sky and can take several minutes. Încă nicio poziţie. O pornire la rece are nevoie de cer liber şi poate dura câteva minute. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Niciun răspuns de la %s No reply. Check password, server,\nor device clock (device: %s) Niciun răspuns. Verifică parola, serverul\nsau ceasul dispozitivului (dispozitiv: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Fără dale salvate aici.\n\nConectează Wi-Fi (Setări → Wi-Fi)\npentru a descărca zona.\nDalele salvate rămân offline. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Auzite recent Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Reformatezi SD ca MESHCOMOD (FAT32)?\nTOATE datele de pe card vor fi şterse. Region & scope Regiune şi acoperire +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Domeniu regional (#tag) pentru acest canal.\nGol = domeniul implicit. Region scope (#tag), blank = default. Domeniu regional (#tag), gol = implicit. Region scope (#tag, blank = none) Domeniu regional (#tag, gol = niciunul) diff --git a/deploy/apps/lang/ru.lang b/deploy/apps/lang/ru.lang index 588e950..a9ea518 100644 --- a/deploy/apps/lang/ru.lang +++ b/deploy/apps/lang/ru.lang @@ -282,6 +282,7 @@ End time Время окончания Enter SSID first Сначала введите SSID Enter a name Введите имя Enter a network name Введите имя сети +Enter a region name Enter a region name Enter adds a new line Enter добавляет строку Enter exactly 32 hex characters. Введите ровно 32 hex-символа. Enter key sends message Клавиша Enter отправляет сообщение @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Навигация клавиатурой: WASDZ вкл. Keyboard nav: off Навигация клавиатурой: выкл. Keyboard navigation Навигация клавиатурой Keys +Known regions Known regions LOS → %s Прямая видимость → %s Landscape (desktop) Альбомная (десктоп) Landscape set - applies when remote mode starts. Альбомная выбрана - применится при запуске удалённого режима. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Сети не найдены (только 2.4 No onboard GPS Нет встроенного GPS No other networks found Другие сети не найдены No position yet. A cold start needs a clear view of the sky and can take several minutes. Позиции пока нет. Холодный старт требует открытого неба и может занять несколько минут. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Нет ответа от %s No reply. Check password, server,\nor device clock (device: %s) Нет ответа. Проверьте пароль, сервер\nили часы устройства (устройство: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Здесь нет сохранённых тайлов.\n\nПодключитесь к Wi-Fi (Настройки → Wi-Fi),\nчтобы загрузить этот район.\nСохранённые тайлы остаются доступны офлайн. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Недавно слышно Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Отформатировать SD как MESHCOMOD (FAT32)?\nВСЕ данные на карте будут стёрты. Region & scope Регион и охват +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Регион (#tag) для этого канала.\nПусто = область по умолчанию. Region scope (#tag), blank = default. Область региона (#tag), пусто = по умолчанию. Region scope (#tag, blank = none) Регион (#tag, пусто = нет) diff --git a/deploy/apps/lang/sr.lang b/deploy/apps/lang/sr.lang index 712afbc..13764b8 100644 --- a/deploy/apps/lang/sr.lang +++ b/deploy/apps/lang/sr.lang @@ -282,6 +282,7 @@ End time Време краја Enter SSID first Прво унесите SSID Enter a name Унесите име Enter a network name Унесите име мреже +Enter a region name Enter a region name Enter adds a new line Enter додаје нови ред Enter exactly 32 hex characters. Унесите тачно 32 hex знака. Enter key sends message Тастер Enter шаље поруку @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Навиг. тастатуром: WASDZ укљ. Keyboard nav: off Навиг. тастатуром: искљ. Keyboard navigation Навигација тастатуром Keys +Known regions Known regions LOS → %s Оптичка видљивост → %s Landscape (desktop) Положено (десктоп) Landscape set - applies when remote mode starts. Положено подешено - важи кад крене даљински режим. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Нема мрежа (само 2.4 GHz) No onboard GPS Нема уграђеног GPS No other networks found Нема других мрежа No position yet. A cold start needs a clear view of the sky and can take several minutes. Још нема позиције. Хладан старт тражи чист поглед на небо и може да потраје неколико минута. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Нема одговора од %s No reply. Check password, server,\nor device clock (device: %s) Нема одговора. Проверите лозинку, сервер\nили сат уређаја (уређај: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Овде нема сачуваних плочица.\n\nПовежите се на Wi-Fi (Подешавања → Wi-Fi)\nда преузмете ову област.\nСачуване плочице остају доступне ван мреже. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Недавно чути Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Форматирати SD као MESHCOMOD (FAT32)?\nСВИ подаци на картици биће обрисани. Region & scope Регион и опсег +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Опсег региона (#tag) за овај канал.\nПразно = подразумевани опсег. Region scope (#tag), blank = default. Опсег региона (#tag), празно = подразумевано. Region scope (#tag, blank = none) Опсег региона (#tag, празно = ниједан) diff --git a/deploy/apps/lang/uk.lang b/deploy/apps/lang/uk.lang index 7e0d9a1..ce1a244 100644 --- a/deploy/apps/lang/uk.lang +++ b/deploy/apps/lang/uk.lang @@ -282,6 +282,7 @@ End time Час завершення Enter SSID first Спочатку введіть SSID Enter a name Введіть ім'я Enter a network name Введіть назву мережі +Enter a region name Enter a region name Enter adds a new line Enter додає новий рядок Enter exactly 32 hex characters. Введіть рівно 32 hex-символи. Enter key sends message Клавіша Enter надсилає повідомлення @@ -407,6 +408,7 @@ Keyboard nav: WASDZ on Навігація клавіатурою: WASDZ увім Keyboard nav: off Навігація клавіатурою: вимк. Keyboard navigation Навігація клавіатурою Keys +Known regions Known regions LOS → %s Пряма видимість → %s Landscape (desktop) Альбомна (десктоп) Landscape set - applies when remote mode starts. Альбомну вибрано - застосується під час запуску віддаленого режиму. @@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Мережі не знайдено (лише 2. No onboard GPS Немає вбудованого GPS No other networks found Інших мереж не знайдено No position yet. A cold start needs a clear view of the sky and can take several minutes. Позиції ще немає. Холодний старт потребує відкритого неба і може тривати кілька хвилин. +No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No reply from %s Немає відповіді від %s No reply. Check password, server,\nor device clock (device: %s) Немає відповіді. Перевірте пароль, сервер\nабо годинник пристрою (пристрій: %s) No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Тут немає збережених плиток.\n\nПідключіться до Wi-Fi (Налаштування → Wi-Fi),\nщоб завантажити цю ділянку.\nЗбережені плитки лишаються доступні офлайн. @@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update Recently heard Нещодавно чуто Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Переформатувати SD як MESHCOMOD (FAT32)?\nУСІ дані на картці будуть стерті. Region & scope Регіон і охоплення +Region list is full Region list is full Region scope (#tag) for this channel.\nBlank = use the default scope. Регіон (#tag) для цього каналу.\nПорожньо = область за умовчанням. Region scope (#tag), blank = default. Область регіону (#tag), порожньо = за замовчуванням. Region scope (#tag, blank = none) Регіон (#tag, порожньо = немає) diff --git a/src/RegionRegistry.h b/src/RegionRegistry.h index 14e387b..d936931 100644 --- a/src/RegionRegistry.h +++ b/src/RegionRegistry.h @@ -49,13 +49,20 @@ #define REGION_REG_MAP_PATH "/region_map.dat" #define REGION_REG_SLOT_PATH "/region_slots.dat" -#define REGION_REG_SLOT_MAGIC 0x52475331UL // "RGS1" +#define REGION_REG_SLOT_MAGIC 0x52475331UL // "RGS1" — slots only +#define REGION_REG_SLOT_MAGIC2 0x52475332UL // "RGS2" — slots + active mask class RegionRegistry { TransportKeyStore _keys; RegionMap _map; // index = slot (1..REGION_SLOT_MAX); value = RegionEntry::id, 0 = free. + // A slot binding is PERMANENT once assigned. Removing a region clears its bit + // in _slot_active -- it stops being matched at RX -- but the binding stays, so + // messages received while it WAS registered still resolve to the right name. + // Freeing the slot for reuse would silently relabel that history, which is the + // failure #271 explicitly warns about. uint16_t _slot_id[REGION_SLOT_MAX + 1]; + uint16_t _slot_active = 0; // bit (slot-1) set => participates in matching FILESYSTEM* _fs = nullptr; bool _ready = false; @@ -80,14 +87,23 @@ class RegionRegistry { void loadSlots() { memset(_slot_id, 0, sizeof _slot_id); + _slot_active = 0; if (!_fs) return; File f = _fs->open(REGION_REG_SLOT_PATH, "r"); if (!f) return; uint32_t magic = 0; - if (f.read((uint8_t*)&magic, sizeof magic) == (int)sizeof magic && magic == REGION_REG_SLOT_MAGIC) + if (f.read((uint8_t*)&magic, sizeof magic) == (int)sizeof magic + && (magic == REGION_REG_SLOT_MAGIC || magic == REGION_REG_SLOT_MAGIC2)) { f.read((uint8_t*)_slot_id, sizeof _slot_id); - else + if (magic == REGION_REG_SLOT_MAGIC2) { + f.read((uint8_t*)&_slot_active, sizeof _slot_active); + } else { + for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) // pre-mask file: all assigned slots were live + if (_slot_id[s]) _slot_active |= (uint16_t)(1u << (s - 1)); + } + } else { memset(_slot_id, 0, sizeof _slot_id); + } f.close(); } @@ -109,9 +125,10 @@ public: _map.save(_fs, REGION_REG_MAP_PATH); File f = _fs->open(REGION_REG_SLOT_PATH, "w"); if (!f) return; - const uint32_t magic = REGION_REG_SLOT_MAGIC; + const uint32_t magic = REGION_REG_SLOT_MAGIC2; f.write((const uint8_t*)&magic, sizeof magic); f.write((const uint8_t*)_slot_id, sizeof _slot_id); + f.write((const uint8_t*)&_slot_active, sizeof _slot_active); f.close(); } @@ -127,10 +144,22 @@ public: if (!e) e = _map.putRegion(tag, 0); if (!e) return REGION_SLOT_NONE; - for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) // already slotted? - if (_slot_id[s] == e->id) return s; + for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) { // already slotted? + if (_slot_id[s] == e->id) { + // Re-adding a retired region revives its ORIGINAL slot rather than + // taking a new one, so its old messages and its new ones stay one region. + _slot_active |= (uint16_t)(1u << (s - 1)); + save(); + return s; + } + } for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) { // take the first free - if (_slot_id[s] == 0) { _slot_id[s] = e->id; save(); return s; } + if (_slot_id[s] == 0) { + _slot_id[s] = e->id; + _slot_active |= (uint16_t)(1u << (s - 1)); + save(); + return s; + } } return REGION_SLOT_NONE; // full: the message records "unknown", never a wrong name } @@ -144,7 +173,8 @@ public: uint8_t hit = REGION_SLOT_NONE; uint8_t n = 0; for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) { - if (_slot_id[s] == 0) continue; + if (_slot_id[s] == 0 || !isActive(s)) continue; // retired regions keep their + // name for history, but stop matching RegionEntry* e = const_cast(_map).findById(_slot_id[s]); if (!e) continue; TransportKey keys[4]; @@ -170,9 +200,34 @@ public: return (e && e->name[0]) ? e->name : nullptr; } + /** True when this slot currently takes part in matching. A retired slot still + * resolves via nameForSlot() so old messages keep their region name. */ + bool isActive(uint8_t slot) const { + if (slot == REGION_SLOT_NONE || slot > REGION_SLOT_MAX) return false; + return (_slot_active & (uint16_t)(1u << (slot - 1))) != 0; + } + + /** Stop matching this region. The slot binding and name are KEPT on purpose -- + * see the note on _slot_id. Returns false if the slot was never assigned. */ + bool retire(uint8_t slot) { + if (!_ready || slot == REGION_SLOT_NONE || slot > REGION_SLOT_MAX) return false; + if (_slot_id[slot] == 0) return false; + _slot_active &= (uint16_t)~(1u << (slot - 1)); + save(); + return true; + } + + /** Live regions (what the user sees as "the list"). */ int count() const { int n = 0; - for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) if (_slot_id[s]) n++; + for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) if (_slot_id[s] && isActive(s)) n++; return n; } + + /** True when every slot is assigned, so no NEW region can be added. Retired + * slots still count: their bindings are permanent. */ + bool isFull() const { + for (uint8_t s = 1; s <= REGION_SLOT_MAX; ++s) if (_slot_id[s] == 0) return false; + return true; + } }; diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index 7184ced..96af1b4 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -4829,6 +4829,7 @@ static void chanScopeClose(); // fwd static bool blockedModalIsOpen();// fwd: the bar's Back chevron also closes the blocked-users sheet static void blockedModalClose(); // fwd static void openBlockedUsersModal(); // ignore-list manager (unblock) +static void openRegionsModal(); // known-regions manager (#271) static bool overlayBlocksTabSwipe(); // theme/channel-scope pickers swallow tab swipes static bool drawerPopupOpen(); // popups floating over the app drawer (signal/mentions/power/files) static void refreshContactsList(); @@ -10600,6 +10601,25 @@ static void buildRadioSettings() { lv_obj_update_layout(note); y += lv_obj_get_height(note) + SC(8); } + // #271: the regions above are the ones we SEND under. This opens the list of + // regions we can RECOGNISE — naming them in message details needs only the + // name, since the key is derived from it. + { + lv_obj_t* rb = lv_btn_create(body); + lv_obj_set_size(rb, s_settings_content_w - SC(4), SC(34)); + lv_obj_set_pos(rb, 2, y); + styleButton(rb); + lv_obj_add_event_cb(rb, [](lv_event_t* e) { + if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; + closeSettingsModal(); + openRegionsModal(); + }, LV_EVENT_CLICKED, nullptr); + lv_obj_t* rl = lv_label_create(rb); + lv_label_set_text(rl, TR(LV_SYMBOL_LIST " Known regions")); + lv_obj_set_style_text_font(rl, &g_font_14, LV_PART_MAIN); + lv_obj_center(rl); + y += SC(40); + } // Opt-in: also scope DIRECT messages / logins / remote-management floods to the region // (not just channels). For networks where your only repeater re-floods a single region. @@ -44094,6 +44114,143 @@ static void blockedUnblockNameCb(lv_event_t* e) { } openBlockedUsersModal(); // rebuild the list } +// ---- Known regions manager (#271) ------------------------------------------- +// The list that makes scope naming possible. A region's key is derived from its +// NAME (SHA256("#tag")), so holding the name is enough to recompute an incoming +// packet's transport code and recognise it -- which is why adding a region here +// names its traffic even though we do not participate in it. +// +// Adding is the whole point of the feature; removing is deliberately "retire": +// the slot and name are kept so messages already received under that region keep +// resolving, it just stops being matched from now on. See RegionRegistry. +static lv_obj_t* s_regions_modal = nullptr; +static lv_obj_t* s_regions_ta = nullptr; +static void openRegionsModal(); // fwd: the add/remove callbacks rebuild the page + +static void regionsModalClose() { + if (s_regions_modal) { hideKb(); popupClose(&s_regions_modal); } + s_regions_ta = nullptr; + if (s_apppage_close == regionsModalClose) { + s_apppage_title = nullptr; s_apppage_close = nullptr; + statusBarSetTall(false); updateGlobalStatusBar(); + } +} +static void regionsAddCb(lv_event_t* e) { + if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; + if (!s_regions_ta) return; + const char* t = lv_textarea_get_text(s_regions_ta); + if (!t || !t[0]) { if (g_lv.task) g_lv.task->showAlert(TR("Enter a region name"), 1400); return; } + RegionRegistry& reg = the_mesh.regionRegistry(); + if (reg.ensureRegion(t) == REGION_SLOT_NONE) { + // Two different failures, and the user can only act on one of them: the list + // being full, or the name canonicalising away to nothing (blank, or a bare + // "#"). Say which rather than silently not adding a row. + if (g_lv.task) g_lv.task->showAlert(reg.isFull() ? TR("Region list is full") + : TR("Enter a region name"), 2000); + return; + } + openRegionsModal(); // rebuild (closes first) +} +static void regionsRemoveCb(lv_event_t* e) { + if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; + const uint8_t slot = (uint8_t)(intptr_t)lv_event_get_user_data(e); + the_mesh.regionRegistry().retire(slot); + openRegionsModal(); // rebuild +} + +static void openRegionsModal() { + regionsModalClose(); + const lv_coord_t sw = lv_disp_get_hor_res(nullptr); + const lv_coord_t sh = lv_disp_get_ver_res(nullptr); + s_regions_modal = lv_obj_create(lv_layer_top()); + lv_obj_remove_style_all(s_regions_modal); + lv_obj_set_size(s_regions_modal, sw, sh - chatBarH()); + lv_obj_set_pos(s_regions_modal, 0, chatBarH()); + lv_obj_set_style_bg_color(s_regions_modal, lv_color_hex(COLOR_BG), LV_PART_MAIN); + lv_obj_set_style_bg_opa(s_regions_modal, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_clear_flag(s_regions_modal, LV_OBJ_FLAG_SCROLLABLE); + + s_apppage_title = "Known regions"; + s_apppage_close = regionsModalClose; + statusBarSetTall(true); + updateGlobalStatusBar(); + lv_obj_move_foreground(s_regions_modal); + if (g_statusbar.root) lv_obj_move_foreground(g_statusbar.root); + + const lv_coord_t pad = SC(6); + lv_coord_t y = SC(6); + + // Add row: field + button on one line, so the common action is reachable + // without scrolling on the short panels too. + const lv_coord_t btn_w = SC(64); + s_regions_ta = lv_textarea_create(s_regions_modal); + lv_textarea_set_one_line(s_regions_ta, true); + lv_textarea_set_max_length(s_regions_ta, TOUCH_REGION_SCOPE_MAXLEN - 1); + lv_obj_set_size(s_regions_ta, sw - pad * 3 - btn_w, SC(32)); + lv_obj_set_pos(s_regions_ta, pad, y); + taSetPlaceholder(s_regions_ta, TR("#region")); + attachSettingsTaEvents(s_regions_ta); + + lv_obj_t* add = lv_btn_create(s_regions_modal); + lv_obj_set_size(add, btn_w, SC(32)); + lv_obj_set_pos(add, sw - pad - btn_w, y); + styleButton(add); + lv_obj_add_event_cb(add, regionsAddCb, LV_EVENT_CLICKED, nullptr); + { lv_obj_t* l = lv_label_create(add); lv_label_set_text(l, TR("Add")); + lv_obj_set_style_text_font(l, &g_font_12, LV_PART_MAIN); lv_obj_center(l); } + y += SC(38); + + RegionRegistry& reg = the_mesh.regionRegistry(); + if (reg.count() <= 0) { + lv_obj_t* empty = lv_label_create(s_regions_modal); + lv_label_set_text(empty, TR("No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.")); + lv_label_set_long_mode(empty, LV_LABEL_LONG_WRAP); + lv_obj_set_width(empty, sw - pad * 2); + lv_obj_set_style_text_color(empty, lv_color_hex(COLOR_SUB), LV_PART_MAIN); + lv_obj_set_style_text_font(empty, &g_font_12, LV_PART_MAIN); + lv_obj_set_pos(empty, pad, y); + return; + } + + lv_obj_t* list = lv_obj_create(s_regions_modal); + lv_obj_remove_style_all(list); + lv_obj_set_size(list, sw - pad * 2, sh - chatBarH() - y - SC(6)); + lv_obj_set_pos(list, pad, y); + lv_obj_set_flex_flow(list, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_row(list, SC(5), LV_PART_MAIN); + lv_obj_set_scroll_dir(list, LV_DIR_VER); + + for (uint8_t slot = 1; slot <= REGION_SLOT_MAX; ++slot) { + if (!reg.isActive(slot)) continue; + const char* nm = reg.nameForSlot(slot); + if (!nm || !nm[0]) continue; + + lv_obj_t* row = lv_obj_create(list); + lv_obj_remove_style_all(row); + lv_obj_set_size(row, sw - pad * 2 - SC(4), SC(36)); + lv_obj_set_style_bg_color(row, lv_color_hex(COLOR_PANEL), LV_PART_MAIN); + lv_obj_set_style_bg_opa(row, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_radius(row, 6, LV_PART_MAIN); + lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE); + + lv_obj_t* lbl = lv_label_create(row); + lv_label_set_text(lbl, nm); + lv_label_set_long_mode(lbl, LV_LABEL_LONG_DOT); + lv_obj_set_width(lbl, sw - pad * 2 - SC(4) - SC(84)); + lv_obj_set_style_text_color(lbl, lv_color_hex(COLOR_TEXT), LV_PART_MAIN); + lv_obj_set_style_text_font(lbl, &g_font_14, LV_PART_MAIN); + lv_obj_align(lbl, LV_ALIGN_LEFT_MID, SC(6), 0); + + lv_obj_t* rm = lv_btn_create(row); + lv_obj_set_size(rm, SC(72), SC(28)); + lv_obj_align(rm, LV_ALIGN_RIGHT_MID, -SC(5), 0); + styleButton(rm); + lv_obj_add_event_cb(rm, regionsRemoveCb, LV_EVENT_CLICKED, (void*)(intptr_t)slot); + { lv_obj_t* l = lv_label_create(rm); lv_label_set_text(l, TR("Remove")); + lv_obj_set_style_text_font(l, &g_font_12, LV_PART_MAIN); lv_obj_center(l); } + } +} + static void openBlockedUsersModal() { blockedModalClose(); const lv_coord_t sw = lv_disp_get_hor_res(nullptr);