damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit 9e2e8595e8b168d2e86e06a69216d41f53f3b10a
parent 331d7e979229bf7c6764ea4dcc2d5172e7d85057
Author: William Casarin <jb55@jb55.com>
Date:   Sat,  4 Feb 2023 09:55:16 -0800

move text event to its own file, improve zaps

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 8++++++++
Mdamus/Components/ZapButton.swift | 7+++----
Mdamus/Models/HomeModel.swift | 3++-
Mdamus/Views/ActionBar/EventActionBar.swift | 18++++++++++++++++--
Mdamus/Views/ActionBar/EventDetailBar.swift | 2+-
Mdamus/Views/EventView.swift | 91+++++++++++++++++--------------------------------------------------------------
Mdamus/Views/Events/BuilderEventView.swift | 29++++++++++++++++++-----------
Adamus/Views/Events/TextEvent.swift | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adamus/Views/Events/ZapEvent.swift | 33+++++++++++++++++++++++++++++++++
9 files changed, 172 insertions(+), 91 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -69,6 +69,8 @@ 4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD9281DCA1400B3DE84 /* LikeCounter.swift */; }; 4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */; }; 4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */; }; + 4C3D52B6298DB4E6001C5831 /* ZapEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3D52B5298DB4E6001C5831 /* ZapEvent.swift */; }; + 4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3D52B7298DB5C6001C5831 /* TextEvent.swift */; }; 4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA63C28FF52D600C48A62 /* bolt11.c */; }; 4C3EA64128FF553900C48A62 /* hash_u5.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA64028FF553900C48A62 /* hash_u5.c */; }; 4C3EA64428FF558100C48A62 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA64328FF558100C48A62 /* sha256.c */; }; @@ -315,6 +317,8 @@ 4C3BEFD9281DCA1400B3DE84 /* LikeCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeCounter.swift; sourceTree = "<group>"; }; 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Liked.swift; sourceTree = "<group>"; }; 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusState.swift; sourceTree = "<group>"; }; + 4C3D52B5298DB4E6001C5831 /* ZapEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapEvent.swift; sourceTree = "<group>"; }; + 4C3D52B7298DB5C6001C5831 /* TextEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEvent.swift; sourceTree = "<group>"; }; 4C3EA63B28FF52D600C48A62 /* bolt11.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bolt11.h; sourceTree = "<group>"; }; 4C3EA63C28FF52D600C48A62 /* bolt11.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bolt11.c; sourceTree = "<group>"; }; 4C3EA63E28FF54BD00C48A62 /* short_types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = short_types.h; sourceTree = "<group>"; }; @@ -771,6 +775,8 @@ 4CC7AAF7297F1CEE00430951 /* EventProfile.swift */, 4CC7AAF9297F64AC00430951 /* EventMenu.swift */, 4CF0ABE6298444FC00D66079 /* MutedEventView.swift */, + 4C3D52B5298DB4E6001C5831 /* ZapEvent.swift */, + 4C3D52B7298DB5C6001C5831 /* TextEvent.swift */, ); path = Events; sourceTree = "<group>"; @@ -1109,11 +1115,13 @@ 4C363A9028247A1D006E126D /* NostrLink.swift in Sources */, 4C0A3F8C280F5FCA000448DE /* ChatroomView.swift in Sources */, 4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */, + 4C3D52B6298DB4E6001C5831 /* ZapEvent.swift in Sources */, 647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */, F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */, 4C0A3F91280F6528000448DE /* ChatView.swift in Sources */, 4CF0ABE32981BC7D00D66079 /* UserView.swift in Sources */, 4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */, + 4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */, 4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */, 4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */, 4C75EFA627FF87A20006080F /* Nostr.swift in Sources */, diff --git a/damus/Components/ZapButton.swift b/damus/Components/ZapButton.swift @@ -109,6 +109,7 @@ struct ZapButton: View { } Text("\(bar.zap_total > 0 ? "\(format_msats_abbrev(bar.zap_total))" : "")") + .offset(x: 22) .font(.footnote) .foregroundColor(bar.zapped ? Color.orange : Color.gray) } @@ -119,12 +120,10 @@ struct ZapButton: View { } -/* struct ZapButton_Previews: PreviewProvider { static var previews: some View { - let bar = ActionBarModel.empty() - ZapButton(damus_state: test_damus_state(), event: NostrEvent(content: "hi", pubkey: "pk"), bar: bar) + let bar = ActionBarModel(likes: 0, boosts: 0, zaps: 10, zap_total: 15623414, our_like: nil, our_boost: nil, our_zap: nil) + ZapButton(damus_state: test_damus_state(), event: test_event, lnurl: "lnurl", bar: bar) } } -*/ diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -286,7 +286,7 @@ class HomeModel: ObservableObject { switch ev { case .event(let sub_id, let ev): // globally handle likes - let always_process = sub_id == notifications_subid || sub_id == contacts_subid || sub_id == home_subid || sub_id == dms_subid || sub_id == init_subid || ev.known_kind == .like || ev.known_kind == .contacts || ev.known_kind == .metadata + let always_process = sub_id == notifications_subid || sub_id == contacts_subid || sub_id == home_subid || sub_id == dms_subid || sub_id == init_subid || ev.known_kind == .like || ev.known_kind == .zap || ev.known_kind == .contacts || ev.known_kind == .metadata if !always_process { // TODO: other views like threads might have their own sub ids, so ignore those events... or should we? return @@ -787,3 +787,4 @@ func should_hide_event(contacts: Contacts, ev: NostrEvent) -> Bool { } return !ev.should_show_event } + diff --git a/damus/Views/ActionBar/EventActionBar.swift b/damus/Views/ActionBar/EventActionBar.swift @@ -21,13 +21,26 @@ enum ActionBarSheet: Identifiable { struct EventActionBar: View { let damus_state: DamusState let event: NostrEvent + let test_lnurl: String? let generator = UIImpactFeedbackGenerator(style: .medium) + // just used for previews @State var sheet: ActionBarSheet? = nil @State var confirm_boost: Bool = false @State var show_share_sheet: Bool = false @StateObject var bar: ActionBarModel + init(damus_state: DamusState, event: NostrEvent, bar: ActionBarModel, test_lnurl: String? = nil) { + self.damus_state = damus_state + self.event = event + self.test_lnurl = test_lnurl + _bar = StateObject.init(wrappedValue: bar) + } + + var lnurl: String? { + test_lnurl ?? damus_state.profiles.lookup(id: event.pubkey)?.lnurl + } + var body: some View { HStack { if damus_state.keypair.privkey != nil { @@ -51,6 +64,7 @@ struct EventActionBar: View { .foregroundColor(bar.boosted ? Color.green : Color.gray) } Spacer() + ZStack { LikeButton(liked: bar.liked) { if bar.liked { @@ -66,7 +80,7 @@ struct EventActionBar: View { } - if let lnurl = damus_state.profiles.lookup(id: event.pubkey)?.lnurl { + if let lnurl = self.lnurl { Spacer() ZapButton(damus_state: damus_state, event: event, lnurl: lnurl, bar: bar) } @@ -177,7 +191,7 @@ struct EventActionBar_Previews: PreviewProvider { EventActionBar(damus_state: ds, event: ev, bar: maxed_bar) - EventActionBar(damus_state: ds, event: ev, bar: zapbar) + EventActionBar(damus_state: ds, event: ev, bar: zapbar, test_lnurl: "lnurl") } .padding(20) } diff --git a/damus/Views/ActionBar/EventDetailBar.swift b/damus/Views/ActionBar/EventDetailBar.swift @@ -29,7 +29,7 @@ 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'.") + Text("\(Text("\(bar.zaps)", comment: "Number of zap payments on a post.").font(.body.bold())) \(Text(String(format: NSLocalizedString("Zaps", 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'.") } } } diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift @@ -57,36 +57,33 @@ struct EventView: View { } var body: some View { - return Group { - if event.known_kind == .boost, let inner_ev = event.inner_event { - VStack(alignment: .leading) { - let prof_model = ProfileModel(pubkey: event.pubkey, damus: damus) - let follow_model = FollowersModel(damus_state: damus, target: event.pubkey) - let prof = damus.profiles.lookup(id: event.pubkey) - let booster_profile = ProfileView(damus_state: damus, profile: prof_model, followers: follow_model) - - NavigationLink(destination: booster_profile) { - Reposted(damus: damus, pubkey: event.pubkey, profile: prof) + VStack { + if event.known_kind == .boost { + if let inner_ev = event.inner_event { + VStack(alignment: .leading) { + let prof_model = ProfileModel(pubkey: event.pubkey, damus: damus) + let follow_model = FollowersModel(damus_state: damus, target: event.pubkey) + let prof = damus.profiles.lookup(id: event.pubkey) + let booster_profile = ProfileView(damus_state: damus, profile: prof_model, followers: follow_model) + + NavigationLink(destination: booster_profile) { + Reposted(damus: damus, pubkey: event.pubkey, profile: prof) + } + .buttonStyle(PlainButtonStyle()) + TextEvent(damus: damus, event: inner_ev, pubkey: inner_ev.pubkey, has_action_bar: has_action_bar, booster_pubkey: event.pubkey) + .padding([.top], 1) } - .buttonStyle(PlainButtonStyle()) - TextEvent(inner_ev, pubkey: inner_ev.pubkey, booster_pubkey: event.pubkey) - .padding([.top], 1) + } else { + EmptyView() } } else if event.known_kind == .zap { if let zap = damus.zaps.zaps[event.id] { - VStack(alignment: .leading) { - Text("⚡️ \(format_msats(zap.invoice.amount))") - .font(.headline) - .padding([.top], 2) - - TextEvent(zap.request.ev, pubkey: zap.request.ev.pubkey, booster_pubkey: nil) - .padding([.top], 1) - } + ZapEvent(damus: damus, zap: zap) } else { EmptyView() } } else { - TextEvent(event, pubkey: pubkey) + TextEvent(damus: damus, event: event, pubkey: pubkey, has_action_bar: has_action_bar, booster_pubkey: nil) .padding([.top], 6) } @@ -94,56 +91,6 @@ struct EventView: View { .padding([.top], 4) } } - - func TextEvent(_ event: NostrEvent, pubkey: String, booster_pubkey: String? = nil) -> some View { - return HStack(alignment: .top) { - let profile = damus.profiles.lookup(id: pubkey) - - VStack { - let pmodel = ProfileModel(pubkey: pubkey, damus: damus) - let pv = ProfileView(damus_state: damus, profile: pmodel, followers: FollowersModel(damus_state: damus, target: pubkey)) - - NavigationLink(destination: pv) { - ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: .none, profiles: damus.profiles) - } - - Spacer() - } - - VStack(alignment: .leading) { - HStack(alignment: .center) { - EventProfileName(pubkey: pubkey, profile: profile, damus: damus, show_friend_confirmed: true, size: .normal) - - Text("\(format_relative_time(event.created_at))") - .foregroundColor(.gray) - - Spacer() - } - - EventBody(damus_state: damus, event: event, size: .normal) - - if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) { - BuilderEventView(damus: damus, event_id: mention.ref.id) - } - - if has_action_bar { - Rectangle().frame(height: 2).opacity(0) - - let bar = make_actionbar_model(ev: event, damus: damus) - - EventActionBar(damus_state: damus, event: event, bar: bar) - .padding([.top], 4) - } - } - .padding([.leading], 2) - } - .contentShape(Rectangle()) - .background(event_validity_color(event.validity)) - .id(event.id) - .frame(maxWidth: .infinity, minHeight: PFP_SIZE) - .padding([.bottom], 2) - .event_context_menu(event, keypair: damus.keypair, target_pubkey: pubkey) - } } // blame the porn bots for this code diff --git a/damus/Views/Events/BuilderEventView.swift b/damus/Views/Events/BuilderEventView.swift @@ -31,23 +31,30 @@ struct BuilderEventView: View { return } - // Is current event - if id == subscription_uuid { - if event != nil { - return - } - - event = nostr_event - - unsubscribe() + guard id == subscription_uuid else { + return + } + + guard nostr_event.known_kind == .text else { + return } + + if event != nil { + return + } + + event = nostr_event + + unsubscribe() } func load() { subscribe(filters: [ + NostrFilter(ids: [self.event_id], limit: 1), NostrFilter( - ids: [self.event_id], - limit: 1 + kinds: [NostrKind.zap.rawValue], + referenced_ids: [self.event_id], + limit: 500 ) ]) } diff --git a/damus/Views/Events/TextEvent.swift b/damus/Views/Events/TextEvent.swift @@ -0,0 +1,72 @@ +// +// TextEvent.swift +// damus +// +// Created by William Casarin on 2023-02-03. +// + +import SwiftUI + +struct TextEvent: View { + let damus: DamusState + let event: NostrEvent + let pubkey: String + let has_action_bar: Bool + let booster_pubkey: String? + + var body: some View { + HStack(alignment: .top) { + let profile = damus.profiles.lookup(id: pubkey) + + VStack { + let pmodel = ProfileModel(pubkey: pubkey, damus: damus) + let pv = ProfileView(damus_state: damus, profile: pmodel, followers: FollowersModel(damus_state: damus, target: pubkey)) + + NavigationLink(destination: pv) { + ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: .none, profiles: damus.profiles) + } + + Spacer() + } + + VStack(alignment: .leading) { + HStack(alignment: .center) { + EventProfileName(pubkey: pubkey, profile: profile, damus: damus, show_friend_confirmed: true, size: .normal) + + Text("\(format_relative_time(event.created_at))") + .foregroundColor(.gray) + + Spacer() + } + + EventBody(damus_state: damus, event: event, size: .normal) + + if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) { + BuilderEventView(damus: damus, event_id: mention.ref.id) + } + + if has_action_bar { + Rectangle().frame(height: 2).opacity(0) + + let bar = make_actionbar_model(ev: event, damus: damus) + + EventActionBar(damus_state: damus, event: event, bar: bar) + .padding([.top], 4) + } + } + .padding([.leading], 2) + } + .contentShape(Rectangle()) + .background(event_validity_color(event.validity)) + .id(event.id) + .frame(maxWidth: .infinity, minHeight: PFP_SIZE) + .padding([.bottom], 2) + .event_context_menu(event, keypair: damus.keypair, target_pubkey: pubkey) + } +} + +struct TextEvent_Previews: PreviewProvider { + static var previews: some View { + TextEvent(damus: test_damus_state(), event: test_event, pubkey: "pk", has_action_bar: true, booster_pubkey: nil) + } +} diff --git a/damus/Views/Events/ZapEvent.swift b/damus/Views/Events/ZapEvent.swift @@ -0,0 +1,33 @@ +// +// ZapEvent.swift +// damus +// +// Created by William Casarin on 2023-02-03. +// + +import SwiftUI + +struct ZapEvent: View { + let damus: DamusState + let zap: Zap + + var body: some View { + VStack(alignment: .leading) { + Text("⚡️ \(format_msats(zap.invoice.amount))") + .font(.headline) + .padding([.top], 2) + + TextEvent(damus: damus, event: zap.request.ev, pubkey: zap.request.ev.pubkey, has_action_bar: false, booster_pubkey: nil) + .padding([.top], 1) + } + } +} + +/* +struct ZapEvent_Previews: PreviewProvider { + static var previews: some View { + ZapEvent() + } +} + +*/