mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 05:45:18 +00:00
* UI: replace textual 'close' with X icon\n\n- AppInfoView (iOS): use xmark icon in nav bar to match Location Notes style.\n- LocationChannelsSheet: use xmark icon for close on iOS/macOS toolbars; add accessibility label. * Location Notes: prefix usernames with @ and lighten #geohash\n\n- Show @ before usernames in notes list.\n- Split header into '@' and '#geohash' and color the geohash with secondary green for consistency. * Header spacing: add breathing room between channel badge, notes button, and people count\n\n- Add trailing padding after #mesh/#geohash badge.\n- Add leading padding before notes button and people counter to improve readability. * Header: nudge #mesh/#geohash badge right with leading padding * Location Notes + Header polish\n\n- Header: add space in '@ #geohash' and use darker green for geohash.\n- Notes list: render '@name#abcd' with darker green for #abcd to match chat.\n- Header: move geochat bookmark icon after #geohash badge with consistent spacing. * Location Notes: @name regular green, #abcd darker; nudge #hash\n\n- Render '@' and base name in regular green, suffix '#abcd' in darker green.\n- Add extra left padding before '#geohash' in notes header.\n- Increase leading padding for channel badge to push #mesh/#geohash further right. * Fix notes icon color: subscribe/count at block-level geohash\n\n- Use block (precision 7) geohash for notes: when opening sheet, on channel changes, and when subscribing the counter.\n- Aligns with LocationNotesManager which publishes at street-level geohash, allowing the counter to detect notes and turn icon blue. * Header spacing: move #mesh/#geohash closer to notes/bookmark\n\n- Reduce trailing padding on channel badge and leading padding on notes/bookmark to cluster them together.\n- Keeps larger gap before people count for readability. * Notes: standardize on building-level (8 chars) for publish/read\n\n- Use .building geohash when opening notes, reacting to channel updates, and subscribing the counter.\n- Update comments to reflect building-level scope. * Location Channels sheet: use black sheet background like other sheets\n\n- Add backgroundColor and apply to container and list.\n- Hide list default background with scrollContentBackground(.hidden). * Notes icon: use green when notes exist (matches app green) * Location Channels: boxed 'bookmarked' section; keep 'remove location access' outside box\n\n- Wrap bookmarked list in a rounded, subtle grey box within the list.\n- Ensure the 'remove location access' button is not inside the box and clears list row background. * Notes counter UX: avoid grey flicker when closing sheet\n\n- Preserve last count during resubscribe to prevent brief 0 state.\n- Keep existing subscription when building geohash temporarily unavailable; only cancel if none or permission revoked. * Notes counter: unsubscribe without clearing count on resubscribe\n\n- Avoid calling cancel() in subscribe; just unsubscribe old sub to prevent wiping count to 0.\n- Prevents green→grey flicker after closing sheet or location updates. * Notes icon: use sheet count until counter finishes initial load; don’t zero on sheet close\n\n- Compute hasNotes using max(count, sheetCount) while initialLoadComplete is false.\n- Remove sheetNotesCount reset on sheet disappear to avoid transient grey. * Location Notes header: remove extra gap before #geohash (drop leading padding) * Notes sheet: color #abcd suffix as darker green via opacity (match chat) * Notes sheet: show timestamp in brackets; drop #abcd from @name * chore: commit remaining local changes * Header: move notes + bookmark to left of #mesh/#geohash * Header spacing: tighten gap between #mesh/#geohash and peer count --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com>
54 lines
2.2 KiB
Swift
54 lines
2.2 KiB
Swift
import Foundation
|
|
|
|
/// Lightweight background counter for location notes (kind 1) at building-level geohash (8 chars).
|
|
@MainActor
|
|
final class LocationNotesCounter: ObservableObject {
|
|
static let shared = LocationNotesCounter()
|
|
|
|
@Published private(set) var geohash: String? = nil
|
|
@Published private(set) var count: Int? = 0
|
|
@Published private(set) var initialLoadComplete: Bool = false
|
|
|
|
private var subscriptionID: String? = nil
|
|
private var noteIDs = Set<String>()
|
|
|
|
private init() {}
|
|
|
|
func subscribe(geohash gh: String) {
|
|
let norm = gh.lowercased()
|
|
if geohash == norm, subscriptionID != nil { return }
|
|
// Unsubscribe previous without clearing count to avoid flicker
|
|
if let sub = subscriptionID { NostrRelayManager.shared.unsubscribe(id: sub) }
|
|
subscriptionID = nil
|
|
geohash = norm
|
|
noteIDs.removeAll()
|
|
initialLoadComplete = false
|
|
|
|
// Subscribe only to the building geohash (precision 8)
|
|
let subID = "locnotes-count-\(norm)-\(UUID().uuidString.prefix(6))"
|
|
subscriptionID = subID
|
|
let filter = NostrFilter.geohashNotes(norm, since: nil, limit: 500)
|
|
let relays = GeoRelayDirectory.shared.closestRelays(toGeohash: norm, count: TransportConfig.nostrGeoRelayCount)
|
|
let relayUrls: [String]? = relays.isEmpty ? nil : relays
|
|
NostrRelayManager.shared.subscribe(filter: filter, id: subID, relayUrls: relayUrls, handler: { [weak self] event in
|
|
guard let self = self else { return }
|
|
guard event.kind == NostrProtocol.EventKind.textNote.rawValue else { return }
|
|
guard event.tags.contains(where: { $0.count >= 2 && $0[0].lowercased() == "g" && $0[1].lowercased() == norm }) else { return }
|
|
if !self.noteIDs.contains(event.id) {
|
|
self.noteIDs.insert(event.id)
|
|
self.count = self.noteIDs.count
|
|
}
|
|
}, onEOSE: { [weak self] in
|
|
self?.initialLoadComplete = true
|
|
})
|
|
}
|
|
|
|
func cancel() {
|
|
if let sub = subscriptionID { NostrRelayManager.shared.unsubscribe(id: sub) }
|
|
subscriptionID = nil
|
|
geohash = nil
|
|
count = 0
|
|
noteIDs.removeAll()
|
|
}
|
|
}
|