commit 715d4aa35d4dc1be61e89f9298d8a8e6a2759f7a
parent 4b54278378f56e8901d12f87a5fcb8722948ae21
Author: William Casarin <jb55@jb55.com>
Date: Fri, 10 Feb 2023 10:50:49 -0800
List zaps on posts
Diffstat:
6 files changed, 143 insertions(+), 10 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -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 */,
diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift
@@ -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)
}
}
diff --git a/damus/Models/ZapsModel.swift b/damus/Models/ZapsModel.swift
@@ -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()
+ }
+ }
+}
diff --git a/damus/Views/ActionBar/EventDetailBar.swift b/damus/Views/ActionBar/EventDetailBar.swift
@@ -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())
}
}
diff --git a/damus/Views/Events/SelectedEventView.swift b/damus/Views/Events/SelectedEventView.swift
@@ -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()
}
diff --git a/damus/Views/Zaps/ZapsView.swift b/damus/Views/Zaps/ZapsView.swift
@@ -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"))
+ }
+}