commit 0dd74fde7f73ee21dee938849ec4cc1501ca3043
parent 7a55ea13e3c548221a2dd11145fa060d16b43ab9
Author: ericholguin <eric.holguinsanchez@gmail.com>
Date: Wed, 29 Mar 2023 15:05:33 -0600
Improve reply view
Changelog-Changed: Improved look of reply view
Diffstat:
5 files changed, 152 insertions(+), 116 deletions(-)
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -312,9 +312,9 @@ struct ContentView: View {
case .report(let target):
MaybeReportView(target: target)
case .post:
- PostView(replying_to: nil, references: [], damus_state: damus_state!)
+ PostView(replying_to: nil, damus_state: damus_state!)
case .reply(let event):
- ReplyView(replying_to: event, damus: damus_state!)
+ PostView(replying_to: event, damus_state: damus_state!)
case .event:
EventDetailView()
case .filter:
diff --git a/damus/Views/ParicipantsView.swift b/damus/Views/ParicipantsView.swift
@@ -16,23 +16,34 @@ struct ParticipantsView: View {
var body: some View {
VStack {
- Text("Edit participants", comment: "Text indicating that the view is used for editing which participants are replied to in a note.")
+ Text("Replying to", comment: "Text indicating that the view is used for editing which participants are replied to in a note.")
+ .font(.headline)
HStack {
Spacer()
+
Button {
// Remove all "p" refs, keep "e" refs
references = originalReferences.eRefs
} label: {
Text("Remove all", comment: "Button label to remove all participants from a note reply.")
}
- .buttonStyle(.borderedProminent)
- Spacer()
+ .font(.system(size: 14, weight: .bold))
+ .frame(width: 100, height: 30)
+ .foregroundColor(.white)
+ .background(LINEAR_GRADIENT)
+ .clipShape(Capsule())
+
Button {
references = originalReferences
} label: {
Text("Add all", comment: "Button label to re-add all original participants as profiles to reply to in a note")
}
- .buttonStyle(.borderedProminent)
+ .font(.system(size: 14, weight: .bold))
+ .frame(width: 80, height: 30)
+ .foregroundColor(.white)
+ .background(LINEAR_GRADIENT)
+ .clipShape(Capsule())
+
Spacer()
}
VStack {
@@ -56,7 +67,7 @@ struct ParticipantsView: View {
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 30))
- .foregroundColor(references.contains(participant) ? .purple : .gray)
+ .foregroundColor(references.contains(participant) ? DamusColors.purple : .gray)
}
.onTapGesture {
if references.contains(participant) {
diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift
@@ -22,10 +22,12 @@ struct PostView: View {
@State var attach_camera: Bool = false
@State var error: String? = nil
+ @State var originalReferences: [ReferencedId] = []
+ @State var references: [ReferencedId] = []
+
@StateObject var image_upload: ImageUploadModel = ImageUploadModel()
let replying_to: NostrEvent?
- let references: [ReferencedId]
let damus_state: DamusState
@Environment(\.presentationMode) var presentationMode
@@ -105,10 +107,12 @@ struct PostView: View {
self.send_post()
}
}
+ .disabled(is_post_empty)
.font(.system(size: 14, weight: .bold))
.frame(width: 80, height: 30)
.foregroundColor(.white)
.background(LINEAR_GRADIENT)
+ .opacity(is_post_empty ? 0.5 : 1.0)
.clipShape(Capsule())
}
@@ -150,9 +154,7 @@ struct PostView: View {
Spacer()
- if !is_post_empty {
- PostButton
- }
+ PostButton
}
if let progress = image_upload.progress {
@@ -161,7 +163,7 @@ struct PostView: View {
}
}
.frame(height: 30)
- .padding([.top, .bottom], 4)
+ .padding([.bottom], 10)
}
func append_url(_ url: String) {
@@ -200,75 +202,97 @@ struct PostView: View {
}
var body: some View {
- VStack(alignment: .leading, spacing: 0) {
- let searching = get_searching_string(post.string)
-
- TopBar
-
- HStack(alignment: .top) {
- ProfilePicView(pubkey: damus_state.pubkey, size: 45.0, highlight: .none, profiles: damus_state.profiles)
+ GeometryReader { (deviceSize: GeometryProxy) in
+ VStack(alignment: .leading, spacing: 0) {
- TextEntry
- }
- .frame(maxHeight: searching == nil ? .infinity : 50)
-
- // This if-block observes @ for tagging
- if let searching {
- UserSearch(damus_state: damus_state, search: searching, post: $post)
- .frame(maxHeight: .infinity)
- } else {
- Divider()
- .padding([.bottom], 10)
+ let searching = get_searching_string(post.string)
+
+ TopBar
- AttachmentBar
+ ScrollViewReader { scroller in
+ ScrollView {
+ if let replying_to = replying_to {
+ ReplyView(replying_to: replying_to, damus: damus_state, originalReferences: $originalReferences, references: $references)
+ }
+ VStack(alignment: .leading, spacing: 0) {
+ HStack(alignment: .top) {
+ ProfilePicView(pubkey: damus_state.pubkey, size: PFP_SIZE, highlight: .none, profiles: damus_state.profiles)
+ .padding(.leading, replying_to != nil ? 15 : 0)
+
+ TextEntry
+ }
+ .frame(height: deviceSize.size.height*0.78)
+ .id("post")
+ }
+ }
+ .frame(maxHeight: searching == nil ? .infinity : 70)
+ .onAppear {
+ scroll_to_event(scroller: scroller, id: "post", delay: 1.0, animate: true, anchor: .top)
+ }
+ }
+
+ // This if-block observes @ for tagging
+ if let searching {
+ UserSearch(damus_state: damus_state, search: searching, post: $post)
+ .padding(.leading, replying_to != nil ? 15 : 0)
+ .frame(maxHeight: .infinity)
+ } else {
+ Divider()
+ .padding([.top, .bottom], 10)
+ VStack(alignment: .leading) {
+ AttachmentBar
+ }
+ }
}
- }
- .padding()
- .sheet(isPresented: $attach_media) {
- ImagePicker(sourceType: .photoLibrary, damusState: damus_state) { img in
- handle_upload(media: .image(img))
- } onVideoPicked: { url in
- handle_upload(media: .video(url))
+ .padding()
+ .sheet(isPresented: $attach_media) {
+ ImagePicker(sourceType: .photoLibrary, damusState: damus_state) { img in
+ handle_upload(media: .image(img))
+ } onVideoPicked: { url in
+ handle_upload(media: .video(url))
+ }
}
- }
- .sheet(isPresented: $attach_camera) {
- ImagePicker(sourceType: .camera, damusState: damus_state) { img in
- handle_upload(media: .image(img))
- } onVideoPicked: { url in
- handle_upload(media: .video(url))
+ .sheet(isPresented: $attach_camera) {
+ ImagePicker(sourceType: .camera, damusState: damus_state) { img in
+ handle_upload(media: .image(img))
+ } onVideoPicked: { url in
+ handle_upload(media: .video(url))
+ }
}
- }
- .onAppear() {
- if let replying_to {
- if damus_state.drafts.replies[replying_to] == nil {
- damus_state.drafts.post = NSMutableAttributedString(string: "")
+ .onAppear() {
+ if let replying_to {
+ references = gather_reply_ids(our_pubkey: damus_state.pubkey, from: replying_to)
+ originalReferences = references
+ if damus_state.drafts.replies[replying_to] == nil {
+ damus_state.drafts.post = NSMutableAttributedString(string: "")
+ }
+ if let p = damus_state.drafts.replies[replying_to] {
+ post = p
+ }
+ } else {
+ post = damus_state.drafts.post
}
- if let p = damus_state.drafts.replies[replying_to] {
- post = p
+
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
+ self.focus = true
}
- } else {
- post = damus_state.drafts.post
- }
-
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
- self.focus = true
}
- }
- .onDisappear {
- if let replying_to, let reply = damus_state.drafts.replies[replying_to], reply.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
- damus_state.drafts.replies.removeValue(forKey: replying_to)
- } else if replying_to == nil && damus_state.drafts.post.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
- damus_state.drafts.post = NSMutableAttributedString(string : "")
+ .onDisappear {
+ if let replying_to, let reply = damus_state.drafts.replies[replying_to], reply.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
+ damus_state.drafts.replies.removeValue(forKey: replying_to)
+ } else if replying_to == nil && damus_state.drafts.post.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
+ damus_state.drafts.post = NSMutableAttributedString(string : "")
+ }
}
+ .alert(NSLocalizedString("Note contains \"nsec1\" private key. Are you sure?", comment: "Alert user that they might be attempting to paste a private key and ask them to confirm."), isPresented: $showPrivateKeyWarning, actions: {
+ Button(NSLocalizedString("No", comment: "Button to cancel out of posting a note after being alerted that it looks like they might be posting a private key."), role: .cancel) {
+ showPrivateKeyWarning = false
+ }
+ Button(NSLocalizedString("Yes, Post with Private Key", comment: "Button to proceed with posting a note even though it looks like they might be posting a private key."), role: .destructive) {
+ self.send_post()
+ }
+ })
}
- .alert(NSLocalizedString("Note contains \"nsec1\" private key. Are you sure?", comment: "Alert user that they might be attempting to paste a private key and ask them to confirm."), isPresented: $showPrivateKeyWarning, actions: {
- Button(NSLocalizedString("No", comment: "Button to cancel out of posting a note after being alerted that it looks like they might be posting a private key."), role: .cancel) {
- showPrivateKeyWarning = false
- }
- Button(NSLocalizedString("Yes, Post with Private Key", comment: "Button to proceed with posting a note even though it looks like they might be posting a private key."), role: .destructive) {
- self.send_post()
- }
- })
}
}
@@ -295,6 +319,6 @@ func get_searching_string(_ post: String) -> String? {
struct PostView_Previews: PreviewProvider {
static var previews: some View {
- PostView(replying_to: nil, references: [], damus_state: test_damus_state())
+ PostView(replying_to: nil, damus_state: test_damus_state())
}
}
diff --git a/damus/Views/ReplyView.swift b/damus/Views/ReplyView.swift
@@ -7,71 +7,71 @@
import SwiftUI
-func all_referenced_pubkeys(_ ev: NostrEvent) -> [ReferencedId] {
- var keys = ev.referenced_pubkeys
- let ref = ReferencedId(ref_id: ev.pubkey, relay_id: nil, key: "p")
- keys.insert(ref, at: 0)
- return keys
-}
-
struct ReplyView: View {
let replying_to: NostrEvent
let damus: DamusState
- @State var originalReferences: [ReferencedId] = []
- @State var references: [ReferencedId] = []
-
+ @Binding var originalReferences: [ReferencedId]
+ @Binding var references: [ReferencedId]
@State var participantsShown: Bool = false
-
- var body: some View {
- VStack {
- Text("Replying to:", comment: "Indicating that the user is replying to the following listed people.")
-
- HStack(alignment: .top) {
+
+ var ReplyingToSection: some View {
+ HStack {
+ Group {
let names = references.pRefs
.map { pubkey in
let pk = pubkey.ref_id
let prof = damus.profiles.lookup(id: pk)
- return Profile.displayName(profile: prof, pubkey: pk).username
+ return "@" + Profile.displayName(profile: prof, pubkey: pk).username
}
- .joined(separator: ", ")
- Text(names)
+ .joined(separator: " ")
+ Text("Replying to ", comment: "Indicating that the user is replying to the following listed people.")
.foregroundColor(.gray)
+ .font(.footnote) +
+ Text(names.isEmpty ? "self" : names)
+ .foregroundColor(.accentColor)
.font(.footnote)
}
.onTapGesture {
participantsShown.toggle()
}
.sheet(isPresented: $participantsShown) {
- ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
- }
-
- ScrollViewReader { scroller in
- ScrollView {
- EventView(damus: damus, event: replying_to, options: [.no_action_bar])
-
- PostView(replying_to: replying_to, references: references, damus_state: damus)
- .frame(minHeight: 500, maxHeight: .infinity)
- .id("post")
- }
- .frame(maxHeight: .infinity)
- .onAppear {
- scroll_to_event(scroller: scroller, id: "post", delay: 1.0, animate: true, anchor: .top)
+ if #available(iOS 16.0, *) {
+ ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
+ .presentationDetents([.medium, .large])
+ .presentationDragIndicator(.visible)
+ } else {
+ ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
}
}
- }
- .padding()
- .onAppear {
- references = gather_reply_ids(our_pubkey: damus.pubkey, from: replying_to)
- originalReferences = references
+ .padding(.leading, 75)
+ Spacer()
}
}
-
-
-}
+
+ var body: some View {
+ VStack(alignment: .leading) {
-struct ReplyView_Previews: PreviewProvider {
- static var previews: some View {
- ReplyView(replying_to: NostrEvent(content: "hi", pubkey: "pubkey"), damus: test_damus_state(), references: [])
+ EventView(damus: damus, event: replying_to, options: [.no_action_bar])
+ .padding()
+ .background(GeometryReader { geometry in
+ let eventHeight = geometry.frame(in: .global).height
+ Rectangle()
+ .fill(Color.gray.opacity(0.25))
+ .frame(width: 2, height: eventHeight + 7)
+ .offset(x: 25, y: 40)
+ .padding(.leading)
+ })
+
+ ReplyingToSection
+ .background(GeometryReader { geometry in
+ let replyingToHeight = geometry.frame(in: .global).height
+ Rectangle()
+ .fill(Color.gray.opacity(0.25))
+ .frame(width: 2, height: replyingToHeight)
+ .offset(x: 25, y: 40)
+ .padding(.leading)
+ })
+ }
}
}
diff --git a/damus/Views/TextViewWrapper.swift b/damus/Views/TextViewWrapper.swift
@@ -13,6 +13,7 @@ struct TextViewWrapper: UIViewRepresentable {
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
+ textView.showsVerticalScrollIndicator = false
TextViewWrapper.setTextProperties(textView)
return textView
}