mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
Merge pull request #217 from MeshEnvy/chrome/main
enh: Chrome compatibility
This commit is contained in:
commit
6bd3c17cdf
48 changed files with 399 additions and 31 deletions
38
.github/workflows/deploy.yml
vendored
Normal file
38
.github/workflows/deploy.yml
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
name: Deploy to Cloudflare Workers
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
# Match local development version which provides Dart 3.11.0
|
||||
flutter-version: '3.41.2'
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Get dependencies
|
||||
run: flutter pub get
|
||||
|
||||
- name: Build Web
|
||||
run: bun run build
|
||||
|
||||
- name: Deploy to Cloudflare
|
||||
uses: cloudflare/wrangler-action@v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: deploy
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -83,3 +83,6 @@ keystore.properties
|
|||
# IDE
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
|
||||
# Cloudflare Wrangler
|
||||
.wrangler
|
||||
|
|
@ -717,17 +717,13 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
|
||||
_scanSubscription = FlutterBluePlus.scanResults.listen((results) {
|
||||
_scanResults.clear();
|
||||
for (var result in results) {
|
||||
if (result.device.platformName.startsWith("MeshCore-") ||
|
||||
result.advertisementData.advName.startsWith("MeshCore-") ||
|
||||
result.advertisementData.advName.startsWith("Whisper-")) {
|
||||
_scanResults.add(result);
|
||||
}
|
||||
}
|
||||
_scanResults.addAll(results);
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
await FlutterBluePlus.startScan(
|
||||
withKeywords: ["MeshCore-", "Whisper-"],
|
||||
webOptionalServices: [Guid(MeshCoreUuids.service)],
|
||||
timeout: timeout,
|
||||
androidScanMode: AndroidScanMode.lowLatency,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1606,6 +1606,8 @@
|
|||
"scanner_bluetoothOff": "Bluetooth е изключен.",
|
||||
"scanner_enableBluetooth": "Активирайте Bluetooth",
|
||||
"scanner_bluetoothOffMessage": "Моля, активирайте Bluetooth, за да сканирате за устройства.",
|
||||
"scanner_chromeRequired": "Изисква се браузър Chrome",
|
||||
"scanner_chromeRequiredMessage": "Това уеб приложение изисква Google Chrome или браузър, базиран на Chromium, за поддръжка на Bluetooth.",
|
||||
"snrIndicator_lastSeen": "Последно видян",
|
||||
"snrIndicator_nearByRepeaters": "Близки повтарящи се устройства",
|
||||
"chat_ShowAllPaths": "Покажи всички пътища",
|
||||
|
|
|
|||
|
|
@ -1635,6 +1635,8 @@
|
|||
"pathTrace_clearTooltip": "Pfad löschen",
|
||||
"map_pathTraceCancelled": "Pfadverfolgung abgebrochen.",
|
||||
"scanner_bluetoothOffMessage": "Bitte aktivieren Sie Bluetooth, um nach Geräten zu suchen.",
|
||||
"scanner_chromeRequired": "Chrome Browser erforderlich",
|
||||
"scanner_chromeRequiredMessage": "Diese Webanwendung erfordert Google Chrome oder einen Chromium-basierten Browser für die Bluetooth-Unterstützung.",
|
||||
"scanner_bluetoothOff": "Bluetooth ist deaktiviert.",
|
||||
"scanner_enableBluetooth": "Bluetooth aktivieren",
|
||||
"snrIndicator_lastSeen": "Zuletzt gesehen",
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@
|
|||
"scanner_scan": "Scan",
|
||||
"scanner_bluetoothOff": "Bluetooth is off",
|
||||
"scanner_bluetoothOffMessage": "Please turn on Bluetooth to scan for devices",
|
||||
"scanner_chromeRequired": "Chrome Browser Required",
|
||||
"scanner_chromeRequiredMessage": "This web application requires Google Chrome or a Chromium-based browser for Bluetooth support.",
|
||||
"scanner_enableBluetooth": "Enable Bluetooth",
|
||||
"device_quickSwitch": "Quick switch",
|
||||
"device_meshcore": "MeshCore",
|
||||
|
|
|
|||
|
|
@ -1632,6 +1632,8 @@
|
|||
"map_removeLast": "Eliminar último",
|
||||
"map_pathTraceCancelled": "Rastreo de ruta cancelado.",
|
||||
"scanner_bluetoothOffMessage": "Por favor, active el Bluetooth para escanear dispositivos.",
|
||||
"scanner_chromeRequired": "Navegador Chrome requerido",
|
||||
"scanner_chromeRequiredMessage": "Esta aplicación web requiere Google Chrome o un navegador basado en Chromium para el soporte de Bluetooth.",
|
||||
"scanner_bluetoothOff": "Bluetooth está desactivado.",
|
||||
"scanner_enableBluetooth": "Habilitar Bluetooth",
|
||||
"snrIndicator_nearByRepeaters": "Repetidores cercanos",
|
||||
|
|
|
|||
|
|
@ -1604,6 +1604,8 @@
|
|||
"map_removeLast": "Supprimer le dernier",
|
||||
"map_runTrace": "Exécuter la traçage de chemin",
|
||||
"scanner_bluetoothOffMessage": "Veuillez activer le Bluetooth pour rechercher des appareils.",
|
||||
"scanner_chromeRequired": "Navigateur Chrome requis",
|
||||
"scanner_chromeRequiredMessage": "Cette application web nécessite Google Chrome ou un navigateur basé sur Chromium pour le support Bluetooth.",
|
||||
"scanner_bluetoothOff": "Le Bluetooth est désactivé.",
|
||||
"scanner_enableBluetooth": "Activer le Bluetooth",
|
||||
"snrIndicator_lastSeen": "Dernière fois vu",
|
||||
|
|
|
|||
|
|
@ -1605,6 +1605,8 @@
|
|||
"map_tapToAdd": "Tocca i nodi per aggiungerli al percorso.",
|
||||
"scanner_bluetoothOff": "Il Bluetooth è disattivato.",
|
||||
"scanner_bluetoothOffMessage": "Si prega di attivare il Bluetooth per effettuare la scansione dei dispositivi.",
|
||||
"scanner_chromeRequired": "Browser Chrome richiesto",
|
||||
"scanner_chromeRequiredMessage": "Questa applicazione web richiede Google Chrome o un browser basato su Chromium per il supporto Bluetooth.",
|
||||
"scanner_enableBluetooth": "Abilita il Bluetooth",
|
||||
"snrIndicator_nearByRepeaters": "Ripetitori vicini",
|
||||
"snrIndicator_lastSeen": "Ultimo accesso",
|
||||
|
|
|
|||
|
|
@ -388,6 +388,18 @@ abstract class AppLocalizations {
|
|||
/// **'Please turn on Bluetooth to scan for devices'**
|
||||
String get scanner_bluetoothOffMessage;
|
||||
|
||||
/// No description provided for @scanner_chromeRequired.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Chrome Browser Required'**
|
||||
String get scanner_chromeRequired;
|
||||
|
||||
/// No description provided for @scanner_chromeRequiredMessage.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'This web application requires Google Chrome or a Chromium-based browser for Bluetooth support.'**
|
||||
String get scanner_chromeRequiredMessage;
|
||||
|
||||
/// No description provided for @scanner_enableBluetooth.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsBg extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Моля, активирайте Bluetooth, за да сканирате за устройства.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Изисква се браузър Chrome';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Това уеб приложение изисква Google Chrome или браузър, базиран на Chromium, за поддръжка на Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Активирайте Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Bitte aktivieren Sie Bluetooth, um nach Geräten zu suchen.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Chrome Browser erforderlich';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Diese Webanwendung erfordert Google Chrome oder einen Chromium-basierten Browser für die Bluetooth-Unterstützung.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Bluetooth aktivieren';
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,13 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Please turn on Bluetooth to scan for devices';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Chrome Browser Required';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'This web application requires Google Chrome or a Chromium-based browser for Bluetooth support.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Enable Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Por favor, active el Bluetooth para escanear dispositivos.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Navegador Chrome requerido';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Esta aplicación web requiere Google Chrome o un navegador basado en Chromium para el soporte de Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Habilitar Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Veuillez activer le Bluetooth pour rechercher des appareils.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Navigateur Chrome requis';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Cette application web nécessite Google Chrome ou un navigateur basé sur Chromium pour le support Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Activer le Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Si prega di attivare il Bluetooth per effettuare la scansione dei dispositivi.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Browser Chrome richiesto';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Questa applicazione web richiede Google Chrome o un browser basato su Chromium per il supporto Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Abilita il Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,13 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Zorg ervoor dat Bluetooth is ingeschakeld om naar apparaten te zoeken.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Chrome-browser vereist';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Deze webapplicatie vereist Google Chrome of een op Chromium gebaseerde browser voor Bluetooth-ondersteuning.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Activeer Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Prosimy włączyć Bluetooth, aby przeskanować urządzenia.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Wymagana przeglądarka Chrome';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Ta aplikacja internetowa wymaga przeglądarki Google Chrome lub opartej na Chromium do obsługi Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Włącz Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Por favor, ative o Bluetooth para escanear por dispositivos.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Navegador Chrome necessário';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Esta aplicação web requer o Google Chrome ou um navegador baseado no Chromium para suporte de Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Ative o Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,13 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Пожалуйста, включите Bluetooth, чтобы найти устройства.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Требуется браузер Chrome';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Для поддержки Bluetooth в этом веб-приложении требуется Google Chrome или браузер на базе Chromium.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Включите Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsSk extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Prosím, zapnite Bluetooth, aby ste mohli skenovať pre zariadenia.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Vyžaduje sa prehliadač Chrome';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Táto webová aplikácia vyžaduje Google Chrome alebo prehliadač založený na Chromium pre podporu Bluetooth.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Povolte Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Prosimo, vklopite Bluetooth, da lahko poiščete naprave.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Zahtevan brskalnik Chrome';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Ta spletna aplikacija za podporo Bluetooth zahteva Google Chrome ali brskalnik na osnovi Chromiuma.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Omogočite Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,13 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Vänligen aktivera Bluetooth för att söka efter enheter.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Chrome-webbläsare krävs';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Denna webbapplikation kräver Google Chrome oder en Chromium-baserader webbläsare för Bluetooth-stöd.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Aktivera Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,13 @@ class AppLocalizationsUk extends AppLocalizations {
|
|||
String get scanner_bluetoothOffMessage =>
|
||||
'Будь ласка, увімкніть Bluetooth, щоб сканувати пристрої.';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => 'Потрібен браузер Chrome';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'Для підтримки Bluetooth у цьому веб-додатку потрібен Google Chrome або браузер на базі Chromium.';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => 'Увімкніть Bluetooth';
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,13 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||
@override
|
||||
String get scanner_bluetoothOffMessage => '请开启蓝牙以搜索设备';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequired => '需要 Chrome 浏览器';
|
||||
|
||||
@override
|
||||
String get scanner_chromeRequiredMessage =>
|
||||
'此 Web 应用程序需要 Google Chrome 或基于 Chromium 的浏览器以支持蓝牙。';
|
||||
|
||||
@override
|
||||
String get scanner_enableBluetooth => '启用蓝牙';
|
||||
|
||||
|
|
|
|||
|
|
@ -1605,6 +1605,8 @@
|
|||
"map_runTrace": "Padeshulp traceren",
|
||||
"scanner_enableBluetooth": "Activeer Bluetooth",
|
||||
"scanner_bluetoothOffMessage": "Zorg ervoor dat Bluetooth is ingeschakeld om naar apparaten te zoeken.",
|
||||
"scanner_chromeRequired": "Chrome-browser vereist",
|
||||
"scanner_chromeRequiredMessage": "Deze webapplicatie vereist Google Chrome of een op Chromium gebaseerde browser voor Bluetooth-ondersteuning.",
|
||||
"scanner_bluetoothOff": "Bluetooth is uitgeschakeld",
|
||||
"snrIndicator_lastSeen": "Laatst gezien",
|
||||
"snrIndicator_nearByRepeaters": "Nabije herhalingseenheden",
|
||||
|
|
|
|||
|
|
@ -1604,6 +1604,8 @@
|
|||
"map_removeLast": "Usuń ostatni",
|
||||
"map_tapToAdd": "Kliknij na węzły, aby dodać je do ścieżki.",
|
||||
"scanner_bluetoothOffMessage": "Prosimy włączyć Bluetooth, aby przeskanować urządzenia.",
|
||||
"scanner_chromeRequired": "Wymagana przeglądarka Chrome",
|
||||
"scanner_chromeRequiredMessage": "Ta aplikacja internetowa wymaga przeglądarki Google Chrome lub opartej na Chromium do obsługi Bluetooth.",
|
||||
"scanner_bluetoothOff": "Bluetooth jest wyłączony",
|
||||
"scanner_enableBluetooth": "Włącz Bluetooth",
|
||||
"snrIndicator_lastSeen": "Ostatnio widziany",
|
||||
|
|
|
|||
|
|
@ -1606,6 +1606,8 @@
|
|||
"scanner_enableBluetooth": "Ative o Bluetooth",
|
||||
"scanner_bluetoothOff": "Bluetooth está desativado",
|
||||
"scanner_bluetoothOffMessage": "Por favor, ative o Bluetooth para escanear por dispositivos.",
|
||||
"scanner_chromeRequired": "Navegador Chrome necessário",
|
||||
"scanner_chromeRequiredMessage": "Esta aplicação web requer o Google Chrome ou um navegador baseado no Chromium para suporte de Bluetooth.",
|
||||
"snrIndicator_nearByRepeaters": "Repetidores Próximos",
|
||||
"snrIndicator_lastSeen": "Visto pela última vez",
|
||||
"chat_ShowAllPaths": "Mostrar todos os caminhos",
|
||||
|
|
|
|||
|
|
@ -846,6 +846,8 @@
|
|||
"scanner_enableBluetooth": "Включите Bluetooth",
|
||||
"scanner_bluetoothOff": "Bluetooth выключен",
|
||||
"scanner_bluetoothOffMessage": "Пожалуйста, включите Bluetooth, чтобы найти устройства.",
|
||||
"scanner_chromeRequired": "Требуется браузер Chrome",
|
||||
"scanner_chromeRequiredMessage": "Для поддержки Bluetooth в этом веб-приложении требуется Google Chrome или браузер на базе Chromium.",
|
||||
"snrIndicator_nearByRepeaters": "Ближайшие ретрансляторы",
|
||||
"snrIndicator_lastSeen": "Последний раз видели",
|
||||
"chat_ShowAllPaths": "Показать все пути",
|
||||
|
|
|
|||
|
|
@ -1604,6 +1604,8 @@
|
|||
"map_runTrace": "Spustiť trasovaním cesty",
|
||||
"map_pathTraceCancelled": "Zrušenie stopáže cesty bolo zrušené.",
|
||||
"scanner_bluetoothOffMessage": "Prosím, zapnite Bluetooth, aby ste mohli skenovať pre zariadenia.",
|
||||
"scanner_chromeRequired": "Vyžaduje sa prehliadač Chrome",
|
||||
"scanner_chromeRequiredMessage": "Táto webová aplikácia vyžaduje Google Chrome alebo prehliadač založený na Chromium pre podporu Bluetooth.",
|
||||
"scanner_bluetoothOff": "Bluetooth je vypnutý",
|
||||
"scanner_enableBluetooth": "Povolte Bluetooth",
|
||||
"snrIndicator_lastSeen": "Naposledy videný",
|
||||
|
|
|
|||
|
|
@ -1605,6 +1605,8 @@
|
|||
"map_pathTraceCancelled": "Spremljanje poti je prekinjeno.",
|
||||
"scanner_enableBluetooth": "Omogočite Bluetooth",
|
||||
"scanner_bluetoothOffMessage": "Prosimo, vklopite Bluetooth, da lahko poiščete naprave.",
|
||||
"scanner_chromeRequired": "Zahtevan brskalnik Chrome",
|
||||
"scanner_chromeRequiredMessage": "Ta spletna aplikacija za podporo Bluetooth zahteva Google Chrome ali brskalnik na osnovi Chromiuma.",
|
||||
"scanner_bluetoothOff": "Bluetooth je izklopljen",
|
||||
"snrIndicator_lastSeen": "Zadnjič videno",
|
||||
"snrIndicator_nearByRepeaters": "Bližnji ponovitelji",
|
||||
|
|
|
|||
|
|
@ -1605,6 +1605,8 @@
|
|||
"map_removeLast": "Ta bort sista",
|
||||
"scanner_enableBluetooth": "Aktivera Bluetooth",
|
||||
"scanner_bluetoothOffMessage": "Vänligen aktivera Bluetooth för att söka efter enheter.",
|
||||
"scanner_chromeRequired": "Chrome-webbläsare krävs",
|
||||
"scanner_chromeRequiredMessage": "Denna webbapplikation kräver Google Chrome oder en Chromium-baserader webbläsare för Bluetooth-stöd.",
|
||||
"scanner_bluetoothOff": "Bluetooth är avstängt",
|
||||
"snrIndicator_lastSeen": "Senast sedd",
|
||||
"snrIndicator_nearByRepeaters": "Närliggande uppreparstationer",
|
||||
|
|
|
|||
|
|
@ -1605,6 +1605,8 @@
|
|||
"map_pathTraceCancelled": "Відмінується трасування шляху",
|
||||
"scanner_enableBluetooth": "Увімкніть Bluetooth",
|
||||
"scanner_bluetoothOffMessage": "Будь ласка, увімкніть Bluetooth, щоб сканувати пристрої.",
|
||||
"scanner_chromeRequired": "Потрібен браузер Chrome",
|
||||
"scanner_chromeRequiredMessage": "Для підтримки Bluetooth у цьому веб-додатку потрібен Google Chrome або браузер на базі Chromium.",
|
||||
"scanner_bluetoothOff": "Bluetooth вимкнено",
|
||||
"snrIndicator_lastSeen": "Останній раз бачили",
|
||||
"snrIndicator_nearByRepeaters": "Ближні ретранслятори",
|
||||
|
|
|
|||
|
|
@ -1609,6 +1609,8 @@
|
|||
"map_removeLast": "移除最后一个",
|
||||
"map_runTrace": "运行路径追踪",
|
||||
"scanner_bluetoothOffMessage": "请开启蓝牙以搜索设备",
|
||||
"scanner_chromeRequired": "需要 Chrome 浏览器",
|
||||
"scanner_chromeRequiredMessage": "此 Web 应用程序需要 Google Chrome 或基于 Chromium 的浏览器以支持蓝牙。",
|
||||
"scanner_bluetoothOff": "蓝牙已关闭",
|
||||
"scanner_enableBluetooth": "启用蓝牙",
|
||||
"snrIndicator_lastSeen": "最近访问",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import 'package:flutter/foundation.dart';
|
|||
import 'l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'screens/chrome_required_screen.dart';
|
||||
import 'utils/platform_info.dart';
|
||||
|
||||
import 'connector/meshcore_connector.dart';
|
||||
import 'screens/scanner_screen.dart';
|
||||
import 'services/storage_service.dart';
|
||||
|
|
@ -187,7 +190,9 @@ class MeshCoreApp extends StatelessWidget {
|
|||
NotificationService().setLocale(locale);
|
||||
return child ?? const SizedBox.shrink();
|
||||
},
|
||||
home: const ScannerScreen(),
|
||||
home: (PlatformInfo.isWeb && !PlatformInfo.isChrome)
|
||||
? const ChromeRequiredScreen()
|
||||
: const ScannerScreen(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
89
lib/screens/chrome_required_screen.dart
Normal file
89
lib/screens/chrome_required_screen.dart
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import '../l10n/l10n.dart';
|
||||
|
||||
class ChromeRequiredScreen extends StatelessWidget {
|
||||
const ChromeRequiredScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final theme = Theme.of(context);
|
||||
final isDark = theme.brightness == Brightness.dark;
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: isDark
|
||||
? [const Color(0xFF1A1A1A), const Color(0xFF0D0D0D)]
|
||||
: [const Color(0xFFF5F7FA), const Color(0xFFE4E7EB)],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange.withValues(alpha: 0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.browser_not_supported_rounded,
|
||||
size: 80,
|
||||
color: Colors.orange,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
Text(
|
||||
l10n.scanner_chromeRequired,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : Colors.black87,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
l10n.scanner_chromeRequiredMessage,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyLarge?.copyWith(
|
||||
color: isDark ? Colors.white70 : Colors.black54,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 48),
|
||||
// We can't really "fix" it for them other than telling them to use Chrome
|
||||
// but we can provide a nice visual.
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
border: Border.all(color: Colors.blue.withValues(alpha: 0.3)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.info_outline, size: 20, color: Colors.blue),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
"Web Bluetooth requires a Chromium browser",
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.blue,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../utils/platform_info.dart';
|
||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
|
@ -46,17 +45,22 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
|
||||
connector.addListener(_connectionListener);
|
||||
|
||||
_bluetoothStateSubscription = FlutterBluePlus.adapterState.listen((state) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_bluetoothState = state;
|
||||
});
|
||||
// Cancel scan if Bluetooth turns off while scanning
|
||||
if (state != BluetoothAdapterState.on) {
|
||||
unawaited(connector.stopScan());
|
||||
_bluetoothStateSubscription = FlutterBluePlus.adapterState.listen(
|
||||
(state) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_bluetoothState = state;
|
||||
});
|
||||
// Cancel scan if Bluetooth turns off while scanning
|
||||
if (state != BluetoothAdapterState.on) {
|
||||
unawaited(connector.stopScan());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
onError: (Object e) {
|
||||
debugPrint("Scanner adapterState stream error: $e");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -108,7 +112,11 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
if (isScanning) {
|
||||
connector.stopScan();
|
||||
} else {
|
||||
connector.startScan();
|
||||
unawaited(
|
||||
connector.startScan().catchError((e) {
|
||||
debugPrint("Scanner screen startScan error: $e");
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
icon: isScanning
|
||||
|
|
@ -265,7 +273,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
],
|
||||
),
|
||||
),
|
||||
if (Platform.isAndroid)
|
||||
if (PlatformInfo.isAndroid)
|
||||
TextButton(
|
||||
onPressed: () => FlutterBluePlus.turnOn(),
|
||||
child: Text(context.l10n.scanner_enableBluetooth),
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import '../utils/platform_info.dart';
|
||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
|
||||
class BackgroundService {
|
||||
bool _initialized = false;
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (!Platform.isAndroid || _initialized) return;
|
||||
if (!PlatformInfo.isAndroid || _initialized) return;
|
||||
FlutterForegroundTask.init(
|
||||
androidNotificationOptions: AndroidNotificationOptions(
|
||||
channelId: 'meshcore_background',
|
||||
|
|
@ -29,7 +28,7 @@ class BackgroundService {
|
|||
}
|
||||
|
||||
Future<void> start() async {
|
||||
if (!Platform.isAndroid) return;
|
||||
if (!PlatformInfo.isAndroid) return;
|
||||
if (!_initialized) {
|
||||
await initialize();
|
||||
}
|
||||
|
|
@ -43,7 +42,7 @@ class BackgroundService {
|
|||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
if (!Platform.isAndroid) return;
|
||||
if (!PlatformInfo.isAndroid) return;
|
||||
final running = await FlutterForegroundTask.isRunningService;
|
||||
if (!running) return;
|
||||
await FlutterForegroundTask.stopService();
|
||||
|
|
|
|||
2
lib/utils/browser_detection.dart
Normal file
2
lib/utils/browser_detection.dart
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export 'browser_detection_stub.dart'
|
||||
if (dart.library.js_interop) 'browser_detection_web.dart';
|
||||
3
lib/utils/browser_detection_stub.dart
Normal file
3
lib/utils/browser_detection_stub.dart
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
class BrowserDetection {
|
||||
static bool get isChrome => false;
|
||||
}
|
||||
9
lib/utils/browser_detection_web.dart
Normal file
9
lib/utils/browser_detection_web.dart
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import 'package:web/web.dart' as web;
|
||||
|
||||
class BrowserDetection {
|
||||
static bool get isChrome {
|
||||
final userAgent = web.window.navigator.userAgent.toLowerCase();
|
||||
final isChrome = userAgent.contains('chrome');
|
||||
return isChrome;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import 'package:meshcore_open/connector/meshcore_connector.dart';
|
|||
import 'package:meshcore_open/connector/meshcore_protocol.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'dart:io';
|
||||
import '../utils/platform_info.dart';
|
||||
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
|
|
@ -109,6 +110,10 @@ class GpxExport {
|
|||
String shareText,
|
||||
String subject,
|
||||
) async {
|
||||
if (PlatformInfo.isWeb) {
|
||||
debugPrint("GPX export is not supported on Web.");
|
||||
return gpxExportNotAvailable;
|
||||
}
|
||||
if (_contacts.isEmpty) {
|
||||
debugPrint("No repeaters to export – nothing to share.");
|
||||
return gpxExportNoContacts;
|
||||
|
|
|
|||
36
lib/utils/platform_info.dart
Normal file
36
lib/utils/platform_info.dart
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'dart:io' show Platform;
|
||||
import 'browser_detection.dart';
|
||||
|
||||
/// Utility class to safely check the current platform across web and native.
|
||||
///
|
||||
/// Using `Platform` from `dart:io` directly on Web causes a crash.
|
||||
/// This class handles the `kIsWeb` check first to avoid those crashes.
|
||||
class PlatformInfo {
|
||||
/// Whether the app is running in a web browser.
|
||||
static bool get isWeb => kIsWeb;
|
||||
|
||||
/// Whether the app is running in the Chrome browser (only relevant if [isWeb] is true).
|
||||
static bool get isChrome => isWeb && BrowserDetection.isChrome;
|
||||
|
||||
/// Whether the app is running on Android.
|
||||
static bool get isAndroid => !kIsWeb && Platform.isAndroid;
|
||||
|
||||
/// Whether the app is running on iOS.
|
||||
static bool get isIOS => !kIsWeb && Platform.isIOS;
|
||||
|
||||
/// Whether the app is running on macOS.
|
||||
static bool get isMacOS => !kIsWeb && Platform.isMacOS;
|
||||
|
||||
/// Whether the app is running on Windows.
|
||||
static bool get isWindows => !kIsWeb && Platform.isWindows;
|
||||
|
||||
/// Whether the app is running on Linux.
|
||||
static bool get isLinux => !kIsWeb && Platform.isLinux;
|
||||
|
||||
/// Whether the app is running on a mobile platform (Android or iOS).
|
||||
static bool get isMobile => isAndroid || isIOS;
|
||||
|
||||
/// Whether the app is running on a desktop platform (macOS, Windows, or Linux).
|
||||
static bool get isDesktop => isMacOS || isWindows || isLinux;
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import '../utils/platform_info.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -326,8 +327,7 @@ class _RepeaterLoginDialogState extends State<RepeaterLoginDialog> {
|
|||
},
|
||||
onSubmitted: (_) => _handleLogin(),
|
||||
autofocus:
|
||||
!(defaultTargetPlatform == TargetPlatform.android ||
|
||||
defaultTargetPlatform == TargetPlatform.iOS) &&
|
||||
!PlatformInfo.isMobile &&
|
||||
_passwordController.text.isEmpty,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import '../utils/platform_info.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -274,8 +275,7 @@ class _RoomLoginDialogState extends State<RoomLoginDialog> {
|
|||
),
|
||||
onSubmitted: (_) => _handleLogin(),
|
||||
autofocus:
|
||||
!(defaultTargetPlatform == TargetPlatform.android ||
|
||||
defaultTargetPlatform == TargetPlatform.iOS) &&
|
||||
!PlatformInfo.isMobile &&
|
||||
_passwordController.text.isEmpty,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
|
|
|||
7
package.json
Normal file
7
package.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "meshcore-open",
|
||||
"scripts": {
|
||||
"build": "dart run build_pipe:build",
|
||||
"deploy": "bun x wrangler deploy"
|
||||
}
|
||||
}
|
||||
14
pubspec.yaml
14
pubspec.yaml
|
|
@ -60,6 +60,7 @@ dependencies:
|
|||
gpx: ^2.3.0
|
||||
path_provider: ^2.1.5
|
||||
share_plus: ^12.0.1
|
||||
build_pipe: ^0.3.1
|
||||
material_symbols_icons: ^4.2906.0
|
||||
web: ^1.1.1
|
||||
flutter_svg: ^2.0.10+1
|
||||
|
|
@ -128,3 +129,16 @@ flutter_launcher_icons:
|
|||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/to/font-from-package
|
||||
|
||||
build_pipe:
|
||||
workflows:
|
||||
default:
|
||||
clean_flutter: true # Optional: Cleans old build artifacts before running
|
||||
generate_log: true # Optional: Outputs a build log file for debugging
|
||||
platforms:
|
||||
web:
|
||||
build:
|
||||
build_command: flutter build web --release --pwa-strategy=none
|
||||
# Strongly recommended: disables the default service worker which often causes more cache headaches
|
||||
add_version_query_param: true
|
||||
# This is the key flag! It appends ?v=<your pubspec version> to bootstrap/JS files
|
||||
7
wrangler.toml
Normal file
7
wrangler.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#:schema node_modules/wrangler/config-schema.json
|
||||
name = "meshcore"
|
||||
compatibility_date = "2025-10-08"
|
||||
|
||||
[assets]
|
||||
directory = "build/web"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue