mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 04:25:21 +00:00
Notes counter: show 0 by default; subscribe at building-level (precision 8) for notes and counter; keep building hidden in channel list
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user