mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 14:25:20 +00:00
Switch location notes and UI helpers to building-level geohash (precision 8): add GeohashChannelLevel.building, map length 8, use building for notes selection and counter, add building name mapping
This commit is contained in:
@@ -2,6 +2,7 @@ import Foundation
|
|||||||
|
|
||||||
/// Levels of location channels mapped to geohash precisions.
|
/// Levels of location channels mapped to geohash precisions.
|
||||||
enum GeohashChannelLevel: CaseIterable, Codable, Equatable {
|
enum GeohashChannelLevel: CaseIterable, Codable, Equatable {
|
||||||
|
case building
|
||||||
case block
|
case block
|
||||||
case neighborhood
|
case neighborhood
|
||||||
case city
|
case city
|
||||||
@@ -11,6 +12,7 @@ enum GeohashChannelLevel: CaseIterable, Codable, Equatable {
|
|||||||
/// Geohash length used for this level.
|
/// Geohash length used for this level.
|
||||||
var precision: Int {
|
var precision: Int {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .building: return 8
|
||||||
case .block: return 7
|
case .block: return 7
|
||||||
case .neighborhood: return 6
|
case .neighborhood: return 6
|
||||||
case .city: return 5
|
case .city: return 5
|
||||||
@@ -21,6 +23,7 @@ enum GeohashChannelLevel: CaseIterable, Codable, Equatable {
|
|||||||
|
|
||||||
var displayName: String {
|
var displayName: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .building: return "Building"
|
||||||
case .block: return "Block"
|
case .block: return "Block"
|
||||||
case .neighborhood: return "Neighborhood"
|
case .neighborhood: return "Neighborhood"
|
||||||
case .city: return "City"
|
case .city: return "City"
|
||||||
@@ -35,6 +38,7 @@ extension GeohashChannelLevel {
|
|||||||
let container = try decoder.singleValueContainer()
|
let container = try decoder.singleValueContainer()
|
||||||
if let raw = try? container.decode(String.self) {
|
if let raw = try? container.decode(String.self) {
|
||||||
switch raw {
|
switch raw {
|
||||||
|
case "building": self = .building
|
||||||
case "block": self = .block
|
case "block": self = .block
|
||||||
case "neighborhood": self = .neighborhood
|
case "neighborhood": self = .neighborhood
|
||||||
case "city": self = .city
|
case "city": self = .city
|
||||||
@@ -46,6 +50,7 @@ extension GeohashChannelLevel {
|
|||||||
}
|
}
|
||||||
} else if let precision = try? container.decode(Int.self) {
|
} else if let precision = try? container.decode(Int.self) {
|
||||||
switch precision {
|
switch precision {
|
||||||
|
case 8: self = .building
|
||||||
case 7: self = .block
|
case 7: self = .block
|
||||||
case 6: self = .neighborhood
|
case 6: self = .neighborhood
|
||||||
case 5: self = .city
|
case 5: self = .city
|
||||||
@@ -61,6 +66,7 @@ extension GeohashChannelLevel {
|
|||||||
func encode(to encoder: Encoder) throws {
|
func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.singleValueContainer()
|
var container = encoder.singleValueContainer()
|
||||||
switch self {
|
switch self {
|
||||||
|
case .building: try container.encode("building")
|
||||||
case .block: try container.encode("block")
|
case .block: try container.encode("block")
|
||||||
case .neighborhood: try container.encode("neighborhood")
|
case .neighborhood: try container.encode("neighborhood")
|
||||||
case .city: try container.encode("city")
|
case .city: try container.encode("city")
|
||||||
|
|||||||
@@ -285,12 +285,18 @@ final class LocationChannelManager: NSObject, CLLocationManagerDelegate, Observa
|
|||||||
} else if let locality = pm.locality, !locality.isEmpty {
|
} else if let locality = pm.locality, !locality.isEmpty {
|
||||||
dict[.neighborhood] = locality
|
dict[.neighborhood] = locality
|
||||||
}
|
}
|
||||||
// Block: reuse neighborhood/locality granularity without exposing street level
|
// Block: reuse neighborhood/locality granularity
|
||||||
if let subLocality = pm.subLocality, !subLocality.isEmpty {
|
if let subLocality = pm.subLocality, !subLocality.isEmpty {
|
||||||
dict[.block] = subLocality
|
dict[.block] = subLocality
|
||||||
} else if let locality = pm.locality, !locality.isEmpty {
|
} else if let locality = pm.locality, !locality.isEmpty {
|
||||||
dict[.block] = locality
|
dict[.block] = locality
|
||||||
}
|
}
|
||||||
|
// Building: prefer place name/street address without numbers where possible
|
||||||
|
if let name = pm.name, !name.isEmpty {
|
||||||
|
dict[.building] = name
|
||||||
|
} else if let thoroughfare = pm.thoroughfare, !thoroughfare.isEmpty {
|
||||||
|
dict[.building] = thoroughfare
|
||||||
|
}
|
||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -474,7 +474,8 @@ struct ContentView: View {
|
|||||||
case 5: return .city
|
case 5: return .city
|
||||||
case 6: return .neighborhood
|
case 6: return .neighborhood
|
||||||
case 7: return .block
|
case 7: return .block
|
||||||
default: return .block
|
case 8: return .building
|
||||||
|
default: return .building
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let level = levelForLength(gh.count)
|
let level = levelForLength(gh.count)
|
||||||
@@ -1180,7 +1181,7 @@ struct ContentView: View {
|
|||||||
LocationChannelManager.shared.enableLocationChannels()
|
LocationChannelManager.shared.enableLocationChannels()
|
||||||
LocationChannelManager.shared.refreshChannels()
|
LocationChannelManager.shared.refreshChannels()
|
||||||
// If we already have a block geohash, pass it; otherwise wait in the sheet.
|
// 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
|
showLocationNotes = true
|
||||||
}) {
|
}) {
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
@@ -1231,7 +1232,7 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
.sheet(isPresented: $showLocationNotes) {
|
.sheet(isPresented: $showLocationNotes) {
|
||||||
Group {
|
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)
|
LocationNotesView(geohash: gh)
|
||||||
.environmentObject(viewModel)
|
.environmentObject(viewModel)
|
||||||
} else {
|
} else {
|
||||||
@@ -1265,8 +1266,8 @@ struct ContentView: View {
|
|||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
.onChange(of: locationManager.availableChannels) { channels in
|
.onChange(of: locationManager.availableChannels) { channels in
|
||||||
if notesGeohash == nil, let block = channels.first(where: { $0.level == .block }) {
|
if notesGeohash == nil, let building = channels.first(where: { $0.level == .building }) {
|
||||||
notesGeohash = block.geohash
|
notesGeohash = building.geohash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1478,8 +1479,8 @@ extension ContentView {
|
|||||||
private func updateNotesCounterSubscription() {
|
private func updateNotesCounterSubscription() {
|
||||||
switch locationManager.selectedChannel {
|
switch locationManager.selectedChannel {
|
||||||
case .mesh:
|
case .mesh:
|
||||||
if let block = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .block })?.geohash {
|
if let building = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash {
|
||||||
LocationNotesCounter.shared.subscribe(geohash: block)
|
LocationNotesCounter.shared.subscribe(geohash: building)
|
||||||
} else {
|
} else {
|
||||||
LocationNotesCounter.shared.cancel()
|
LocationNotesCounter.shared.cancel()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,7 +381,8 @@ struct LocationChannelsSheet: View {
|
|||||||
case 5: return .city
|
case 5: return .city
|
||||||
case 6: return .neighborhood
|
case 6: return .neighborhood
|
||||||
case 7: return .block
|
case 7: return .block
|
||||||
default: return .block
|
case 8: return .building
|
||||||
|
default: return .building
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,6 +463,8 @@ extension LocationChannelsSheet {
|
|||||||
switch level {
|
switch level {
|
||||||
case .region:
|
case .region:
|
||||||
return ""
|
return ""
|
||||||
|
case .building:
|
||||||
|
return ""
|
||||||
default:
|
default:
|
||||||
return "~"
|
return "~"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct LocationNotesSheet: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if let gh = notesGeohash ?? locationManager.availableChannels.first(where: { $0.level == .block })?.geohash {
|
if let gh = notesGeohash ?? locationManager.availableChannels.first(where: { $0.level == .building })?.geohash {
|
||||||
// Found block geohash: show notes view
|
// Found block geohash: show notes view
|
||||||
LocationNotesView(geohash: gh)
|
LocationNotesView(geohash: gh)
|
||||||
.environmentObject(viewModel)
|
.environmentObject(viewModel)
|
||||||
@@ -55,12 +55,11 @@ struct LocationNotesSheet: View {
|
|||||||
LocationChannelManager.shared.refreshChannels()
|
LocationChannelManager.shared.refreshChannels()
|
||||||
}
|
}
|
||||||
.onChange(of: locationManager.availableChannels) { channels in
|
.onChange(of: locationManager.availableChannels) { channels in
|
||||||
if notesGeohash == nil, let block = channels.first(where: { $0.level == .block }) {
|
if notesGeohash == nil, let building = channels.first(where: { $0.level == .building }) {
|
||||||
notesGeohash = block.geohash
|
notesGeohash = building.geohash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user