Files
damus/damus/Views/DMChatView.swift
William Casarin 24c4d99f78 DMs: copy decrypted text instead of raw content
Changelog-Fixed: Copying text in DMs will now copy the decrypted text
Signed-off-by: William Casarin <jb55@jb55.com>
2022-07-21 15:51:44 -07:00

159 lines
4.5 KiB
Swift

//
// DMChatView.swift
// damus
//
// Created by William Casarin on 2022-06-30.
//
import SwiftUI
struct DMChatView: View {
let damus_state: DamusState
let pubkey: String
@EnvironmentObject var dms: DirectMessageModel
@State var message: String = ""
var Messages: some View {
ScrollViewReader { scroller in
ScrollView {
VStack(alignment: .leading) {
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, privkey: damus_state.keypair.privkey)
}
Color.white.opacity(0)
.id("endblock")
.frame(height: 80)
}
}
.onAppear {
scroller.scrollTo("endblock")
}
}
}
var Header: some View {
let profile = damus_state.profiles.lookup(id: pubkey)
let pmodel = ProfileModel(pubkey: pubkey, damus: damus_state)
let fmodel = FollowersModel(damus_state: damus_state, target: pubkey)
let profile_page = ProfileView(damus_state: damus_state, profile: pmodel, followers: fmodel)
return NavigationLink(destination: profile_page) {
HStack {
ProfilePicView(pubkey: pubkey, size: 24, highlight: .none, image_cache: damus_state.image_cache, profiles: damus_state.profiles)
ProfileName(pubkey: pubkey, profile: profile)
}
}
.buttonStyle(PlainButtonStyle())
}
var InputField: some View {
TextField("New Encrypted Message", text: $message)
.padding([.leading, .trailing], 12)
.padding([.top, .bottom], 8)
.background {
InputBackground()
}
.foregroundColor(Color.primary)
.cornerRadius(20)
.padding(8)
}
@Environment(\.colorScheme) var colorScheme
func InputBackground() -> some View {
if colorScheme == .dark {
return Color.black.brightness(0.1)
} else {
return Color.gray.brightness(0.35)
}
}
func BackgroundColor() -> some View {
if colorScheme == .dark {
return Color.black.opacity(0.9)
} else {
return Color.white.opacity(0.9)
}
}
var Footer: some View {
ZStack {
BackgroundColor()
HStack(spacing: 0) {
InputField
if !message.isEmpty {
Button(role: .none, action: send_message) {
Label("", systemImage: "arrow.right.circle")
.font(.title)
}
}
}
}
.frame(height: 70)
}
func send_message() {
guard let dm = create_dm(message, to_pk: pubkey, keypair: damus_state.keypair) else {
print("error creating dm")
return
}
message = ""
damus_state.pool.send(.event(dm))
}
var body: some View {
ZStack {
Messages
.padding([.top, .leading, .trailing], 10)
.dismissKeyboardOnTap()
VStack {
Spacer()
Footer
}
}
.navigationTitle("DM")
.toolbar { Header }
}
}
struct DMChatView_Previews: PreviewProvider {
static var previews: some View {
let ev = NostrEvent(content: "hi", pubkey: "pubkey", kind: 1, tags: [])
let model = DirectMessageModel(events: [ev])
DMChatView(damus_state: test_damus_state(), pubkey: "pubkey")
.environmentObject(model)
}
}
func create_dm(_ message: String, to_pk: String, keypair: Keypair) -> NostrEvent?
{
guard let privkey = keypair.privkey else {
return nil
}
let tags = [["p", to_pk]]
let iv = random_bytes(count: 16).bytes
guard let shared_sec = get_shared_secret(privkey: privkey, pubkey: to_pk) else {
return nil
}
let utf8_message = Data(message.utf8).bytes
guard let enc_message = aes_encrypt(data: utf8_message, iv: iv, shared_sec: shared_sec) else {
return nil
}
let enc_content = encode_dm_base64(content: enc_message.bytes, iv: iv)
let ev = NostrEvent(content: enc_content, pubkey: keypair.pubkey, kind: 4, tags: tags)
ev.calculate_id()
ev.sign(privkey: privkey)
return ev
}