commit 0f5e1dfb8181124c41a44a054d75b83108ae6281
parent a5cb10ddaa6d48deca2c7b4af095cdeb1ed61f94
Author: William Casarin <jb55@jb55.com>
Date: Fri, 5 May 2023 16:12:03 -0700
Properly scroll DM view when keyboard is open
Less DM jank!
Changelog-Fixed: Properly scroll DM view when keyboard is open
Diffstat:
3 files changed, 82 insertions(+), 37 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -141,6 +141,7 @@
4C75EFB728049D990006080F /* RelayPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFB628049D990006080F /* RelayPool.swift */; };
4C75EFB92804A2740006080F /* EventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFB82804A2740006080F /* EventView.swift */; };
4C75EFBB2804A34C0006080F /* ProofOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFBA2804A34C0006080F /* ProofOfWork.swift */; };
+ 4C7D09592A05BEAD00943473 /* KeyboardVisible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D09582A05BEAD00943473 /* KeyboardVisible.swift */; };
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7FF7D42823313F009601DB /* Mentions.swift */; };
4C8682872814DE470026224F /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8682862814DE470026224F /* ProfileView.swift */; };
4C8D00C829DF791C0036AF10 /* CompatibleAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00C729DF791C0036AF10 /* CompatibleAttribute.swift */; };
@@ -559,6 +560,7 @@
4C75EFB628049D990006080F /* RelayPool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayPool.swift; sourceTree = "<group>"; };
4C75EFB82804A2740006080F /* EventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventView.swift; sourceTree = "<group>"; };
4C75EFBA2804A34C0006080F /* ProofOfWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProofOfWork.swift; sourceTree = "<group>"; };
+ 4C7D09582A05BEAD00943473 /* KeyboardVisible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardVisible.swift; sourceTree = "<group>"; };
4C7FF7D42823313F009601DB /* Mentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mentions.swift; sourceTree = "<group>"; };
4C8682862814DE470026224F /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
4C8D00C729DF791C0036AF10 /* CompatibleAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompatibleAttribute.swift; sourceTree = "<group>"; };
@@ -1069,6 +1071,7 @@
4CDA128B29EB19C40006FA5A /* LocalNotification.swift */,
4CA5588229F33F5B00DC6A45 /* StringCodable.swift */,
50B5685229F97CB400A23243 /* CredentialHandler.swift */,
+ 4C7D09582A05BEAD00943473 /* KeyboardVisible.swift */,
);
path = Util;
sourceTree = "<group>";
@@ -1654,6 +1657,7 @@
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */,
4CB883A82975FC1800DC99E7 /* Zaps.swift in Sources */,
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
+ 4C7D09592A05BEAD00943473 /* KeyboardVisible.swift in Sources */,
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */,
4CC7AAEB297F0AEC00430951 /* BuilderEventView.swift in Sources */,
31D2E847295218AF006D67F8 /* Shimmer.swift in Sources */,
diff --git a/damus/Util/KeyboardVisible.swift b/damus/Util/KeyboardVisible.swift
@@ -0,0 +1,31 @@
+//
+// KeyboardVisible.swift
+// damus
+//
+// Created by William Casarin on 2023-05-05.
+//
+
+import Foundation
+import Combine
+import UIKit
+
+
+/// Publisher to read keyboard changes.
+protocol KeyboardReadable {
+ var keyboardPublisher: AnyPublisher<Bool, Never> { get }
+}
+
+extension KeyboardReadable {
+ var keyboardPublisher: AnyPublisher<Bool, Never> {
+ Publishers.Merge(
+ NotificationCenter.default
+ .publisher(for: UIResponder.keyboardWillShowNotification)
+ .map { _ in true },
+
+ NotificationCenter.default
+ .publisher(for: UIResponder.keyboardWillHideNotification)
+ .map { _ in false }
+ )
+ .eraseToAnyPublisher()
+ }
+}
diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift
@@ -6,8 +6,9 @@
//
import SwiftUI
+import Combine
-struct DMChatView: View {
+struct DMChatView: View, KeyboardReadable {
let damus_state: DamusState
@ObservedObject var dms: DirectMessageModel
@State var showPrivateKeyWarning: Bool = false
@@ -24,17 +25,37 @@ struct DMChatView: View {
DMView(event: dms.events[ind], damus_state: damus_state)
.contextMenu{MenuItems(event: ev, keypair: damus_state.keypair, target_pubkey: ev.pubkey, bookmarks: damus_state.bookmarks, muted_threads: damus_state.muted_threads)}
}
- EndBlock(height: 80)
+ EndBlock(height: 1)
}
.padding(.horizontal)
+
}
+ .dismissKeyboardOnTap()
.onAppear {
- scroller.scrollTo("endblock")
+ scroll_to_end(scroller)
}.onChange(of: dms.events.count) { _ in
- withAnimation {
- scroller.scrollTo("endblock")
+ scroll_to_end(scroller, animated: true)
+ }
+
+ Footer
+ .onReceive(keyboardPublisher) { visible in
+ guard visible else {
+ return
+ }
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+ scroll_to_end(scroller, animated: true)
+ }
}
+ }
+ }
+
+ func scroll_to_end(_ scroller: ScrollViewProxy, animated: Bool = false) {
+ if animated {
+ withAnimation {
+ scroller.scrollTo("endblock")
}
+ } else {
+ scroller.scrollTo("endblock")
}
}
@@ -87,37 +108,32 @@ struct DMChatView: View {
}
var Footer: some View {
- ZStack {
- BackgroundColor()
-
- HStack(spacing: 0) {
- InputField
-
- if !dms.draft.isEmpty {
- Button(
- role: .none,
- action: {
- showPrivateKeyWarning = contentContainsPrivateKey(dms.draft)
-
- if !showPrivateKeyWarning {
- send_message()
- }
+
+ HStack(spacing: 0) {
+ InputField
+
+ if !dms.draft.isEmpty {
+ Button(
+ role: .none,
+ action: {
+ showPrivateKeyWarning = contentContainsPrivateKey(dms.draft)
+
+ if !showPrivateKeyWarning {
+ send_message()
}
- ) {
- Label("", systemImage: "arrow.right.circle")
- .font(.title)
}
+ ) {
+ Label("", systemImage: "arrow.right.circle")
+ .font(.title)
}
}
+ }
+
+ /*
+ Text(dms.draft).opacity(0).padding(.all, 8)
.fixedSize(horizontal: false, vertical: true)
.frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
-
- Text(dms.draft).opacity(0).padding(.all, 8)
- .fixedSize(horizontal: false, vertical: true)
- .frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
- }
- .fixedSize(horizontal: false, vertical: true)
- .frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
+ */
}
func send_message() {
@@ -143,13 +159,6 @@ struct DMChatView: View {
var body: some View {
ZStack {
Messages
- .dismissKeyboardOnTap()
-
- VStack {
- Spacer()
-
- Footer
- }
Text("Send a message to start the conversation...", comment: "Text prompt for user to send a message to the other user.")
.lineLimit(nil)
@@ -238,3 +247,4 @@ extension View {
.background(content())
}
}
+