commit 366293315d93da92f6e7b2312cc714888b35c205
parent 471f29f7ea6847571deaa3313c5b632f26dc2a91
Author: William Casarin <jb55@jb55.com>
Date: Sun, 3 Jul 2022 09:23:08 -0700
Add DM button to profile
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
10 files changed, 102 insertions(+), 37 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
4C216F32286E388800040376 /* DMChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C216F31286E388800040376 /* DMChatView.swift */; };
4C216F34286F5ACD00040376 /* DMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C216F33286F5ACD00040376 /* DMView.swift */; };
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C216F352870A9A700040376 /* InputDismissKeyboard.swift */; };
+ 4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C216F372871EDE300040376 /* DirectMessageModel.swift */; };
4C285C8228385570008A31F1 /* CarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8128385570008A31F1 /* CarouselView.swift */; };
4C285C8428385690008A31F1 /* CreateAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8328385690008A31F1 /* CreateAccountView.swift */; };
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C85283892E7008A31F1 /* CreateAccountModel.swift */; };
@@ -132,6 +133,7 @@
4C216F31286E388800040376 /* DMChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMChatView.swift; sourceTree = "<group>"; };
4C216F33286F5ACD00040376 /* DMView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMView.swift; sourceTree = "<group>"; };
4C216F352870A9A700040376 /* InputDismissKeyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputDismissKeyboard.swift; sourceTree = "<group>"; };
+ 4C216F372871EDE300040376 /* DirectMessageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectMessageModel.swift; sourceTree = "<group>"; };
4C285C8128385570008A31F1 /* CarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselView.swift; sourceTree = "<group>"; };
4C285C8328385690008A31F1 /* CreateAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateAccountView.swift; sourceTree = "<group>"; };
4C285C85283892E7008A31F1 /* CreateAccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateAccountModel.swift; sourceTree = "<group>"; };
@@ -279,6 +281,7 @@
4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */,
4C649843285A952100EAE2B3 /* LocalUserConfig.swift */,
4C64987D286D082C00EAE2B3 /* DirectMessagesModel.swift */,
+ 4C216F372871EDE300040376 /* DirectMessageModel.swift */,
);
path = Models;
sourceTree = "<group>";
@@ -609,6 +612,7 @@
4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */,
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
+ 4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */,
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */,
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */,
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -123,7 +123,8 @@ struct ContentView: View {
.navigationTitle("Notifications")
case .dms:
- DirectMessagesView(damus_state: damus_state!, dms: $home.dms)
+ DirectMessagesView(damus_state: damus_state!)
+ .environmentObject(home.dms)
case .none:
EmptyView()
@@ -345,7 +346,8 @@ struct ContentView: View {
contacts: Contacts(),
tips: TipCounter(our_pubkey: pubkey),
image_cache: ImageCache(),
- profiles: Profiles()
+ profiles: Profiles(),
+ dms: home.dms
)
home.damus_state = self.damus_state!
diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift
@@ -16,12 +16,13 @@ struct DamusState {
let tips: TipCounter
let image_cache: ImageCache
let profiles: Profiles
+ let dms: DirectMessagesModel
var pubkey: String {
return keypair.pubkey
}
static var empty: DamusState {
- return DamusState.init(pool: RelayPool(), keypair: Keypair(pubkey: "", privkey: ""), likes: EventCounter(our_pubkey: ""), boosts: EventCounter(our_pubkey: ""), contacts: Contacts(), tips: TipCounter(our_pubkey: ""), image_cache: ImageCache(), profiles: Profiles())
+ return DamusState.init(pool: RelayPool(), keypair: Keypair(pubkey: "", privkey: ""), likes: EventCounter(our_pubkey: ""), boosts: EventCounter(our_pubkey: ""), contacts: Contacts(), tips: TipCounter(our_pubkey: ""), image_cache: ImageCache(), profiles: Profiles(), dms: DirectMessagesModel())
}
}
diff --git a/damus/Models/DirectMessageModel.swift b/damus/Models/DirectMessageModel.swift
@@ -0,0 +1,20 @@
+//
+// DirectMessageModel.swift
+// damus
+//
+// Created by William Casarin on 2022-07-03.
+//
+
+import Foundation
+
+class DirectMessageModel: ObservableObject {
+ @Published var events: [NostrEvent]
+
+ init(events: [NostrEvent]) {
+ self.events = events
+ }
+
+ init() {
+ self.events = []
+ }
+}
diff --git a/damus/Models/DirectMessagesModel.swift b/damus/Models/DirectMessagesModel.swift
@@ -8,8 +8,26 @@
import Foundation
class DirectMessagesModel: ObservableObject {
- @Published var events: [(String, [NostrEvent])] = []
+ @Published var dms: [(String, DirectMessageModel)] = []
@Published var loading: Bool = false
+ func lookup_or_create(_ pubkey: String) -> DirectMessageModel {
+ if let dm = lookup(pubkey) {
+ return dm
+ }
+
+ let new = DirectMessageModel()
+ dms.append((pubkey, new))
+ return new
+ }
+ func lookup(_ pubkey: String) -> DirectMessageModel? {
+ for dm in dms {
+ if pubkey == dm.0 {
+ return dm.1
+ }
+ }
+
+ return nil
+ }
}
diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift
@@ -44,7 +44,7 @@ class HomeModel: ObservableObject {
@Published var new_events: NewEventsBits = NewEventsBits()
@Published var notifications: [NostrEvent] = []
- @Published var dms: [(String, [NostrEvent])] = []
+ @Published var dms: DirectMessagesModel = DirectMessagesModel()
@Published var events: [NostrEvent] = []
@Published var loading: Bool = false
@Published var signal: SignalModel = SignalModel()
@@ -372,10 +372,10 @@ class HomeModel: ObservableObject {
}
}
- for (pk, _) in dms {
+ for (pk, _) in dms.dms {
if pk == the_pk {
found = true
- inserted = insert_uniq_sorted_event(events: &(dms[i].1), new_ev: ev) {
+ inserted = insert_uniq_sorted_event(events: &(dms.dms[i].1.events), new_ev: ev) {
$0.created_at < $1.created_at
}
@@ -386,14 +386,18 @@ class HomeModel: ObservableObject {
if !found {
inserted = true
- dms.append((the_pk, [ev]))
+ let model = DirectMessageModel(events: [ev])
+ dms.dms.append((the_pk, model))
}
if inserted {
handle_last_event(ev: ev, timeline: .dms)
- dms = dms.sorted { a, b in
- a.1.last!.created_at > b.1.last!.created_at
+ dms.dms = dms.dms.sorted { a, b in
+ if a.1.events.count > 0 && b.1.events.count > 0 {
+ return a.1.events.last!.created_at > b.1.events.last!.created_at
+ }
+ return true
}
}
}
diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift
@@ -10,15 +10,15 @@ import SwiftUI
struct DMChatView: View {
let damus_state: DamusState
let pubkey: String
- @Binding var events: [NostrEvent]
+ @EnvironmentObject var dms: DirectMessageModel
@State var message: String = ""
var Messages: some View {
ScrollViewReader { scroller in
ScrollView {
VStack(alignment: .leading) {
- ForEach(Array(zip(events, events.indices)), id: \.0.id) { (ev, ind) in
- DMView(event: events[ind], damus_state: damus_state)
+ ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in
+ DMView(event: dms.events[ind], damus_state: damus_state)
.event_context_menu(ev)
}
Color.white.opacity(0)
@@ -125,11 +125,11 @@ struct DMChatView: View {
struct DMChatView_Previews: PreviewProvider {
static var previews: some View {
let ev = NostrEvent(content: "hi", pubkey: "pubkey", kind: 1, tags: [])
- let evs = Binding<[NostrEvent]>.init(
- get: { [ev] },
- set: { _ in })
- DMChatView(damus_state: test_damus_state(), pubkey: "pubkey", events: evs)
+ let model = DirectMessageModel(events: [ev])
+
+ DMChatView(damus_state: test_damus_state(), pubkey: "pubkey")
+ .environmentObject(model)
}
}
diff --git a/damus/Views/DirectMessagesView.swift b/damus/Views/DirectMessagesView.swift
@@ -9,26 +9,33 @@ import SwiftUI
struct DirectMessagesView: View {
let damus_state: DamusState
- @Binding var dms: [(String, [NostrEvent])]
+ @EnvironmentObject var model: DirectMessagesModel
var MainContent: some View {
ScrollView {
VStack {
- ForEach(dms, id: \.0) { tup in
- let evs = Binding<[NostrEvent]>.init(
- get: { tup.1 },
- set: { _ in }
- )
- let chat = DMChatView(damus_state: damus_state, pubkey: tup.0, events: evs)
- NavigationLink(destination: chat) {
- EventView(damus: damus_state, event: tup.1.last!, pubkey: tup.0)
- }
- .buttonStyle(PlainButtonStyle())
+ ForEach(model.dms, id: \.0) { tup in
+ MaybeEvent(tup)
}
}
}
}
+ func MaybeEvent(_ tup: (String, DirectMessageModel)) -> some View {
+ Group {
+ if let ev = tup.1.events.last {
+ let chat = DMChatView(damus_state: damus_state, pubkey: tup.0)
+ .environmentObject(tup.1)
+ NavigationLink(destination: chat) {
+ EventView(damus: damus_state, event: ev, pubkey: tup.0)
+ }
+ .buttonStyle(PlainButtonStyle())
+ } else {
+ EmptyView()
+ }
+ }
+ }
+
var body: some View {
MainContent
.navigationTitle("Encrypted DMs")
@@ -41,12 +48,8 @@ struct DirectMessagesView_Previews: PreviewProvider {
pubkey: "pubkey",
kind: 4,
tags: [])
- let dms = Binding<[(String, [NostrEvent])]>.init(
- get: {
- return [ ("pubkey", [ ev ]) ]
- },
- set: { _ in }
- )
- DirectMessagesView(damus_state: test_damus_state(), dms: dms)
+ let model = DirectMessageModel(events: [ev])
+ DirectMessagesView(damus_state: test_damus_state())
+ .environmentObject(model)
}
}
diff --git a/damus/Views/NoteContentView.swift b/damus/Views/NoteContentView.swift
@@ -33,7 +33,7 @@ struct NoteContentView: View {
let md_opts: AttributedString.MarkdownParsingOptions =
.init(interpretedSyntax: .inlineOnlyPreservingWhitespace)
- guard var txt = try? AttributedString(markdown: content, options: md_opts) else {
+ guard let txt = try? AttributedString(markdown: content, options: md_opts) else {
return Text(content)
}
diff --git a/damus/Views/ProfileView.swift b/damus/Views/ProfileView.swift
@@ -75,6 +75,16 @@ struct ProfileView: View {
//@EnvironmentObject var profile: ProfileModel
+ var DMButton: some View {
+ let dm_model = damus_state.dms.lookup_or_create(profile.pubkey)
+ let dmview = DMChatView(damus_state: damus_state, pubkey: profile.pubkey)
+ .environmentObject(dm_model)
+ return NavigationLink(destination: dmview) {
+ Label("", systemImage: "text.bubble")
+ }
+ .buttonStyle(PlainButtonStyle())
+ }
+
var TopSection: some View {
VStack(alignment: .leading) {
let data = damus_state.profiles.lookup(id: profile.pubkey)
@@ -86,6 +96,9 @@ struct ProfileView: View {
Spacer()
+ DMButton
+ .padding([.trailing], 20)
+
FollowButtonView(target: profile.get_follow_target(), follow_state: damus_state.contacts.follow_state(profile.pubkey))
}
@@ -162,7 +175,7 @@ struct ProfileView_Previews: PreviewProvider {
func test_damus_state() -> DamusState {
let pubkey = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"
- let damus = DamusState(pool: RelayPool(), keypair: Keypair(pubkey: pubkey, privkey: "privkey"), likes: EventCounter(our_pubkey: pubkey), boosts: EventCounter(our_pubkey: pubkey), contacts: Contacts(), tips: TipCounter(our_pubkey: pubkey), image_cache: ImageCache(), profiles: Profiles())
+ let damus = DamusState(pool: RelayPool(), keypair: Keypair(pubkey: pubkey, privkey: "privkey"), likes: EventCounter(our_pubkey: pubkey), boosts: EventCounter(our_pubkey: pubkey), contacts: Contacts(), tips: TipCounter(our_pubkey: pubkey), image_cache: ImageCache(), profiles: Profiles(), dms: DirectMessagesModel())
let prof = Profile(name: "damus", display_name: "Damus", about: "iOS app!", picture: "https://damus.io/img/logo.png")
let tsprof = TimestampedProfile(profile: prof, timestamp: 0)