From f10e5d1788ed1f37ce20b977c1f0d31d92c79c82 Mon Sep 17 00:00:00 2001 From: jack Date: Sat, 13 Sep 2025 11:59:55 +0200 Subject: [PATCH] Notes counter: show 0 by default; subscribe at building-level (precision 8) for notes and counter; keep building hidden in channel list --- bitchat/Protocols/LocationChannel.swift | 6 ++++++ bitchat/Services/LocationChannelManager.swift | 6 ++++++ bitchat/Services/LocationNotesCounter.swift | 6 +++--- bitchat/Views/ContentView.swift | 13 +++++++------ bitchat/Views/LocationChannelsSheet.swift | 3 ++- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/bitchat/Protocols/LocationChannel.swift b/bitchat/Protocols/LocationChannel.swift index ac58946d..5aea0575 100644 --- a/bitchat/Protocols/LocationChannel.swift +++ b/bitchat/Protocols/LocationChannel.swift @@ -2,6 +2,7 @@ import Foundation /// Levels of location channels mapped to geohash precisions. enum GeohashChannelLevel: CaseIterable, Codable, Equatable { + case building case block case neighborhood case city @@ -11,6 +12,7 @@ enum GeohashChannelLevel: CaseIterable, Codable, Equatable { /// Geohash length used for this level. var precision: Int { switch self { + case .building: return 8 case .block: return 7 case .neighborhood: return 6 case .city: return 5 @@ -21,6 +23,7 @@ enum GeohashChannelLevel: CaseIterable, Codable, Equatable { var displayName: String { switch self { + case .building: return "Building" case .block: return "Block" case .neighborhood: return "Neighborhood" case .city: return "City" @@ -35,6 +38,7 @@ extension GeohashChannelLevel { let container = try decoder.singleValueContainer() if let raw = try? container.decode(String.self) { switch raw { + case "building": self = .building case "block": self = .block case "neighborhood": self = .neighborhood case "city": self = .city @@ -46,6 +50,7 @@ extension GeohashChannelLevel { } } else if let precision = try? container.decode(Int.self) { switch precision { + case 8: self = .building case 7: self = .block case 6: self = .neighborhood case 5: self = .city @@ -61,6 +66,7 @@ extension GeohashChannelLevel { func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { + case .building: try container.encode("building") case .block: try container.encode("block") case .neighborhood: try container.encode("neighborhood") case .city: try container.encode("city") diff --git a/bitchat/Services/LocationChannelManager.swift b/bitchat/Services/LocationChannelManager.swift index bff1c89f..dbcdda57 100644 --- a/bitchat/Services/LocationChannelManager.swift +++ b/bitchat/Services/LocationChannelManager.swift @@ -291,6 +291,12 @@ final class LocationChannelManager: NSObject, CLLocationManagerDelegate, Observa } else if let locality = pm.locality, !locality.isEmpty { dict[.block] = locality } + // Building: prefer place name/street/venue when available + if let name = pm.name, !name.isEmpty { + dict[.building] = name + } else if let thoroughfare = pm.thoroughfare, !thoroughfare.isEmpty { + dict[.building] = thoroughfare + } return dict } } diff --git a/bitchat/Services/LocationNotesCounter.swift b/bitchat/Services/LocationNotesCounter.swift index 90682eb4..5e3f1285 100644 --- a/bitchat/Services/LocationNotesCounter.swift +++ b/bitchat/Services/LocationNotesCounter.swift @@ -6,7 +6,7 @@ final class LocationNotesCounter: ObservableObject { static let shared = LocationNotesCounter() @Published private(set) var geohash: String? = nil - @Published private(set) var count: Int? = nil + @Published private(set) var count: Int? = 0 @Published private(set) var initialLoadComplete: Bool = false private var subscriptionID: String? = nil @@ -19,7 +19,7 @@ final class LocationNotesCounter: ObservableObject { if geohash == norm { return } cancel() geohash = norm - count = nil + count = 0 noteIDs.removeAll() initialLoadComplete = false @@ -46,7 +46,7 @@ final class LocationNotesCounter: ObservableObject { } subscriptionID = nil geohash = nil - count = nil + count = 0 noteIDs.removeAll() } } diff --git a/bitchat/Views/ContentView.swift b/bitchat/Views/ContentView.swift index 0539a670..213a78c0 100644 --- a/bitchat/Views/ContentView.swift +++ b/bitchat/Views/ContentView.swift @@ -1180,7 +1180,7 @@ struct ContentView: View { LocationChannelManager.shared.enableLocationChannels() LocationChannelManager.shared.refreshChannels() // If we already have a block geohash, pass it; otherwise wait in the sheet. - notesGeohash = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .block })?.geohash + notesGeohash = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash showLocationNotes = true }) { HStack(alignment: .center, spacing: 4) { @@ -1193,6 +1193,7 @@ struct ContentView: View { .foregroundColor(Color(hue: 0.60, saturation: 0.85, brightness: 0.82)) .lineLimit(1) .fixedSize(horizontal: true, vertical: false) + .alignmentGuide(.firstTextBaseline) { d in d[.firstTextBaseline] } } } .fixedSize(horizontal: true, vertical: false) @@ -1234,7 +1235,7 @@ struct ContentView: View { } .sheet(isPresented: $showLocationNotes) { Group { - if let gh = notesGeohash ?? LocationChannelManager.shared.availableChannels.first(where: { $0.level == .block })?.geohash { + if let gh = notesGeohash ?? LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash { LocationNotesView(geohash: gh) .environmentObject(viewModel) } else { @@ -1268,8 +1269,8 @@ struct ContentView: View { .background(backgroundColor) .foregroundColor(textColor) .onChange(of: locationManager.availableChannels) { channels in - if notesGeohash == nil, let block = channels.first(where: { $0.level == .block }) { - notesGeohash = block.geohash + if notesGeohash == nil, let building = channels.first(where: { $0.level == .building }) { + notesGeohash = building.geohash } } } @@ -1481,8 +1482,8 @@ extension ContentView { private func updateNotesCounterSubscription() { switch locationManager.selectedChannel { case .mesh: - if let block = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .block })?.geohash { - LocationNotesCounter.shared.subscribe(geohash: block) + if let building = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash { + LocationNotesCounter.shared.subscribe(geohash: building) } else { LocationNotesCounter.shared.cancel() } diff --git a/bitchat/Views/LocationChannelsSheet.swift b/bitchat/Views/LocationChannelsSheet.swift index 19ab4a26..162bff2e 100644 --- a/bitchat/Views/LocationChannelsSheet.swift +++ b/bitchat/Views/LocationChannelsSheet.swift @@ -107,7 +107,7 @@ struct LocationChannelsSheet: View { // Nearby options if !manager.availableChannels.isEmpty { - ForEach(manager.availableChannels) { channel in + ForEach(manager.availableChannels.filter { $0.level != .building }) { channel in let coverage = coverageString(forPrecision: channel.geohash.count) let nameBase = locationName(for: channel.level) let namePart = nameBase.map { formattedNamePrefix(for: channel.level) + $0 } @@ -381,6 +381,7 @@ struct LocationChannelsSheet: View { case 5: return .city case 6: return .neighborhood case 7: return .block + case 8: return .building default: return .block } }