mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 18:05:21 +00:00
geo: disable background sampling + notifications\n- Gate sampling to foreground only (beginGeohashSampling, watchers)\n- Suppress geohash activity notifications unless app is active\n- Stop sampling explicitly on background scene phase
This commit is contained in:
@@ -61,6 +61,10 @@ struct BitchatApp: App {
|
|||||||
// Optionally nudge Tor to dormant to save power
|
// Optionally nudge Tor to dormant to save power
|
||||||
TorManager.shared.setAppForeground(false)
|
TorManager.shared.setAppForeground(false)
|
||||||
TorManager.shared.goDormantOnBackground()
|
TorManager.shared.goDormantOnBackground()
|
||||||
|
// Stop geohash sampling while backgrounded
|
||||||
|
Task { @MainActor in
|
||||||
|
chatViewModel.endGeohashSampling()
|
||||||
|
}
|
||||||
// Proactively disconnect Nostr to avoid spurious socket errors while Tor is down
|
// Proactively disconnect Nostr to avoid spurious socket errors while Tor is down
|
||||||
NostrRelayManager.shared.disconnect()
|
NostrRelayManager.shared.disconnect()
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -632,7 +632,11 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
let regional = LocationChannelManager.shared.availableChannels.map { $0.geohash }
|
let regional = LocationChannelManager.shared.availableChannels.map { $0.geohash }
|
||||||
let bookmarks = GeohashBookmarksStore.shared.bookmarks
|
let bookmarks = GeohashBookmarksStore.shared.bookmarks
|
||||||
let union = Array(Set(regional).union(bookmarks))
|
let union = Array(Set(regional).union(bookmarks))
|
||||||
|
if TorManager.shared.isForeground() {
|
||||||
self.beginGeohashSampling(for: union)
|
self.beginGeohashSampling(for: union)
|
||||||
|
} else {
|
||||||
|
self.endGeohashSampling()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -658,7 +662,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
self.switchLocationChannel(to: LocationChannelManager.shared.selectedChannel)
|
self.switchLocationChannel(to: LocationChannelManager.shared.selectedChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background: keep sampling nearby geohashes + bookmarks for notifications even when sheet is closed
|
// Foreground-only: sample nearby geohashes + bookmarks (disabled in background)
|
||||||
LocationChannelManager.shared.$availableChannels
|
LocationChannelManager.shared.$availableChannels
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] channels in
|
.sink { [weak self] channels in
|
||||||
@@ -667,7 +671,11 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
let bookmarks = GeohashBookmarksStore.shared.bookmarks
|
let bookmarks = GeohashBookmarksStore.shared.bookmarks
|
||||||
let union = Array(Set(regional).union(bookmarks))
|
let union = Array(Set(regional).union(bookmarks))
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
|
if TorManager.shared.isForeground() {
|
||||||
self.beginGeohashSampling(for: union)
|
self.beginGeohashSampling(for: union)
|
||||||
|
} else {
|
||||||
|
self.endGeohashSampling()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
@@ -680,17 +688,21 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
let regional = LocationChannelManager.shared.availableChannels.map { $0.geohash }
|
let regional = LocationChannelManager.shared.availableChannels.map { $0.geohash }
|
||||||
let union = Array(Set(regional).union(bookmarks))
|
let union = Array(Set(regional).union(bookmarks))
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
|
if TorManager.shared.isForeground() {
|
||||||
self.beginGeohashSampling(for: union)
|
self.beginGeohashSampling(for: union)
|
||||||
|
} else {
|
||||||
|
self.endGeohashSampling()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
// Kick off initial sampling if we have regional channels or bookmarks
|
// Kick off initial sampling if we have regional channels or bookmarks (foreground only)
|
||||||
do {
|
do {
|
||||||
let regional = LocationChannelManager.shared.availableChannels.map { $0.geohash }
|
let regional = LocationChannelManager.shared.availableChannels.map { $0.geohash }
|
||||||
let bookmarks = GeohashBookmarksStore.shared.bookmarks
|
let bookmarks = GeohashBookmarksStore.shared.bookmarks
|
||||||
let union = Array(Set(regional).union(bookmarks))
|
let union = Array(Set(regional).union(bookmarks))
|
||||||
if !union.isEmpty {
|
if !union.isEmpty && TorManager.shared.isForeground() {
|
||||||
Task { @MainActor in self.beginGeohashSampling(for: union) }
|
Task { @MainActor in self.beginGeohashSampling(for: union) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1931,6 +1943,11 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
/// Begin sampling multiple geohashes (used by channel sheet) without changing active channel.
|
/// Begin sampling multiple geohashes (used by channel sheet) without changing active channel.
|
||||||
@MainActor
|
@MainActor
|
||||||
func beginGeohashSampling(for geohashes: [String]) {
|
func beginGeohashSampling(for geohashes: [String]) {
|
||||||
|
// Disable sampling when app is backgrounded (Tor is stopped there)
|
||||||
|
if !TorManager.shared.isForeground() {
|
||||||
|
endGeohashSampling()
|
||||||
|
return
|
||||||
|
}
|
||||||
// Determine which to add and which to remove
|
// Determine which to add and which to remove
|
||||||
let desired = Set(geohashes)
|
let desired = Set(geohashes)
|
||||||
let current = Set(geoSamplingSubs.values)
|
let current = Set(geoSamplingSubs.values)
|
||||||
@@ -1976,15 +1993,13 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
// Avoid notifications for old sampled events when launching or (re)subscribing
|
// Avoid notifications for old sampled events when launching or (re)subscribing
|
||||||
let eventTime = Date(timeIntervalSince1970: TimeInterval(event.created_at))
|
let eventTime = Date(timeIntervalSince1970: TimeInterval(event.created_at))
|
||||||
if Date().timeIntervalSince(eventTime) > 30 { return }
|
if Date().timeIntervalSince(eventTime) > 30 { return }
|
||||||
// Foreground policy: allow if it's a different geohash than the one currently open
|
// Foreground-only notifications: app must be active, and not already viewing this geohash
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
if UIApplication.shared.applicationState == .active {
|
guard UIApplication.shared.applicationState == .active else { return }
|
||||||
if case .location(let ch) = self.activeChannel, ch.geohash == gh { return }
|
if case .location(let ch) = self.activeChannel, ch.geohash == gh { return }
|
||||||
}
|
|
||||||
#elseif os(macOS)
|
#elseif os(macOS)
|
||||||
if NSApplication.shared.isActive {
|
guard NSApplication.shared.isActive else { return }
|
||||||
if case .location(let ch) = self.activeChannel, ch.geohash == gh { return }
|
if case .location(let ch) = self.activeChannel, ch.geohash == gh { return }
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
// Cooldown per geohash
|
// Cooldown per geohash
|
||||||
let now = Date()
|
let now = Date()
|
||||||
|
|||||||
Reference in New Issue
Block a user