Co-authored-by: William Casarin <jb55@jb55.com> Changelog-Added: User tagging and autocompletion in posts Closes: #347 Fixes: #411, #63
125 lines
3.3 KiB
Swift
125 lines
3.3 KiB
Swift
//
|
|
// Post.swift
|
|
// damus
|
|
//
|
|
// Created by William Casarin on 2022-04-03.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
enum NostrPostResult {
|
|
case post(NostrPost)
|
|
case cancel
|
|
}
|
|
|
|
let POST_PLACEHOLDER = NSLocalizedString("Type your post here...", comment: "Text box prompt to ask user to type their post.")
|
|
|
|
struct PostView: View {
|
|
@State var post: String = ""
|
|
@FocusState var focus: Bool
|
|
|
|
let replying_to: NostrEvent?
|
|
let references: [ReferencedId]
|
|
let damus_state: DamusState
|
|
|
|
@Environment(\.presentationMode) var presentationMode
|
|
|
|
enum FocusField: Hashable {
|
|
case post
|
|
}
|
|
|
|
func cancel() {
|
|
NotificationCenter.default.post(name: .post, object: NostrPostResult.cancel)
|
|
dismiss()
|
|
}
|
|
|
|
func dismiss() {
|
|
self.presentationMode.wrappedValue.dismiss()
|
|
}
|
|
|
|
func send_post() {
|
|
var kind: NostrKind = .text
|
|
if replying_to?.known_kind == .chat {
|
|
kind = .chat
|
|
}
|
|
let content = self.post.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
|
let new_post = NostrPost(content: content, references: references, kind: kind)
|
|
|
|
NotificationCenter.default.post(name: .post, object: NostrPostResult.post(new_post))
|
|
dismiss()
|
|
}
|
|
|
|
var is_post_empty: Bool {
|
|
return post.allSatisfy { $0.isWhitespace }
|
|
}
|
|
|
|
var body: some View {
|
|
VStack {
|
|
HStack {
|
|
Button(NSLocalizedString("Cancel", comment: "Button to cancel out of posting a note.")) {
|
|
self.cancel()
|
|
}
|
|
.foregroundColor(.primary)
|
|
|
|
Spacer()
|
|
|
|
if !is_post_empty {
|
|
Button(NSLocalizedString("Post", comment: "Button to post a note.")) {
|
|
self.send_post()
|
|
}
|
|
}
|
|
}
|
|
.padding([.top, .bottom], 4)
|
|
|
|
ZStack(alignment: .topLeading) {
|
|
TextEditor(text: $post)
|
|
.focused($focus)
|
|
.textInputAutocapitalization(.sentences)
|
|
|
|
if post.isEmpty {
|
|
Text(POST_PLACEHOLDER)
|
|
.padding(.top, 8)
|
|
.padding(.leading, 4)
|
|
.foregroundColor(Color(uiColor: .placeholderText))
|
|
.allowsHitTesting(false)
|
|
}
|
|
}
|
|
|
|
// This if-block observes @ for tagging
|
|
if let searching = get_searching_string(post) {
|
|
VStack {
|
|
Spacer()
|
|
UserSearch(damus_state: damus_state, search: searching, post: $post)
|
|
}.zIndex(1)
|
|
}
|
|
}
|
|
.onAppear() {
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
self.focus = true
|
|
}
|
|
}
|
|
.padding()
|
|
}
|
|
}
|
|
|
|
func get_searching_string(_ post: String) -> String? {
|
|
guard let last_word = post.components(separatedBy: .whitespacesAndNewlines).last else {
|
|
return nil
|
|
}
|
|
|
|
guard last_word.count >= 2 else {
|
|
return nil
|
|
}
|
|
|
|
guard last_word.first! == "@" else {
|
|
return nil
|
|
}
|
|
|
|
// don't include @npub... strings
|
|
guard last_word.count != 64 else {
|
|
return nil
|
|
}
|
|
|
|
return String(last_word.dropFirst())
|
|
}
|