diff --git a/HeliPort.xcodeproj/project.pbxproj b/HeliPort.xcodeproj/project.pbxproj index d341258..007fac3 100644 --- a/HeliPort.xcodeproj/project.pbxproj +++ b/HeliPort.xcodeproj/project.pbxproj @@ -729,7 +729,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2.3; + CURRENT_PROJECT_VERSION = 23; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = CPMQGF4D2A; ENABLE_HARDENED_RUNTIME = YES; @@ -738,7 +738,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3; + MARKETING_VERSION = 2.3.0; PRODUCT_BUNDLE_IDENTIFIER = com.joshc.HeliPort; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -758,7 +758,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2.3; + CURRENT_PROJECT_VERSION = 23; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = CPMQGF4D2A; ENABLE_HARDENED_RUNTIME = YES; @@ -767,7 +767,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3; + MARKETING_VERSION = 2.3.0; PRODUCT_BUNDLE_IDENTIFIER = com.joshc.HeliPort; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/HeliPort/Appearance/Localizable.xcstrings b/HeliPort/Appearance/Localizable.xcstrings index e5ca5f6..8224e75 100644 --- a/HeliPort/Appearance/Localizable.xcstrings +++ b/HeliPort/Appearance/Localizable.xcstrings @@ -2374,6 +2374,119 @@ } } }, + "Channel" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "قناة" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kanál" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kanal" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Κανάλι" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Canal" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Canal" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kanal" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Canale" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "채널" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kanał" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Canal" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Canal" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Canal" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Канал" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kanal" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Канал" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kênh" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "信道" + } + } + } + }, "Check for Updates..." : { "extractionState" : "manual", "localizations" : { @@ -2624,11 +2737,113 @@ }, "Connected" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "متصل" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Připojeno" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbunden" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Συνδεδεμένο" + } + }, "es" : { "stringUnit" : { "state" : "translated", "value" : "Conectado" } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connecté" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tersambung" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "connesso" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "연결됨" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "połączono" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Conectado" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Conectado" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Conectat" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Подключен" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bağlandı" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Підключено" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Đã kết nối" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已连接" + } } } }, @@ -4339,203 +4554,316 @@ } } }, - "itlwm API Version: " : { + "IP Address" : { "extractionState" : "manual", "localizations" : { "ar" : { "stringUnit" : { "state" : "translated", - "value" : "إصدار itlwm API " + "value" : "عنوان IP" } }, "cs" : { "stringUnit" : { "state" : "translated", - "value" : "Verze itlwm API: " + "value" : "IP Adresa" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IP-Adresse" } }, "el" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm API Έκδοση: " + "value" : "Διεύθυνση IP" } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "Versión del API de itlwm: " + "value" : "Dirección IP" } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "Version de l'API d'itlwm: " + "value" : "Adresse IP" } }, "id" : { "stringUnit" : { "state" : "translated", - "value" : "Versi API itlwm: " + "value" : "Alamat IP" } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "Versione API di itlwm: " + "value" : "Indirizzo IP" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "IP 주소" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adres IP" } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Versão da API do itlwm: " + "value" : "Endereço IP" } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Versão de API do itlwm: " + "value" : "Endereço IP" } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "Versiune API itlwm: " + "value" : "Adresă IP" } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "Версия itlwm API: " + "value" : "IP адрес" } }, "tr" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm API Versiyonu: " + "value" : "IP Adresi" } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "Версія itlwm API: " + "value" : "IP адреса" } }, "vi" : { "stringUnit" : { "state" : "translated", - "value" : "Phiên bản API itlwm: " + "value" : "Địa chỉ IP" } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm API 版本: " + "value" : "IP 地址" } } } }, - "itlwm is not running" : { + "itlwm API Version: " : { "extractionState" : "manual", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إصدار itlwm API " + } + }, "cs" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm není spuštěný" + "value" : "Verze itlwm API: " } }, - "de" : { + "el" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm läuft nicht" + "value" : "itlwm API Έκδοση: " } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "El controlador WLAN necesario no se encuentra activo en su sistema. Por favor, verifique que itwlm.kext esté correctamente instalado y ejecutándose." + "value" : "Versión del API de itlwm: " } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm n'est pas en cours d'éxecution" + "value" : "Version de l'API d'itlwm: " } }, "id" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm belum dijalankan" + "value" : "Versi API itlwm: " } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm non è in esecuzione" + "value" : "Versione API di itlwm: " } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm não está em execução" + "value" : "Versão da API do itlwm: " } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "O itlwm não está a ser executado" + "value" : "Versão de API do itlwm: " } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm nu rulează" + "value" : "Versiune API itlwm: " } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm не запущен" + "value" : "Версия itlwm API: " } }, "tr" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm çalışmıyor" + "value" : "itlwm API Versiyonu: " } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm не запущено" + "value" : "Версія itlwm API: " } }, "vi" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm hiện không chạy" + "value" : "Phiên bản API itlwm: " } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm 未运行" + "value" : "itlwm API 版本: " } } } }, - "itlwm Version Mismatch" : { + "itlwm is not running" : { "extractionState" : "manual", "localizations" : { "cs" : { "stringUnit" : { "state" : "translated", - "value" : "Rozdílné verze itlwm a HeliPort" + "value" : "itlwm není spuštěný" } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "itlwm Version stimmt nicht überein" + "value" : "itlwm läuft nicht" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "El controlador WLAN necesario no se encuentra activo en su sistema. Por favor, verifique que itwlm.kext esté correctamente instalado y ejecutándose." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm n'est pas en cours d'éxecution" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm belum dijalankan" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm non è in esecuzione" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm não está em execução" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "O itlwm não está a ser executado" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm nu rulează" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm не запущен" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm çalışmıyor" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm не запущено" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm hiện không chạy" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm 未运行" + } + } + } + }, + "itlwm Version Mismatch" : { + "extractionState" : "manual", + "localizations" : { + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rozdílné verze itlwm a HeliPort" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "itlwm Version stimmt nicht überein" } }, "el" : { @@ -5620,6 +5948,119 @@ } } }, + "Noise" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "التشويش" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Šum" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Störsignal" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Θόρυβος" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ruido" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bruit" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Noise" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Disturbo" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "노이즈" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Szum" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ruído" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ruído" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zgomot" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Шум" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Parazit" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Шум" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tiếng ồn" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "噪音" + } + } + } + }, "none" : { "extractionState" : "manual", "localizations" : { @@ -6354,6 +6795,119 @@ } } }, + "PHY Mode" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "وضع PHY" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Režim PHY" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "PHY-Modus" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Λειτουργία PHY" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modo PHY" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode PHY" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode PHY" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalità PHY" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "PHY 모드" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tryb PHY" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modo PHY" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modo PHY" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mod PHY" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "PHY Mode" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "PHY Modu" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "PHY Mode" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chế độ PHY" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "PHY 模式" + } + } + } + }, "Quit HeliPort" : { "extractionState" : "manual", "localizations" : { @@ -6890,6 +7444,119 @@ } } }, + "Router" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "جهاز التوجيه" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Směrovač" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Δρομολογητής" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Routeur" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "라우터" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Roteador" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Маршрутизатор" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Yönetici IP" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Маршрутизатор" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bộ định tuyến" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "路由器" + } + } + } + }, "Saved Networks:" : { "extractionState" : "manual", "localizations" : { @@ -7339,12 +8006,115 @@ } }, "SIGNAL STRENGTH" : { + "extractionState" : "stale", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "قوة الإشارة" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "SÍLA SIGNÁLU" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "SIGNALSTÄRKE" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "ΙΣΧΥΣ ΣΗΜΑΤΟΣ" + } + }, "es" : { "stringUnit" : { "state" : "translated", "value" : "INTENSIDAD DE SEÑAL" } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "PUISSANCE DU SIGNAL" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "KEKUATAN SINYAL" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "INTENSITÀ DEL SEGNALE" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "신호 강도" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "SIŁA SYGNAŁU" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "FORÇA DO SINAL" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "FORÇA DO SINAL" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "PUTEREA SEMNALULUI" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "УРОВЕНЬ СИГНАЛА" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "SİNYAL GÜCÜ" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "РІВЕНЬ СИГНАЛУ" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "CƯỜNG ĐỘ TÍN HIỆU" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "信号强度" + } } } }, diff --git a/HeliPort/Appearance/StatusMenu/NetworkDetailsDashboard.swift b/HeliPort/Appearance/StatusMenu/NetworkDetailsDashboard.swift index fff7a8b..a1f4628 100644 --- a/HeliPort/Appearance/StatusMenu/NetworkDetailsDashboard.swift +++ b/HeliPort/Appearance/StatusMenu/NetworkDetailsDashboard.swift @@ -83,7 +83,7 @@ struct NetworkDetailsDashboard: View { Circle() .fill(signalColor) .frame(width: 6, height: 6) - Text("Connected") + Text(String.Dashboard.connected) .font(.system(size: 11, weight: .semibold)) .foregroundColor(signalColor.opacity(0.8)) } @@ -111,7 +111,7 @@ struct NetworkDetailsDashboard: View { // Signal Chart VStack(alignment: .leading, spacing: 6) { HStack { - Text("SIGNAL STRENGTH") + Text(String.Dashboard.signalStrength) .font(.system(size: 9, weight: .black)) .foregroundColor(.secondary.opacity(0.6)) .tracking(0.8) @@ -157,12 +157,14 @@ struct NetworkDetailsDashboard: View { // Details Grid LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 12) { - DetailItem(label: "IP Address", value: viewModel.ipAddress, icon: "network") - DetailItem(label: "Router", value: viewModel.router, icon: "router") - DetailItem(label: "Channel", value: viewModel.channel, icon: "antenna.radiowaves.left.and.right") - DetailItem(label: "PHY Mode", value: viewModel.phyMode, icon: "bolt.fill") + DetailItem(label: String.Dashboard.ipAddress, value: viewModel.ipAddress, icon: "network") + DetailItem(label: String.Dashboard.router, value: viewModel.router, icon: "router") + DetailItem( + label: String.Dashboard.channel, value: viewModel.channel, icon: "antenna.radiowaves.left.and.right" + ) + DetailItem(label: String.Dashboard.phyMode, value: viewModel.phyMode, icon: "bolt.fill") DetailItem(label: "BSSID", value: viewModel.bssid.uppercased(), icon: "macpro.gen3") - DetailItem(label: "Noise", value: "\(viewModel.noise) dBm", icon: "ear.and.waveform") + DetailItem(label: String.Dashboard.noise, value: "\(viewModel.noise) dBm", icon: "ear.and.waveform") DetailItem(label: "SNR", value: "\(viewModel.snr) dB", icon: "equal.circle") } } diff --git a/HeliPort/Appearance/StatusMenu/QuickToggleView.swift b/HeliPort/Appearance/StatusMenu/QuickToggleView.swift index 4815f11..d463ebd 100644 --- a/HeliPort/Appearance/StatusMenu/QuickToggleView.swift +++ b/HeliPort/Appearance/StatusMenu/QuickToggleView.swift @@ -1,7 +1,12 @@ import SwiftUI +class WifiToggleState: ObservableObject { + @Published var isOn: Bool + init(isOn: Bool) { self.isOn = isOn } +} + struct QuickToggleView: View { - @Binding var isOn: Bool + @ObservedObject var state: WifiToggleState let title: String var onToggle: (Bool) -> Void @@ -11,25 +16,35 @@ struct QuickToggleView: View { .font(.system(size: 13, weight: .bold, design: .rounded)) .foregroundColor(.primary) Spacer() - Toggle("", isOn: $isOn) - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .labelsHidden() - .onChange(of: isOn) { newValue in + Toggle("", isOn: Binding( + get: { state.isOn }, + set: { newValue in + state.isOn = newValue onToggle(newValue) } + )) + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + .labelsHidden() } .modernMenuItem() } } class ModernToggleMenuItem: NSMenuItem { - init(title: String, isOn: Binding, onToggle: @escaping (Bool) -> Void) { + private let toggleState: WifiToggleState + + init(title: String, isOn: Bool, onToggle: @escaping (Bool) -> Void) { + self.toggleState = WifiToggleState(isOn: isOn) super.init(title: title, action: nil, keyEquivalent: "") - let view = QuickToggleView(isOn: isOn, title: title, onToggle: onToggle) + let view = QuickToggleView(state: toggleState, title: title, onToggle: onToggle) self.view = NSHostingView(rootView: view) self.view?.frame = NSRect(x: 0, y: 0, width: HeliPortUI.Dashboard.width, height: 44) } + func update(isOn: Bool) { + toggleState.isOn = isOn + } + required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/HeliPort/Appearance/StatusMenu/StatusMenuBase.swift b/HeliPort/Appearance/StatusMenu/StatusMenuBase.swift index 7cae67e..5f92504 100644 --- a/HeliPort/Appearance/StatusMenu/StatusMenuBase.swift +++ b/HeliPort/Appearance/StatusMenu/StatusMenuBase.swift @@ -628,4 +628,14 @@ extension String { static let joinNetworks = NSLocalizedString("Other...") static let wifiSettings = NSLocalizedString("Wi-Fi Settings...") } + + enum Dashboard { + static let connected = NSLocalizedString("Connected") + static let signalStrength = NSLocalizedString("SIGNAL STRENGTH") + static let ipAddress = NSLocalizedString("IP Address") + static let router = NSLocalizedString("Router") + static let channel = NSLocalizedString("Channel") + static let phyMode = NSLocalizedString("PHY Mode") + static let noise = NSLocalizedString("Noise") + } } diff --git a/HeliPort/Appearance/StatusMenu/StatusMenuModern.swift b/HeliPort/Appearance/StatusMenu/StatusMenuModern.swift index 3dba0d2..53446ff 100644 --- a/HeliPort/Appearance/StatusMenu/StatusMenuModern.swift +++ b/HeliPort/Appearance/StatusMenu/StatusMenuModern.swift @@ -13,18 +13,9 @@ final class StatusMenuModern: StatusMenuBase, StatusMenuItems { // - MARK: Menu items - private var toggleState: Bool = true // add this property - private lazy var statusItem: NSMenuItem = { - let binding = Binding( - get: { self.toggleState }, // ← reads local state, not driver - set: { - self.toggleState = $0 // ← updates immediately - self.isWiFiOn = $0 // ← then tells driver - } - ) - return ModernToggleMenuItem(title: String.Modern.wifi, isOn: binding) { _ in - // power state is handled by binding + return ModernToggleMenuItem(title: String.Modern.wifi, isOn: true) { [weak self] newValue in + self?.isWiFiOn = newValue } }() @@ -140,7 +131,7 @@ final class StatusMenuModern: StatusMenuBase, StatusMenuItems { override var isNetworkCardEnabled: Bool { willSet(newState) { super.isNetworkCardEnabled = newState - self.toggleState = newState + (statusItem as? ModernToggleMenuItem)?.update(isOn: newState) } }