From 3a3da2f66d9e57b470c84ed089a07e54a14a6c3c Mon Sep 17 00:00:00 2001 From: jack Date: Sat, 13 Sep 2025 01:00:55 +0200 Subject: [PATCH] Location notes: acquire geohash on open (force refresh) and show Matrix loader until block-level geohash resolves; add LocationNotesSheet wrapper --- bitchat/Views/ContentView.swift | 34 ++++--------- bitchat/Views/LocationNotesSheet.swift | 66 ++++++++++++++++++++++++++ bitchat/Views/LocationNotesView.swift | 4 +- 3 files changed, 76 insertions(+), 28 deletions(-) create mode 100644 bitchat/Views/LocationNotesSheet.swift diff --git a/bitchat/Views/ContentView.swift b/bitchat/Views/ContentView.swift index 5c33914b..0205b530 100644 --- a/bitchat/Views/ContentView.swift +++ b/bitchat/Views/ContentView.swift @@ -1149,13 +1149,12 @@ struct ContentView: View { // Notes icon (mesh only), left of channel badge if case .mesh = locationManager.selectedChannel { Button(action: { - if let block = LocationChannelManager.shared.availableChannels.first(where: { $0.level == .block })?.geohash { - notesGeohash = block - showLocationNotes = true - } else { - notesGeohash = nil - showLocationNotes = true - } + // Kick a one-shot refresh and show the sheet immediately. + 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 + showLocationNotes = true }) { Image(systemName: "note.text") .font(.system(size: 12)) @@ -1222,25 +1221,8 @@ struct ContentView: View { .onDisappear { viewModel.isLocationChannelsSheetPresented = false } } .sheet(isPresented: $showLocationNotes) { - if let gh = notesGeohash { - LocationNotesView(geohash: gh) - .environmentObject(viewModel) - } else { - VStack(spacing: 12) { - Text("location unavailable") - .font(.system(size: 16, weight: .bold, design: .monospaced)) - Text("enable location to view notes for your street-level area") - .font(.system(size: 12, design: .monospaced)) - .foregroundColor(secondaryTextColor) - Button("enable location") { - LocationChannelManager.shared.enableLocationChannels() - } - .buttonStyle(.bordered) - } - .padding(20) - .background(backgroundColor) - .foregroundColor(textColor) - } + LocationNotesSheet(notesGeohash: $notesGeohash) + .environmentObject(viewModel) } .alert("heads up", isPresented: $viewModel.showScreenshotPrivacyWarning) { Button("ok", role: .cancel) {} diff --git a/bitchat/Views/LocationNotesSheet.swift b/bitchat/Views/LocationNotesSheet.swift new file mode 100644 index 00000000..cdef1213 --- /dev/null +++ b/bitchat/Views/LocationNotesSheet.swift @@ -0,0 +1,66 @@ +import SwiftUI + +struct LocationNotesSheet: View { + @EnvironmentObject var viewModel: ChatViewModel + @ObservedObject private var locationManager = LocationChannelManager.shared + @Binding var notesGeohash: String? + @Environment(\.dismiss) private var dismiss + @Environment(\.colorScheme) private var colorScheme + + private var backgroundColor: Color { colorScheme == .dark ? .black : .white } + private var textColor: Color { colorScheme == .dark ? .green : Color(red: 0, green: 0.5, blue: 0) } + private var secondaryTextColor: Color { textColor.opacity(0.8) } + + var body: some View { + Group { + if let gh = notesGeohash ?? locationManager.availableChannels.first(where: { $0.level == .block })?.geohash { + // Found block geohash: show notes view + LocationNotesView(geohash: gh) + .environmentObject(viewModel) + } else { + // Acquire location: keep a loading overlay (Matrix) until we either get a block geohash + ZStack { + VStack(spacing: 0) { + HStack { + VStack(alignment: .leading, spacing: 2) { + Text("notes") + .font(.system(size: 16, weight: .bold, design: .monospaced)) + Text("acquiring location…") + .font(.system(size: 12, design: .monospaced)) + .foregroundColor(secondaryTextColor) + } + Spacer() + Button(action: { dismiss() }) { + Image(systemName: "xmark") + .font(.system(size: 13, weight: .semibold, design: .monospaced)) + .foregroundColor(textColor) + .frame(width: 32, height: 32) + } + .buttonStyle(.plain) + .accessibilityLabel("Close") + } + .frame(height: 44) + .padding(.horizontal, 12) + .background(backgroundColor.opacity(0.95)) + Spacer() + } + MatrixRainView() + .transition(.opacity) + } + .background(backgroundColor) + .foregroundColor(textColor) + .onAppear { + LocationChannelManager.shared.enableLocationChannels() + // Nudge a fresh fix + LocationChannelManager.shared.refreshChannels() + } + .onChange(of: locationManager.availableChannels) { channels in + if notesGeohash == nil, let block = channels.first(where: { $0.level == .block }) { + notesGeohash = block.geohash + } + } + } + } + } +} + diff --git a/bitchat/Views/LocationNotesView.swift b/bitchat/Views/LocationNotesView.swift index 7cffb5f1..eec30aba 100644 --- a/bitchat/Views/LocationNotesView.swift +++ b/bitchat/Views/LocationNotesView.swift @@ -125,7 +125,7 @@ struct LocationNotesView: View { } // MARK: - Matrix Rain Loader -private struct MatrixRainView: View { +struct MatrixRainView: View { @Environment(\.colorScheme) var colorScheme private var fg: Color { colorScheme == .dark ? Color.green : Color(red: 0, green: 0.5, blue: 0) } private let charset = Array("01abcdefghijklmnopqrstuvwxyzアイウエオカキクケコハヒフヘホ0123456789") @@ -164,7 +164,7 @@ private struct MatrixRainView: View { } } -private struct RainColumn: View { +struct RainColumn: View { let charset: [Character] let columnWidth: CGFloat let height: CGFloat