diff --git a/Meshtastic/Extensions/Color+Hex.swift b/Meshtastic/Extensions/Color+Hex.swift index bae3d9b8..79f0f4b5 100644 --- a/Meshtastic/Extensions/Color+Hex.swift +++ b/Meshtastic/Extensions/Color+Hex.swift @@ -27,4 +27,4 @@ extension Color { opacity: Double(a) / 255 ) } -} \ No newline at end of file +} diff --git a/Meshtastic/Extensions/UserDefaults.swift b/Meshtastic/Extensions/UserDefaults.swift index a8f550e7..03ce9187 100644 --- a/Meshtastic/Extensions/UserDefaults.swift +++ b/Meshtastic/Extensions/UserDefaults.swift @@ -19,11 +19,11 @@ struct UserDefault { var wrappedValue: T { get { - if defaultValue as? any RawRepresentable != nil { + if defaultValue is any RawRepresentable { let storedValue = UserDefaults.standard.object(forKey: key.rawValue) guard let storedValue, - let jsonString = (storedValue as? String != nil) ? "\"\(storedValue)\"" : "\(storedValue)", + let jsonString = (storedValue is String) ? "\"\(storedValue)\"" : "\(storedValue)", let data = jsonString.data(using: .utf8), let value = (try? JSONDecoder().decode(T.self, from: data)) else { return defaultValue } diff --git a/Meshtastic/Helpers/GeoJSONOverlayConfig.swift b/Meshtastic/Helpers/GeoJSONOverlayConfig.swift index 9082fcfc..ddbc30bd 100644 --- a/Meshtastic/Helpers/GeoJSONOverlayConfig.swift +++ b/Meshtastic/Helpers/GeoJSONOverlayConfig.swift @@ -16,9 +16,9 @@ struct GeoJSONFeature: Codable { let id: Int? let geometry: GeoJSONGeometry let properties: [String: AnyCodableValue]? - + // MARK: - GeoJSON Styling Properties - + /// Extract feature name from properties, defaulting to empty string var name: String { // Check for "NAME" first (uppercase), then "name" (lowercase) @@ -30,7 +30,7 @@ struct GeoJSONFeature: Codable { } return "" } - + /// Extract layer metadata from properties var layerId: String? { if case .string(let value) = properties?["layer_id"] { @@ -38,60 +38,60 @@ struct GeoJSONFeature: Codable { } return nil } - + var layerName: String? { if case .string(let value) = properties?["layer_name"] { return value } return nil } - + var layerDescription: String? { if case .string(let value) = properties?["description"] { return value } return nil } - + var isVisible: Bool { if case .bool(let value) = properties?["visible"] { return value } return true // Default to visible } - + // MARK: - Point/Marker Styling - + var markerColor: String? { if case .string(let value) = properties?["marker-color"] { return value } return nil } - + var markerSize: String? { if case .string(let value) = properties?["marker-size"] { return value } return "medium" // Default size } - + var markerSymbol: String? { if case .string(let value) = properties?["marker-symbol"] { return value } return nil } - + // MARK: - Stroke/Line Styling - + var strokeColor: String? { if case .string(let value) = properties?["stroke"] { return value } return nil } - + var strokeWidth: Double { if case .double(let value) = properties?["stroke-width"] { return value @@ -100,7 +100,7 @@ struct GeoJSONFeature: Codable { } return 1.0 // Default width } - + var strokeOpacity: Double { if case .double(let value) = properties?["stroke-opacity"] { return value @@ -109,7 +109,7 @@ struct GeoJSONFeature: Codable { } return 1.0 // Default opacity } - + var lineDashArray: [Double]? { if case .array(let values) = properties?["line-dasharray"] { return values.compactMap { value in @@ -122,16 +122,16 @@ struct GeoJSONFeature: Codable { } return nil } - + // MARK: - Fill Styling - + var fillColor: String? { if case .string(let value) = properties?["fill"] { return value } return nil } - + var fillOpacity: Double { if case .double(let value) = properties?["fill-opacity"] { return value @@ -140,14 +140,14 @@ struct GeoJSONFeature: Codable { } return 0.0 // Default to no fill } - + // MARK: - Computed Rendering Properties - + /// Get effective stroke color (fallback to marker color for points) var effectiveStrokeColor: String { return strokeColor ?? markerColor ?? "#000000" } - + /// Get effective fill color (fallback to stroke color if fill opacity > 0) var effectiveFillColor: String { if fillOpacity > 0 { @@ -155,7 +155,7 @@ struct GeoJSONFeature: Codable { } return "#000000" } - + /// Convert marker size to point radius var markerRadius: CGFloat { switch markerSize { @@ -174,7 +174,7 @@ struct GeoJSONStyledFeature: Identifiable { let id = UUID() let feature: GeoJSONFeature let overlayId: String - + /// Create MKOverlay from this styled feature func createOverlay() -> MKOverlay? { do { @@ -187,14 +187,14 @@ struct GeoJSONStyledFeature: Identifiable { ], "properties": feature.properties?.mapValues { $0.toAnyObject() } ?? [:] ] - + // Creating overlay for geometry - + let geojsonData = try JSONSerialization.data(withJSONObject: featureDict) let mkFeatures = try MKGeoJSONDecoder().decode(geojsonData) - + // MKGeoJSONDecoder processing - + if let mkFeature = mkFeatures.first as? MKGeoJSONFeature { // Processing geometry objects if let geometry = mkFeature.geometry.first as? MKOverlay { @@ -207,7 +207,7 @@ struct GeoJSONStyledFeature: Identifiable { } return nil } - + /// Get stroke style for this feature var strokeStyle: StrokeStyle { let dashArray = feature.lineDashArray @@ -226,12 +226,12 @@ struct GeoJSONStyledFeature: Identifiable { ) } } - + /// Get stroke color with opacity var strokeColor: Color { return Color(hex: feature.effectiveStrokeColor).opacity(feature.strokeOpacity) } - + /// Get fill color with opacity var fillColor: Color { return Color(hex: feature.effectiveFillColor).opacity(feature.fillOpacity) @@ -316,26 +316,26 @@ enum AnyCodableValue: Codable { return dict.mapValues { $0.toAnyObject() } } } - + // Helper to convert Point coordinates to CLLocationCoordinate2D func toCoordinate() -> CLLocationCoordinate2D? { if case .array(let coords) = self, coords.count >= 2 { let lon: Double let lat: Double - + switch coords[0] { case .double(let d): lon = d case .int(let i): lon = Double(i) default: return nil } - + switch coords[1] { case .double(let d): lat = d case .int(let i): lat = Double(i) default: return nil } - + return CLLocationCoordinate2D(latitude: lat, longitude: lon) } return nil diff --git a/Meshtastic/Helpers/GeoJSONOverlayManager.swift b/Meshtastic/Helpers/GeoJSONOverlayManager.swift index 85080d89..a77df91b 100644 --- a/Meshtastic/Helpers/GeoJSONOverlayManager.swift +++ b/Meshtastic/Helpers/GeoJSONOverlayManager.swift @@ -28,24 +28,24 @@ class GeoJSONOverlayManager { func loadStyledFeaturesForConfigs(_ enabledConfigs: Set) -> [GeoJSONStyledFeature] { // Get files that match the enabled configs let enabledFiles = MapDataManager.shared.getUploadedFiles().filter { enabledConfigs.contains($0.id) } - + guard !enabledFiles.isEmpty else { return [] } - + // Load feature collection from enabled files only guard let collection = MapDataManager.shared.loadFeatureCollectionForFiles(enabledFiles) else { return [] } - + var styledFeatures: [GeoJSONStyledFeature] = [] - + for feature in collection.features { // Skip invisible features - guard feature.isVisible else { - continue + guard feature.isVisible else { + continue } - + let layerId = feature.layerId ?? "default" let styledFeature = GeoJSONStyledFeature( feature: feature, @@ -53,7 +53,7 @@ class GeoJSONOverlayManager { ) styledFeatures.append(styledFeature) } - + return styledFeatures } @@ -62,15 +62,15 @@ class GeoJSONOverlayManager { guard let collection = loadFeatureCollection() else { return [] } - + var styledFeatures: [GeoJSONStyledFeature] = [] - + for feature in collection.features { // Skip invisible features - guard feature.isVisible else { - continue + guard feature.isVisible else { + continue } - + let layerId = feature.layerId ?? "default" let styledFeature = GeoJSONStyledFeature( feature: feature, @@ -78,16 +78,16 @@ class GeoJSONOverlayManager { ) styledFeatures.append(styledFeature) } - + return styledFeatures } /// Get all features grouped by layer ID func getFeaturesByLayer() -> [String: [GeoJSONFeature]] { guard let collection = loadFeatureCollection() else { return [:] } - + var featuresByLayer: [String: [GeoJSONFeature]] = [:] - + for feature in collection.features { let layerId = feature.layerId ?? "default" if featuresByLayer[layerId] == nil { @@ -95,7 +95,7 @@ class GeoJSONOverlayManager { } featuresByLayer[layerId]?.append(feature) } - + return featuresByLayer } @@ -115,7 +115,7 @@ class GeoJSONOverlayManager { func hasUserData() -> Bool { return !MapDataManager.shared.getUploadedFiles().isEmpty } - + /// Check if there are any active files func hasActiveData() -> Bool { return MapDataManager.shared.getUploadedFiles().contains { $0.isActive } @@ -131,18 +131,18 @@ class GeoJSONOverlayManager { return NSLocalizedString("No Data", comment: "Data source label when no files are available") } } - + // MARK: - File-based Filtering - + /// Get all uploaded files with their active states for UI display func getUploadedFilesWithState() -> [MapDataMetadata] { return MapDataManager.shared.getUploadedFiles() } - + /// Toggle the active state of an uploaded file func toggleFileActive(_ fileId: UUID) { MapDataManager.shared.toggleFileActive(fileId) // Clear cache to force reload with new file states clearCache() } -} \ No newline at end of file +} diff --git a/Meshtastic/Helpers/MapDataManager.swift b/Meshtastic/Helpers/MapDataManager.swift index 04609e7a..bad659af 100644 --- a/Meshtastic/Helpers/MapDataManager.swift +++ b/Meshtastic/Helpers/MapDataManager.swift @@ -167,7 +167,6 @@ class MapDataManager: ObservableObject { ) } - /// Get overlay count from raw GeoJSON data private func getOverlayCount(from data: Data) throws -> Int { // Parse as raw GeoJSON FeatureCollection @@ -305,7 +304,6 @@ class MapDataManager: ObservableObject { throw MapDataError.fileNotFound } - // Check if file exists before trying to delete if !FileManager.default.fileExists(atPath: fileURL.path) { Logger.services.warning("🗑️ MapDataManager: File does not exist at path: \(fileURL.path, privacy: .public)") @@ -351,7 +349,6 @@ class MapDataManager: ObservableObject { } - // MARK: - Metadata Persistence /// Load metadata from disk @@ -463,4 +460,4 @@ enum MapDataError: Error, LocalizedError { // MARK: - Notification Names extension Foundation.Notification.Name { static let mapDataFileDeleted = Foundation.Notification.Name("mapDataFileDeleted") -} \ No newline at end of file +} diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 24a577b2..4223bdf2 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -1027,7 +1027,7 @@ func textMessageAppPacket( subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", content: messageText!, target: "messages", - path: "meshtastic:///messages?userNum=\(newMessage.fromUser?.num ?? 0)&messageId=\(newMessage.isEmoji ? newMessage.replyID : newMessage.messageId)", + path: "meshtastic:///messages?userNum=\(newMessage.fromUser?.num ?? 0)&messageId=\(newMessage.isEmoji ? newMessage.replyID : newMessage.messageId)", messageId: newMessage.messageId, channel: newMessage.channel, userNum: Int64(packet.from), diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift index 8b754fcd..8af740a9 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift @@ -248,7 +248,6 @@ struct MeshMapContent: MapContent { // Get all features but filter by enabled configs let allStyledFeatures = GeoJSONOverlayManager.shared.loadStyledFeaturesForConfigs(enabledOverlayConfigs) - return Group { ForEach(0..