Fix connectivity indicator and port signal bars from Android
The SignalView was never appearing because update_signal_from_pool was defined but never called, leaving signal data at 0/0. Fix by having RelayPool maintain its own SignalModel, updating it on connection events, relay add/remove. Wire views directly to the pool signal via NostrNetworkManager instead of the disconnected HomeModel.signal. Replace the text-based indicator with signal strength bars matching the Android app: 4 progressive-height bars colored red->yellow->green based on the connected/total relay ratio. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
07a7dbddc0
commit
aae43cff3b
@@ -252,7 +252,7 @@ struct ContentView: View {
|
||||
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
HStack(alignment: .center) {
|
||||
SignalView(state: damus_state!, signal: home.signal)
|
||||
SignalView(state: damus_state!, signal: damus_state!.nostrNetwork.signal)
|
||||
|
||||
// maybe expand this to other timelines in the future
|
||||
if selected_timeline == .search {
|
||||
|
||||
@@ -246,6 +246,11 @@ class NostrNetworkManager {
|
||||
var connectedRelays: [RelayPool.Relay] {
|
||||
self.pool.relays
|
||||
}
|
||||
|
||||
@MainActor
|
||||
var signal: SignalModel {
|
||||
self.pool.signal
|
||||
}
|
||||
|
||||
@MainActor
|
||||
var ourRelayDescriptors: [RelayPool.RelayDescriptor] {
|
||||
|
||||
@@ -51,6 +51,7 @@ class RelayPool {
|
||||
var message_received_function: (((String, RelayDescriptor)) -> Void)?
|
||||
var message_sent_function: (((String, Relay)) -> Void)?
|
||||
var delegate: Delegate?
|
||||
@MainActor
|
||||
private(set) var signal: SignalModel = SignalModel()
|
||||
|
||||
/// Tracks active leases on ephemeral relays to prevent premature cleanup.
|
||||
@@ -125,6 +126,18 @@ class RelayPool {
|
||||
return relays.reduce(0) { n, r in n + (r.connection.isConnected ? 1 : 0) }
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func update_signal() {
|
||||
let connected = num_connected
|
||||
let total = relays.count
|
||||
if signal.signal != connected {
|
||||
signal.signal = connected
|
||||
}
|
||||
if signal.max_signal != total {
|
||||
signal.max_signal = total
|
||||
}
|
||||
}
|
||||
|
||||
func remove_handler(sub_id: String) {
|
||||
self.handlers = handlers.filter {
|
||||
if $0.sub_id != sub_id {
|
||||
@@ -183,6 +196,7 @@ class RelayPool {
|
||||
|
||||
i += 1
|
||||
}
|
||||
update_signal()
|
||||
}
|
||||
|
||||
/// Acquires a lease on ephemeral relays to prevent them from being cleaned up
|
||||
@@ -269,6 +283,7 @@ class RelayPool {
|
||||
@MainActor
|
||||
private func appendRelayToList(relay: Relay) {
|
||||
self.relays.append(relay)
|
||||
update_signal()
|
||||
}
|
||||
|
||||
/// Ensures the given relay URLs are connected, adding them as ephemeral relays if not already in the pool.
|
||||
@@ -761,6 +776,7 @@ class RelayPool {
|
||||
run_queue(relay_id)
|
||||
await self.resubscribeAll(relayId: relay_id)
|
||||
}
|
||||
await update_signal()
|
||||
}
|
||||
|
||||
// Handle auth
|
||||
|
||||
@@ -10,25 +10,70 @@ import SwiftUI
|
||||
struct SignalView: View {
|
||||
let state: DamusState
|
||||
@ObservedObject var signal: SignalModel
|
||||
|
||||
|
||||
static let num_bars = 4
|
||||
static let bar_heights: [CGFloat] = [4, 7, 10, 13]
|
||||
static let bar_width: CGFloat = 3
|
||||
static let bar_spacing: CGFloat = 2
|
||||
|
||||
var ratio: Double {
|
||||
guard signal.max_signal > 0 else { return 0 }
|
||||
return Double(signal.signal) / Double(signal.max_signal)
|
||||
}
|
||||
|
||||
var active_bars: Int {
|
||||
if signal.signal == 0 { return 0 }
|
||||
return max(1, min(Self.num_bars, Int(ceil(ratio * Double(Self.num_bars)))))
|
||||
}
|
||||
|
||||
var active_color: Color {
|
||||
if ratio < 0.5 {
|
||||
let t = ratio * 2.0
|
||||
return Color(
|
||||
red: 1.0,
|
||||
green: 0.4 + 0.4 * t,
|
||||
blue: 0.4
|
||||
)
|
||||
} else {
|
||||
let t = (ratio - 0.5) * 2.0
|
||||
return Color(
|
||||
red: 1.0 - 0.6 * t,
|
||||
green: 0.8,
|
||||
blue: 0.4
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var inactive_color: Color {
|
||||
Color.gray.opacity(0.3)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if signal.signal != signal.max_signal {
|
||||
if signal.max_signal > 0 {
|
||||
NavigationLink(value: Route.RelayConfig) {
|
||||
Text("\(signal.signal)/\(signal.max_signal)", comment: "Fraction of how many of the user's relay servers that are operational.")
|
||||
.font(.callout)
|
||||
.foregroundColor(.gray)
|
||||
HStack(alignment: .bottom, spacing: Self.bar_spacing) {
|
||||
ForEach(0..<Self.num_bars, id: \.self) { i in
|
||||
RoundedRectangle(cornerRadius: 1)
|
||||
.fill(i < active_bars ? active_color : inactive_color)
|
||||
.frame(width: Self.bar_width, height: Self.bar_heights[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width:50,height:30)
|
||||
.disabled(signal.signal == signal.max_signal)
|
||||
.frame(width: 30, height: 30)
|
||||
.accessibilityLabel(Text("\(signal.signal)/\(signal.max_signal) relays connected"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct SignalView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SignalView(state: test_damus_state, signal: SignalModel(signal: 5, max_signal: 10))
|
||||
HStack(spacing: 20) {
|
||||
SignalView(state: test_damus_state, signal: SignalModel(signal: 0, max_signal: 10))
|
||||
SignalView(state: test_damus_state, signal: SignalModel(signal: 3, max_signal: 10))
|
||||
SignalView(state: test_damus_state, signal: SignalModel(signal: 5, max_signal: 10))
|
||||
SignalView(state: test_damus_state, signal: SignalModel(signal: 10, max_signal: 10))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,6 @@ class HomeModel: ContactsDelegate, ObservableObject {
|
||||
|
||||
@Published var loading: Bool = true
|
||||
|
||||
var signal = SignalModel()
|
||||
|
||||
var notifications = NotificationsModel()
|
||||
var notification_status = NotificationStatusModel()
|
||||
var events: EventHolder = EventHolder()
|
||||
@@ -1037,18 +1035,6 @@ class HomeModel: ContactsDelegate, ObservableObject {
|
||||
}
|
||||
|
||||
|
||||
func update_signal_from_pool(signal: SignalModel, pool: RelayPool) async {
|
||||
let relayCount = await pool.relays.count
|
||||
if signal.max_signal != relayCount {
|
||||
signal.max_signal = relayCount
|
||||
}
|
||||
|
||||
let numberOfConnectedRelays = await pool.num_connected
|
||||
if signal.signal != numberOfConnectedRelays {
|
||||
signal.signal = numberOfConnectedRelays
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func add_contact_if_friend(contacts: Contacts, ev: NostrEvent) {
|
||||
if !contacts.is_friend(ev.pubkey) {
|
||||
|
||||
@@ -82,7 +82,7 @@ struct PostingTimelineView: View {
|
||||
Spacer()
|
||||
|
||||
HStack(alignment: .center) {
|
||||
SignalView(state: damus_state, signal: home.signal)
|
||||
SignalView(state: damus_state, signal: damus_state.nostrNetwork.signal)
|
||||
if damus_state.settings.enable_favourites_feature {
|
||||
Image(systemName: "square.stack")
|
||||
.foregroundColor(DamusColors.purple)
|
||||
|
||||
Reference in New Issue
Block a user