List zaps on posts
This commit is contained in:
@@ -173,6 +173,8 @@
|
||||
4CE879502996B2BD00F758CC /* RelayStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8794F2996B2BD00F758CC /* RelayStatus.swift */; };
|
||||
4CE879522996B68900F758CC /* RelayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE879512996B68900F758CC /* RelayType.swift */; };
|
||||
4CE879552996BAB900F758CC /* RelayPaidDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE879542996BAB900F758CC /* RelayPaidDetail.swift */; };
|
||||
4CE879582996C45300F758CC /* ZapsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE879572996C45300F758CC /* ZapsView.swift */; };
|
||||
4CE8795B2996C47A00F758CC /* ZapsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8795A2996C47A00F758CC /* ZapsModel.swift */; };
|
||||
4CEE2AED2805B22500AB5EEF /* NostrRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AEC2805B22500AB5EEF /* NostrRequest.swift */; };
|
||||
4CEE2AF1280B216B00AB5EEF /* EventDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */; };
|
||||
4CEE2AF3280B25C500AB5EEF /* ProfilePicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF2280B25C500AB5EEF /* ProfilePicView.swift */; };
|
||||
@@ -472,6 +474,8 @@
|
||||
4CE8794F2996B2BD00F758CC /* RelayStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayStatus.swift; sourceTree = "<group>"; };
|
||||
4CE879512996B68900F758CC /* RelayType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayType.swift; sourceTree = "<group>"; };
|
||||
4CE879542996BAB900F758CC /* RelayPaidDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayPaidDetail.swift; sourceTree = "<group>"; };
|
||||
4CE879572996C45300F758CC /* ZapsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapsView.swift; sourceTree = "<group>"; };
|
||||
4CE8795A2996C47A00F758CC /* ZapsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapsModel.swift; sourceTree = "<group>"; };
|
||||
4CEE2AE72804F57C00AB5EEF /* libsecp256k1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsecp256k1.a; sourceTree = "<group>"; };
|
||||
4CEE2AEC2805B22500AB5EEF /* NostrRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrRequest.swift; sourceTree = "<group>"; };
|
||||
4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailView.swift; sourceTree = "<group>"; };
|
||||
@@ -655,6 +659,7 @@
|
||||
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */,
|
||||
3AAA95C9298DF87B00F3D526 /* TranslationService.swift */,
|
||||
3AAA95CB298E07E900F3D526 /* DeepLPlan.swift */,
|
||||
4CE8795A2996C47A00F758CC /* ZapsModel.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@@ -662,6 +667,7 @@
|
||||
4C75EFA227FA576C0006080F /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CE879562996C44A00F758CC /* Zaps */,
|
||||
4CB9D4A52992D01900A9A7E4 /* Profile */,
|
||||
4CAAD8AE29888A9B00060CEA /* Relays */,
|
||||
4CF0ABF42985CD4200D66079 /* Posting */,
|
||||
@@ -951,6 +957,14 @@
|
||||
path = Detail;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CE879562996C44A00F758CC /* Zaps */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CE879572996C45300F758CC /* ZapsView.swift */,
|
||||
);
|
||||
path = Zaps;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CEE2AE62804F57B00AB5EEF /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1245,12 +1259,14 @@
|
||||
4C3EA64928FF597700C48A62 /* bech32.c in Sources */,
|
||||
4CE879522996B68900F758CC /* RelayType.swift in Sources */,
|
||||
4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */,
|
||||
4CE8795B2996C47A00F758CC /* ZapsModel.swift in Sources */,
|
||||
4C3A1D3729637E0500558C0F /* PreviewCache.swift in Sources */,
|
||||
4C3EA67528FF7A5A00C48A62 /* take.c in Sources */,
|
||||
4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */,
|
||||
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */,
|
||||
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */,
|
||||
4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */,
|
||||
4CE879582996C45300F758CC /* ZapsView.swift in Sources */,
|
||||
4C633352283D419F00B1C9C3 /* SignalModel.swift in Sources */,
|
||||
9609F058296E220800069BF3 /* BannerImageView.swift in Sources */,
|
||||
4C363A94282704FA006E126D /* Post.swift in Sources */,
|
||||
|
||||
@@ -117,13 +117,17 @@ class HomeModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func handle_zap_event_with_zapper(_ ev: NostrEvent, zapper: String) {
|
||||
func handle_zap_event_with_zapper(_ ev: NostrEvent, our_pubkey: String, zapper: String) {
|
||||
guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper) else {
|
||||
return
|
||||
}
|
||||
|
||||
damus_state.zaps.add_zap(zap: zap)
|
||||
|
||||
guard zap.target.pubkey == our_pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
if !insert_uniq_sorted_event(events: ¬ifications, new_ev: ev, cmp: { $0.created_at > $1.created_at }) {
|
||||
return
|
||||
}
|
||||
@@ -138,12 +142,8 @@ class HomeModel: ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
guard ptag == damus_state.pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
if let local_zapper = damus_state.profiles.lookup_zapper(pubkey: damus_state.pubkey) {
|
||||
handle_zap_event_with_zapper(ev, zapper: local_zapper)
|
||||
handle_zap_event_with_zapper(ev, our_pubkey: damus_state.pubkey, zapper: local_zapper)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -161,7 +161,8 @@ class HomeModel: ObservableObject {
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.handle_zap_event_with_zapper(ev, zapper: zapper)
|
||||
self.damus_state.profiles.zappers[ptag] = zapper
|
||||
self.handle_zap_event_with_zapper(ev, our_pubkey: self.damus_state.pubkey, zapper: zapper)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
69
damus/Models/ZapsModel.swift
Normal file
69
damus/Models/ZapsModel.swift
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// ZapsModel.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-02-10.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class ZapsModel: ObservableObject {
|
||||
let profiles: Profiles
|
||||
let pool: RelayPool
|
||||
let target: ZapTarget
|
||||
var zaps: [Zap]
|
||||
|
||||
let zaps_subid = UUID().description
|
||||
|
||||
init(profiles: Profiles, pool: RelayPool, target: ZapTarget) {
|
||||
self.target = target
|
||||
self.profiles = profiles
|
||||
self.pool = pool
|
||||
self.zaps = []
|
||||
}
|
||||
|
||||
func subscribe() {
|
||||
var filter = NostrFilter.filter_kinds([9735])
|
||||
switch target {
|
||||
case .profile(let profile_id):
|
||||
filter.pubkeys = [profile_id]
|
||||
case .note(let note_target):
|
||||
filter.referenced_ids = [note_target.note_id]
|
||||
}
|
||||
pool.subscribe(sub_id: zaps_subid, filters: [filter], handler: handle_event)
|
||||
}
|
||||
|
||||
func unsubscribe() {
|
||||
pool.unsubscribe(sub_id: zaps_subid)
|
||||
}
|
||||
|
||||
func handle_event(relay_id: String, conn_ev: NostrConnectionEvent) {
|
||||
guard case .nostr_event(let resp) = conn_ev else {
|
||||
return
|
||||
}
|
||||
|
||||
guard resp.subid == zaps_subid else {
|
||||
return
|
||||
}
|
||||
|
||||
guard case .event(_, let ev) = resp else {
|
||||
return
|
||||
}
|
||||
|
||||
guard ev.kind == 9735 else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let zapper = profiles.lookup_zapper(pubkey: target.pubkey) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper) else {
|
||||
return
|
||||
}
|
||||
|
||||
if insert_uniq_sorted_zap(zaps: &zaps, new_zap: zap) {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import SwiftUI
|
||||
struct EventDetailBar: View {
|
||||
let state: DamusState
|
||||
let target: String
|
||||
let target_pk: String
|
||||
@ObservedObject var bar: ActionBarModel
|
||||
|
||||
var body: some View {
|
||||
@@ -29,7 +30,11 @@ struct EventDetailBar: View {
|
||||
}
|
||||
|
||||
if bar.zaps > 0 {
|
||||
Text("\(Text("\(bar.zaps)", comment: "Number of zap payments on a post.").font(.body.bold())) \(Text(String(format: NSLocalizedString("zaps_count", comment: "Part of a larger sentence to describe how many zap payments there are on a post."), bar.boosts)).foregroundColor(.gray))", 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'.")
|
||||
let dst = ZapsView(state: state, target: .note(id: target, author: target_pk))
|
||||
NavigationLink(destination: dst) {
|
||||
Text("\(Text("\(bar.zaps)", comment: "Number of zap payments on a post.").font(.body.bold())) \(Text(String(format: NSLocalizedString("zaps_count", comment: "Part of a larger sentence to describe how many zap payments there are on a post."), bar.boosts)).foregroundColor(.gray))", 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())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +42,6 @@ struct EventDetailBar: View {
|
||||
|
||||
struct EventDetailBar_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
EventDetailBar(state: test_damus_state(), target: "", bar: ActionBarModel.empty())
|
||||
EventDetailBar(state: test_damus_state(), target: "", target_pk: "", bar: ActionBarModel.empty())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ struct SelectedEventView: View {
|
||||
let bar = make_actionbar_model(ev: event, damus: damus)
|
||||
|
||||
if !bar.is_empty {
|
||||
EventDetailBar(state: damus, target: event.id, bar: bar)
|
||||
EventDetailBar(state: damus, target: event.id, target_pk: event.pubkey, bar: bar)
|
||||
Divider()
|
||||
}
|
||||
|
||||
|
||||
42
damus/Views/Zaps/ZapsView.swift
Normal file
42
damus/Views/Zaps/ZapsView.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// ZapsView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-02-10.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ZapsView: View {
|
||||
let state: DamusState
|
||||
@StateObject var model: ZapsModel
|
||||
|
||||
init(state: DamusState, target: ZapTarget) {
|
||||
self.state = state
|
||||
self._model = StateObject(wrappedValue: ZapsModel(profiles: state.profiles, pool: state.pool, target: target))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
LazyVStack {
|
||||
ForEach(model.zaps, id: \.event.id) { zap in
|
||||
ZapEvent(damus: state, zap: zap)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(NSLocalizedString("Zaps", comment: "Navigation bar title for the Zaps view."))
|
||||
.onAppear {
|
||||
model.subscribe()
|
||||
}
|
||||
.onDisappear {
|
||||
model.unsubscribe()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ZapsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ZapsView(state: test_damus_state(), target: .profile("pk"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user