diff --git a/Localizable.xcstrings b/Localizable.xcstrings index d9937814..900baa6e 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -1347,8 +1347,15 @@ } } }, - "%lld features" : { - + "%lld %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$lld %2$@" + } + } + } }, "%lld or less hops away" : { "localizations" : { @@ -23105,40 +23112,8 @@ } } }, - "No files uploaded yet" : { - "comment" : "Empty state text when no files are uploaded", - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nessun file caricato ancora" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "まだファイルがアップロードされていません" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Još uvek nema otpremljenih datoteka" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "尚未上传文件" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "尚未上傳檔案" - } - } - } + "No files uploaded" : { + }, "No Interface" : { "localizations" : { @@ -31586,42 +31561,6 @@ } } }, - "Select Map Data File" : { - "comment" : "Button text for selecting map data file", - "extractionState" : "stale", - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Seleziona File Dati Mappa" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "マップデータファイルを選択" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Izaberi Datoteku Podataka Mape" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "选择地图数据文件" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "選擇地圖資料檔案" - } - } - } - }, "Select Map File" : { }, @@ -40379,41 +40318,6 @@ } } }, - "Using %@ data" : { - "comment" : "Shows which data source is being used", - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utilizzo dati %@" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@データを使用" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Koristi %@ podatke" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "使用%@数据" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "使用%@資料" - } - } - } - }, "Utilizes the network connection on your phone to connect to MQTT." : { "localizations" : { "it" : { diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 59b93928..943cbcb2 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1086,6 +1086,7 @@ children = ( 233E99B42D849C2D00CC3A77 /* Compact Widgets */, DD6F65772C6EAB860053C113 /* Help */, + DD5E523D298F5A7D00D21B61 /* Weather */, DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */, DD3CC24B2C498D6C001BD3A2 /* BatteryCompact.swift */, DD457187293C7E63000C49FB /* BLESignalStrengthIndicator.swift */, @@ -1098,7 +1099,6 @@ DDB75A1D2A0B0CD0006ED576 /* LoRaSignalStrengthIndicator.swift */, DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */, DDF45C332BC1A48E005ED5F2 /* MQTTIcon.swift */, - DD5E523D298F5A7D00D21B61 /* Weather */, DD6F65712C6AB8EC0053C113 /* SecureInput.swift */, 8D3F8A3E2D44BB02009EAAA4 /* PowerMetrics.swift */, 237B46952DC8F1C100B22D99 /* RateLimitedButton.swift */, diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift index ef80098c..ec49fd52 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift @@ -25,9 +25,9 @@ struct MapSettingsForm: View { @AppStorage("meshMapDistance") private var meshMapDistance: Double = 800000 @Binding var meshMap: Bool @Binding var enabledOverlayConfigs: Set - + var body: some View { - + NavigationStack { Form { Section(header: Text("Map Options")) { @@ -119,10 +119,9 @@ struct MapSettingsForm: View { UserDefaults.enableMapPointsOfInterest = self.pointsOfInterest } } - + Section(header: Text("Map Overlays")) { let hasUserData = GeoJSONOverlayManager.shared.hasUserData() - // Master toggle for map overlays Toggle(isOn: $mapOverlaysEnabled) { Label { @@ -134,26 +133,15 @@ struct MapSettingsForm: View { } } icon: { Image(systemName: "map") - .foregroundColor(hasUserData ? .accentColor : .secondary) + .symbolRenderingMode(.multicolor) } } .tint(.accentColor) - .disabled(!hasUserData) - + .disabled(!hasUserData && !mapOverlaysEnabled) + // Show individual file toggles when overlays are enabled if mapOverlaysEnabled && hasUserData { if !mapDataManager.getUploadedFiles().isEmpty { - // Data source info - HStack { - Image(systemName: "info.circle") - .foregroundColor(.secondary) - Text(String(format: NSLocalizedString("Using %@ data", comment: "Shows which data source is being used"), GeoJSONOverlayManager.shared.getActiveDataSource())) - .font(.caption) - .foregroundColor(.secondary) - Spacer() - } - .padding(.leading, 35) - // Individual file toggles ForEach(mapDataManager.getUploadedFiles()) { file in Toggle(isOn: Binding( @@ -173,7 +161,7 @@ struct MapSettingsForm: View { Text(file.originalName) .font(.subheadline) HStack { - Text("\(file.overlayCount) features") + Text("\(file.overlayCount) \(file.overlayCount > 1 ? "features".localized : "feature".localized)") .font(.caption2) .foregroundColor(.secondary) Spacer() @@ -189,67 +177,43 @@ struct MapSettingsForm: View { } } .tint(.accentColor) - .padding(.leading, 35) } - - // Manage data link NavigationLink(destination: MapDataFiles()) { - HStack { + Label { + Text("Manage map data") + } icon: { Image(systemName: "folder") - .foregroundColor(.accentColor) - Text(NSLocalizedString("Manage map data", comment: "Link to manage uploaded map data")) - .font(.caption) - .foregroundColor(.secondary) - Spacer() - Image(systemName: "chevron.right") - .font(.caption2) - .foregroundColor(.secondary) + .symbolRenderingMode(.multicolor) } } - .padding(.leading, 35) } else { - // No files uploaded - HStack { - Image(systemName: "exclamationmark.triangle") - .foregroundColor(.orange) - Text(NSLocalizedString("No map data files uploaded", comment: "Message when no files are uploaded")) - .font(.caption) - .foregroundColor(.secondary) - Spacer() - } - .padding(.leading, 35) + ContentUnavailableView ("No map data files uploaded", systemImage: "exclamationmark.triangle") } } else if !hasUserData { // Upload prompt when no data available NavigationLink(destination: MapDataFiles()) { - HStack { + Label { + Text("Upload map data to enable overlays") + } icon: { Image(systemName: "arrow.up.doc") - .foregroundColor(.accentColor) - Text(NSLocalizedString("Upload map data to enable overlays", comment: "Prompt to upload map data when none is available")) - .font(.caption) - .foregroundColor(.secondary) - Spacer() - Image(systemName: "chevron.right") - .font(.caption2) - .foregroundColor(.secondary) + .symbolRenderingMode(.multicolor) } } - .padding(.leading, 35) } } } - + #if targetEnvironment(macCatalyst) -Spacer() - Button { - dismiss() - } label: { - Label("Close", systemImage: "xmark") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) + Spacer() + Button { + dismiss() + } label: { + Label("Close", systemImage: "xmark") + } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding(.bottom) #endif } .presentationDetents([.medium, .large], selection: $currentDetent) @@ -260,6 +224,6 @@ Spacer() // Initialize map data manager mapDataManager.initialize() } - + } } diff --git a/Meshtastic/Views/Settings/MapDataFiles.swift b/Meshtastic/Views/Settings/MapDataFiles.swift index beff897c..7c312bf0 100644 --- a/Meshtastic/Views/Settings/MapDataFiles.swift +++ b/Meshtastic/Views/Settings/MapDataFiles.swift @@ -58,21 +58,12 @@ struct MapDataFiles: View { let uploadedFiles = mapDataManager.getUploadedFiles() if uploadedFiles.isEmpty { - VStack(spacing: 8) { - Image(systemName: "doc.text") - .font(.title) - .foregroundColor(.secondary) - Text("No files uploaded yet") - .font(.caption) - .foregroundColor(.secondary) - } - .frame(maxWidth: .infinity) - //.padding(.vertical, 40) + ContentUnavailableView ("No files uploaded", systemImage: "doc.text") } else { ScrollView { LazyVStack() { - ForEach(uploadedFiles) { file in - MapDataFileRow(file: file) { + ForEach(Array(uploadedFiles.enumerated()), id: \.offset) { index, file in + MapDataFileRow(file: file, showDivider: index < uploadedFiles.count - 1) { deleteFile(file) } } @@ -176,6 +167,7 @@ struct MapDataFiles: View { struct MapDataFileRow: View { let file: MapDataMetadata + let showDivider: Bool let onDelete: () -> Void var body: some View { @@ -222,7 +214,9 @@ struct MapDataFileRow: View { } } } - Divider() + if showDivider { + Divider() + } } }