List zaps on posts
This commit is contained in:
@@ -173,6 +173,8 @@
|
|||||||
4CE879502996B2BD00F758CC /* RelayStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8794F2996B2BD00F758CC /* RelayStatus.swift */; };
|
4CE879502996B2BD00F758CC /* RelayStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE8794F2996B2BD00F758CC /* RelayStatus.swift */; };
|
||||||
4CE879522996B68900F758CC /* RelayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE879512996B68900F758CC /* RelayType.swift */; };
|
4CE879522996B68900F758CC /* RelayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE879512996B68900F758CC /* RelayType.swift */; };
|
||||||
4CE879552996BAB900F758CC /* RelayPaidDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE879542996BAB900F758CC /* RelayPaidDetail.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 */; };
|
4CEE2AED2805B22500AB5EEF /* NostrRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AEC2805B22500AB5EEF /* NostrRequest.swift */; };
|
||||||
4CEE2AF1280B216B00AB5EEF /* EventDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */; };
|
4CEE2AF1280B216B00AB5EEF /* EventDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */; };
|
||||||
4CEE2AF3280B25C500AB5EEF /* ProfilePicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF2280B25C500AB5EEF /* ProfilePicView.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailView.swift; sourceTree = "<group>"; };
|
||||||
@@ -655,6 +659,7 @@
|
|||||||
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */,
|
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */,
|
||||||
3AAA95C9298DF87B00F3D526 /* TranslationService.swift */,
|
3AAA95C9298DF87B00F3D526 /* TranslationService.swift */,
|
||||||
3AAA95CB298E07E900F3D526 /* DeepLPlan.swift */,
|
3AAA95CB298E07E900F3D526 /* DeepLPlan.swift */,
|
||||||
|
4CE8795A2996C47A00F758CC /* ZapsModel.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -662,6 +667,7 @@
|
|||||||
4C75EFA227FA576C0006080F /* Views */ = {
|
4C75EFA227FA576C0006080F /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4CE879562996C44A00F758CC /* Zaps */,
|
||||||
4CB9D4A52992D01900A9A7E4 /* Profile */,
|
4CB9D4A52992D01900A9A7E4 /* Profile */,
|
||||||
4CAAD8AE29888A9B00060CEA /* Relays */,
|
4CAAD8AE29888A9B00060CEA /* Relays */,
|
||||||
4CF0ABF42985CD4200D66079 /* Posting */,
|
4CF0ABF42985CD4200D66079 /* Posting */,
|
||||||
@@ -951,6 +957,14 @@
|
|||||||
path = Detail;
|
path = Detail;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
4CE879562996C44A00F758CC /* Zaps */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4CE879572996C45300F758CC /* ZapsView.swift */,
|
||||||
|
);
|
||||||
|
path = Zaps;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4CEE2AE62804F57B00AB5EEF /* Frameworks */ = {
|
4CEE2AE62804F57B00AB5EEF /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1245,12 +1259,14 @@
|
|||||||
4C3EA64928FF597700C48A62 /* bech32.c in Sources */,
|
4C3EA64928FF597700C48A62 /* bech32.c in Sources */,
|
||||||
4CE879522996B68900F758CC /* RelayType.swift in Sources */,
|
4CE879522996B68900F758CC /* RelayType.swift in Sources */,
|
||||||
4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */,
|
4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */,
|
||||||
|
4CE8795B2996C47A00F758CC /* ZapsModel.swift in Sources */,
|
||||||
4C3A1D3729637E0500558C0F /* PreviewCache.swift in Sources */,
|
4C3A1D3729637E0500558C0F /* PreviewCache.swift in Sources */,
|
||||||
4C3EA67528FF7A5A00C48A62 /* take.c in Sources */,
|
4C3EA67528FF7A5A00C48A62 /* take.c in Sources */,
|
||||||
4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */,
|
4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */,
|
||||||
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */,
|
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */,
|
||||||
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */,
|
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */,
|
||||||
4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */,
|
4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */,
|
||||||
|
4CE879582996C45300F758CC /* ZapsView.swift in Sources */,
|
||||||
4C633352283D419F00B1C9C3 /* SignalModel.swift in Sources */,
|
4C633352283D419F00B1C9C3 /* SignalModel.swift in Sources */,
|
||||||
9609F058296E220800069BF3 /* BannerImageView.swift in Sources */,
|
9609F058296E220800069BF3 /* BannerImageView.swift in Sources */,
|
||||||
4C363A94282704FA006E126D /* Post.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 {
|
guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
damus_state.zaps.add_zap(zap: zap)
|
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 }) {
|
if !insert_uniq_sorted_event(events: ¬ifications, new_ev: ev, cmp: { $0.created_at > $1.created_at }) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -138,12 +142,8 @@ class HomeModel: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard ptag == damus_state.pubkey else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let local_zapper = damus_state.profiles.lookup_zapper(pubkey: damus_state.pubkey) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +161,8 @@ class HomeModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
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 {
|
struct EventDetailBar: View {
|
||||||
let state: DamusState
|
let state: DamusState
|
||||||
let target: String
|
let target: String
|
||||||
|
let target_pk: String
|
||||||
@ObservedObject var bar: ActionBarModel
|
@ObservedObject var bar: ActionBarModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -29,7 +30,11 @@ struct EventDetailBar: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bar.zaps > 0 {
|
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 {
|
struct EventDetailBar_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
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)
|
let bar = make_actionbar_model(ev: event, damus: damus)
|
||||||
|
|
||||||
if !bar.is_empty {
|
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()
|
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