Files
damus/damus/Features/Actions/ActionBar/Views/EventDetailBar.swift
T
Daniel D’Aquino 991a4a86e6 Move most of RelayPool away from the Main Thread
This is a large refactor that aims to improve performance by offloading
RelayPool computations into a separate actor outside the main thread.

This should reduce congestion on the main thread and thus improve UI
performance.

Also, the internal subscription callback mechanism was changed to use
AsyncStreams to prevent race conditions newly found in that area of the
code.

Changelog-Fixed: Added performance improvements to timeline scrolling
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
2025-10-10 16:38:48 -07:00

93 lines
4.6 KiB
Swift

//
// EventDetailBar.swift
// damus
//
// Created by William Casarin on 2023-01-08.
//
import SwiftUI
struct EventDetailBar: View {
let state: DamusState
let target: NoteId
let target_pk: Pubkey
@ObservedObject var bar: ActionBarModel
@State var relays: [RelayURL] = []
init(state: DamusState, target: NoteId, target_pk: Pubkey) {
self.state = state
self.target = target
self.target_pk = target_pk
self._bar = ObservedObject(wrappedValue: make_actionbar_model(ev: target, damus: state))
}
var body: some View {
HStack {
if bar.boosts > 0 {
NavigationLink(value: Route.Reposts(reposts: .reposts(state: state, target: target))) {
let nounString = pluralizedString(key: "reposts_count", count: bar.boosts)
let noun = Text(nounString).foregroundColor(.gray)
Text("\(Text(verbatim: bar.boosts.formatted()).font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.")
}
.buttonStyle(PlainButtonStyle())
}
if bar.quote_reposts > 0 {
NavigationLink(value: Route.QuoteReposts(quotes: .quotes(state: state, target: target))) {
let nounString = pluralizedString(key: "quoted_reposts_count", count: bar.quote_reposts)
let noun = Text(nounString).foregroundColor(.gray)
Text("\(Text(verbatim: bar.quote_reposts.formatted()).font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many quoted reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.")
}
.buttonStyle(PlainButtonStyle())
}
if bar.likes > 0 && !state.settings.onlyzaps_mode {
NavigationLink(value: Route.Reactions(reactions: .likes(state: state, target: target))) {
let nounString = pluralizedString(key: "reactions_count", count: bar.likes)
let noun = Text(nounString).foregroundColor(.gray)
Text("\(Text(verbatim: bar.likes.formatted()).font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many reactions there are on a post. In source English, the first variable is the number of reactions, and the second variable is 'Reaction' or 'Reactions'.")
}
.buttonStyle(PlainButtonStyle())
}
if bar.zaps > 0 {
NavigationLink(value: Route.Zaps(target: .note(id: target, author: target_pk))) {
let nounString = pluralizedString(key: "zaps_count", count: bar.zaps)
let noun = Text(nounString).foregroundColor(.gray)
Text("\(Text(verbatim: bar.zaps.formatted()).font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many zap payments there are on a post. In source English, the first variable is the number of zap payments, and the second variable is 'Zap' or 'Zaps'.")
}
.buttonStyle(PlainButtonStyle())
}
if bar.relays > 0 {
NavigationLink(value: Route.UserRelays(relays: relays)) {
let nounString = pluralizedString(key: "relays_count", count: bar.relays)
let noun = Text(nounString).foregroundColor(.gray)
Text("\(Text(verbatim: bar.relays.formatted()).font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many relays a note was found on. In source English, the first variable is the number of relays, and the second variable is 'Relay' or 'Relays'.")
}
.buttonStyle(PlainButtonStyle())
}
}
.onAppear {
Task { await self.updateSeenRelays() }
}
.onReceive(handle_notify(.update_stats)) { noteId in
guard noteId == target else { return }
Task { await self.updateSeenRelays() }
}
}
func updateSeenRelays() async {
let relays = await Array(state.nostrNetwork.relayURLsThatSawNote(id: target) ?? [])
self.relays = relays
}
}
struct EventDetailBar_Previews: PreviewProvider {
static var previews: some View {
EventDetailBar(state: test_damus_state, target: .empty, target_pk: .empty)
}
}