[codex] Refactor BLE outbound scheduling and Noise queues (#1306)

* Refactor BLE transport event handling

* Make image output paths unique

* Keep queued Nostr read receipts alive

* Refine BLE ingress fanout

* Rediscover BLE service after invalidation

* Extract BLE notification retry buffer

* Extract BLE inbound write buffer

* Extract BLE fragment assembly buffer

* Tidy secure log handling from device run

* Extract BLE outbound fragment scheduler

* Harden app CI media tests

* Redact BLE message content from logs

* Extract BLE Noise session queues

* Fix BLE read receipt UI updates

* Allow self-authored RSR ingress replies

* Harden read receipt queue test timing

* Extract BLE outbound policy and incoming file storage

* Avoid duplicate BLE link snapshots during send

* Canonicalize Nostr relay URLs

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2026-05-31 14:16:11 +02:00
committed by GitHub
co-authored by jack
parent df36b19afe
commit 9e84f5e822
19 changed files with 1084 additions and 629 deletions
+1 -6
View File
@@ -381,12 +381,7 @@ final class GeoRelayDirectory {
if idx == 0 && line.lowercased().contains("relay url") { continue }
let parts = line.split(separator: ",").map { $0.trimmed }
guard parts.count >= 3 else { continue }
var host = parts[0]
host = host.replacingOccurrences(of: "https://", with: "")
host = host.replacingOccurrences(of: "http://", with: "")
host = host.replacingOccurrences(of: "wss://", with: "")
host = host.replacingOccurrences(of: "ws://", with: "")
host = host.trimmingCharacters(in: CharacterSet(charactersIn: "/"))
guard let host = NostrRelayURL.directoryAddress(parts[0]) else { continue }
guard let lat = Double(parts[1]), let lon = Double(parts[2]) else { continue }
result.insert(Entry(host: host, lat: lat, lon: lon))
}
+9 -8
View File
@@ -129,7 +129,7 @@ final class NostrRelayManager: ObservableObject {
"wss://offchain.pub"
// For local testing, you can add: "ws://localhost:8080"
]
private static let defaultRelaySet = Set(defaultRelays)
private static let defaultRelaySet = Set(defaultRelays.compactMap { NostrRelayURL.normalized($0) })
@Published private(set) var relays: [Relay] = []
@Published private(set) var isConnected = false
@@ -390,8 +390,7 @@ final class NostrRelayManager: ObservableObject {
// Target specific relays if provided; else default. Filter permanently failed relays.
let baseUrls = relayUrls ?? Self.defaultRelays
let candidateUrls = baseUrls.filter { !isPermanentlyFailed($0) }
let urls = allowedRelayList(from: candidateUrls)
let urls = allowedRelayList(from: baseUrls).filter { !isPermanentlyFailed($0) }
let requestState = SubscriptionRequestState(messageString: messageString, relayURLs: Set(urls))
if subscriptionRequestState[id] == requestState, subscriptionStateExists(id: id, requestState: requestState) {
return
@@ -474,7 +473,8 @@ final class NostrRelayManager: ObservableObject {
private func allowedRelayList(from urls: [String]) -> [String] {
var seen = Set<String>()
var result: [String] = []
for url in urls {
for rawURL in urls {
guard let url = NostrRelayURL.normalized(rawURL) else { continue }
if !allowDefaultRelays && Self.defaultRelaySet.contains(url) { continue }
if seen.insert(url).inserted {
result.append(url)
@@ -881,7 +881,8 @@ final class NostrRelayManager: ObservableObject {
/// Manually retry connection to a specific relay
func retryConnection(to relayUrl: String) {
guard let index = relays.firstIndex(where: { $0.url == relayUrl }) else { return }
let normalizedRelayUrl = NostrRelayURL.normalized(relayUrl) ?? relayUrl
guard let index = relays.firstIndex(where: { $0.url == normalizedRelayUrl }) else { return }
// Reset reconnection attempts
relays[index].reconnectAttempts = 0
@@ -889,13 +890,13 @@ final class NostrRelayManager: ObservableObject {
relays[index].lastError = nil
// Disconnect if connected
if let connection = connections[relayUrl] {
if let connection = connections[normalizedRelayUrl] {
connection.cancel(with: .goingAway, reason: nil)
connections.removeValue(forKey: relayUrl)
connections.removeValue(forKey: normalizedRelayUrl)
}
// Attempt immediate reconnection
connectToRelay(relayUrl)
connectToRelay(normalizedRelayUrl)
}
/// Get detailed status for all relays
+51
View File
@@ -0,0 +1,51 @@
import Foundation
enum NostrRelayURL {
static func normalized(_ rawValue: String, defaultScheme: String? = nil) -> String? {
var value = rawValue.trimmingCharacters(in: .whitespacesAndNewlines)
guard !value.isEmpty else { return nil }
if !value.contains("://"), let defaultScheme {
value = "\(defaultScheme)://\(value)"
}
guard var components = URLComponents(string: value),
let rawScheme = components.scheme?.lowercased(),
let rawHost = components.host?.lowercased(),
!rawHost.isEmpty else {
return nil
}
switch rawScheme {
case "wss", "https":
components.scheme = "wss"
if components.port == 443 {
components.port = nil
}
case "ws", "http":
components.scheme = "ws"
if components.port == 80 {
components.port = nil
}
default:
return nil
}
components.host = rawHost
if components.path == "/" {
components.path = ""
}
components.fragment = nil
return components.string
}
static func directoryAddress(_ rawValue: String) -> String? {
guard var normalized = normalized(rawValue, defaultScheme: "wss") else { return nil }
for prefix in ["wss://", "ws://"] where normalized.hasPrefix(prefix) {
normalized.removeFirst(prefix.count)
break
}
return normalized
}
}