Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Meshtastic/CarPlay/CarPlaySceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,13 @@ class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate, CPI

private func fetchFavoriteContactItems() -> [CPMessageListItem] {
do {
let descriptor = FetchDescriptor<NodeInfoEntity>(
let activeNum = Int64(AccessoryManager.shared.activeDeviceNum ?? 0)
var descriptor = FetchDescriptor<NodeInfoEntity>(
predicate: #Predicate<NodeInfoEntity> { $0.favorite == true && $0.num != activeNum },
sortBy: [SortDescriptor(\.lastHeard, order: .reverse)]
)
let activeNum = AccessoryManager.shared.activeDeviceNum ?? 0
let nodes = try context.fetch(descriptor).filter { $0.favorite && $0.num != activeNum }
descriptor.fetchLimit = 50
let nodes = try context.fetch(descriptor)
let nodeNums = nodes.compactMap { $0.user != nil ? $0.num : nil as Int64? }
let unreadCounts = fetchUnreadCountsForDMs(nodeNums: nodeNums)
let now = Date()
Expand Down
11 changes: 6 additions & 5 deletions Meshtastic/Helpers/TAK/CoTMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -282,16 +282,17 @@ struct CoTMessage: Identifiable, Sendable {
// MARK: - XML Generation

/// Generate CoT XML string for transmission to TAK clients
private static let xmlDateFormatStyle = Date.ISO8601FormatStyle(includingFractionalSeconds: true, timeZone: TimeZone(secondsFromGMT: 0)!)

func toXML() -> String {
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let dateFormatter = Self.xmlDateFormatStyle

Comment thread
garthvh marked this conversation as resolved.
var cot = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
cot += "<event version='2.0' uid='\(uid.xmlEscaped)' "
cot += "type='\(type)' "
cot += "time='\(dateFormatter.string(from: time))' "
cot += "start='\(dateFormatter.string(from: start))' "
cot += "stale='\(dateFormatter.string(from: stale))' "
cot += "time='\(time.formatted(dateFormatter))' "
cot += "start='\(start.formatted(dateFormatter))' "
cot += "stale='\(stale.formatted(dateFormatter))' "
cot += "how='\(how)'>"
cot += "<point lat='\(latitude)' lon='\(longitude)' "
cot += "hae='\(hae)' ce='\(ce)' le='\(le)'/>"
Expand Down
19 changes: 16 additions & 3 deletions Meshtastic/Services/DiscoveryScanEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import SwiftUI

// MARK: - Scan State

enum DiscoveryScanState: Equatable {
enum DiscoveryScanState: Equatable, CustomStringConvertible {
case idle
case shifting
case reconnecting
Expand All @@ -25,6 +25,19 @@ enum DiscoveryScanState: Equatable {
case complete
case paused
case restoring

var description: String {
switch self {
case .idle: "idle"
case .shifting: "shifting"
case .reconnecting: "reconnecting"
case .dwell: "dwell"
case .analysis: "analysis"
case .complete: "complete"
case .paused: "paused"
case .restoring: "restoring"
}
}
}

// MARK: - DiscoveryScanEngine
Expand Down Expand Up @@ -91,7 +104,7 @@ final class DiscoveryScanEngine {

func startScan() async {
guard currentState == .idle else {
Logger.discovery.warning("📡 [Discovery] Cannot start scan — not idle (state: \(String(describing: self.currentState)))")
Logger.discovery.warning("📡 [Discovery] Cannot start scan — not idle (state: \(self.currentState))")
return
}
guard !selectedPresets.isEmpty else {
Expand Down Expand Up @@ -688,7 +701,7 @@ extension DiscoveryScanEngine {
private func transitionTo(_ newState: DiscoveryScanState) {
let oldState = currentState
currentState = newState
Logger.discovery.info("📡 [Discovery] State: \(String(describing: oldState)) → \(String(describing: newState))")
Logger.discovery.info("📡 [Discovery] State: \(oldState) → \(newState)")
}

private func cleanupAndIdle() {
Expand Down
1 change: 0 additions & 1 deletion Meshtastic/Tips/BluetoothTips.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,5 @@ struct ConnectionTip: Tip {
}
var options: [TipOption] {
Tips.IgnoresDisplayFrequency(true)
Tips.MaxDisplayCount(3)
}
Comment thread
garthvh marked this conversation as resolved.
Comment thread
garthvh marked this conversation as resolved.
}
5 changes: 3 additions & 2 deletions Meshtastic/Views/Helpers/RateLimitedButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,17 @@ class RateLimitStorage: ObservableObject {
// Create the timer
self.timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
guard let self = self else { return }
self.objectWillChange.send()

// Determine if we can clean up the dictionary and stop the timer.
let maxExpiration = self.rateLimits.values.map { $0.rateLimitExpires }.max() ?? .distantPast
if maxExpiration.timeIntervalSinceNow < 0 {
// All rateLimits are in the past. Stop and clean up
// All rateLimits are in the past. Stop and clean up
self.timer?.invalidate()
self.timer = nil
self.rateLimits.removeAll()
return
}
self.objectWillChange.send()
Comment thread
garthvh marked this conversation as resolved.
}
Comment thread
garthvh marked this conversation as resolved.
}
}
Loading
Loading