Page MenuHomeMusing Studio

No OneTemporary

diff --git a/iOS/PostEditor/PostTextEditingView.swift b/iOS/PostEditor/PostTextEditingView.swift
index eede6da..a58fbae 100644
--- a/iOS/PostEditor/PostTextEditingView.swift
+++ b/iOS/PostEditor/PostTextEditingView.swift
@@ -1,101 +1,102 @@
import SwiftUI
struct PostTextEditingView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@ObservedObject var post: WFAPost
@Binding var updatingTitleFromServer: Bool
@Binding var updatingBodyFromServer: Bool
@State private var appearance: PostAppearance = .serif
@State private var titleTextStyle: UIFont = UIFont(name: "Lora-Regular", size: 26)!
@State private var titleTextHeight: CGFloat = 50
@State private var titleIsFirstResponder: Bool = true
@State private var bodyTextStyle: UIFont = UIFont(name: "Lora-Regular", size: 17)!
@State private var bodyIsFirstResponder: Bool = false
private let lineSpacingMultiplier: CGFloat = 0.5
init(
post: ObservedObject<WFAPost>,
updatingTitleFromServer: Binding<Bool>,
updatingBodyFromServer: Binding<Bool>
) {
self._post = post
self._updatingTitleFromServer = updatingTitleFromServer
self._updatingBodyFromServer = updatingBodyFromServer
UITextView.appearance().backgroundColor = .clear
}
var titleFieldHeight: CGFloat {
let minHeight: CGFloat = 50
if titleTextHeight < minHeight {
return minHeight
}
return titleTextHeight
}
var body: some View {
VStack {
ZStack(alignment: .topLeading) {
if post.title.count == 0 {
Text("Title (optional)")
.font(Font(titleTextStyle))
.foregroundColor(Color(UIColor.placeholderText))
.padding(.horizontal, 4)
.padding(.vertical, 8)
}
PostTitleTextView(
text: $post.title,
textStyle: $titleTextStyle,
height: $titleTextHeight,
- isFirstResponder: $titleIsFirstResponder
+ isFirstResponder: $titleIsFirstResponder,
+ lineSpacing: horizontalSizeClass == .compact ? lineSpacingMultiplier / 2 : lineSpacingMultiplier
)
.frame(height: titleFieldHeight)
.onChange(of: post.title) { _ in
if post.status == PostStatus.published.rawValue && !updatingTitleFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingTitleFromServer {
updatingTitleFromServer = false
}
}
}
ZStack(alignment: .topLeading) {
if post.body.count == 0 {
Text("Write…")
.font(Font(bodyTextStyle))
.foregroundColor(Color(UIColor.placeholderText))
.padding(.horizontal, 4)
.padding(.vertical, 8)
}
PostBodyTextView(
text: $post.body,
textStyle: $bodyTextStyle,
isFirstResponder: $bodyIsFirstResponder,
lineSpacing: horizontalSizeClass == .compact ? lineSpacingMultiplier / 2 : lineSpacingMultiplier
)
.onChange(of: post.body) { _ in
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingBodyFromServer {
updatingBodyFromServer = false
}
}
}
}
.onChange(of: titleIsFirstResponder, perform: { _ in
self.bodyIsFirstResponder.toggle()
})
.onAppear(perform: {
switch post.appearance {
case "sans":
self.appearance = .sans
case "wrap", "mono", "code":
self.appearance = .mono
default:
self.appearance = .serif
}
self.titleTextStyle = UIFont(name: appearance.rawValue, size: 26)!
self.bodyTextStyle = UIFont(name: appearance.rawValue, size: 17)!
})
}
}
diff --git a/iOS/PostEditor/PostTitleTextView.swift b/iOS/PostEditor/PostTitleTextView.swift
index 531feee..510ea31 100644
--- a/iOS/PostEditor/PostTitleTextView.swift
+++ b/iOS/PostEditor/PostTitleTextView.swift
@@ -1,92 +1,126 @@
// Based on https://lostmoa.com/blog/DynamicHeightForTextFieldInSwiftUI and https://stackoverflow.com/a/56508132/1234545
import SwiftUI
class PostTitleCoordinator: NSObject, UITextViewDelegate, NSLayoutManagerDelegate {
@Binding var text: String
@Binding var isFirstResponder: Bool
+ var lineSpacingMultiplier: CGFloat
var didBecomeFirstResponder: Bool = false
var postTitleTextView: PostTitleTextView
weak var textView: UITextView?
- init(_ textView: PostTitleTextView, text: Binding<String>, isFirstResponder: Binding<Bool>) {
+ init(
+ _ textView: PostTitleTextView,
+ text: Binding<String>,
+ isFirstResponder: Binding<Bool>,
+ lineSpacingMultiplier: CGFloat
+ ) {
self.postTitleTextView = textView
_text = text
_isFirstResponder = isFirstResponder
+ self.lineSpacingMultiplier = lineSpacingMultiplier
}
func textViewDidChange(_ textView: UITextView) {
DispatchQueue.main.async {
self.postTitleTextView.text = textView.text ?? ""
}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
self.isFirstResponder.toggle()
return false
}
return true
}
func layoutManager(
_ layoutManager: NSLayoutManager,
didCompleteLayoutFor textContainer: NSTextContainer?,
atEnd layoutFinishedFlag: Bool
) {
DispatchQueue.main.async {
guard let view = self.textView else { return }
let size = view.sizeThatFits(view.bounds.size)
if self.postTitleTextView.height != size.height {
self.postTitleTextView.height = size.height
}
}
}
+
+ func layoutManager(
+ _ layoutManager: NSLayoutManager,
+ lineSpacingAfterGlyphAt glyphIndex: Int,
+ withProposedLineFragmentRect rect: CGRect
+ ) -> CGFloat {
+ // HACK: - This seems to be the only way to get line spacing to update dynamically on iPad
+ // when switching between full-screen, split-screen, and slide-over views.
+ if let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first {
+ // Get the width of the window to determine the size class
+ if window.frame.width < 600 {
+ // Use 0.25 multiplier for compact size class
+ return 17 * 0.25
+ } else {
+ // Use 0.5 multiplier otherwise
+ return 17 * 0.5
+ }
+ } else {
+ return 17 * lineSpacingMultiplier
+ }
+ }
}
struct PostTitleTextView: UIViewRepresentable {
@Binding var text: String
@Binding var textStyle: UIFont
@Binding var height: CGFloat
@Binding var isFirstResponder: Bool
+ @State var lineSpacing: CGFloat
func makeUIView(context: UIViewRepresentableContext<PostTitleTextView>) -> UITextView {
let textView = UITextView()
textView.isEditable = true
textView.isUserInteractionEnabled = true
textView.isScrollEnabled = true
textView.alwaysBounceVertical = false
context.coordinator.textView = textView
textView.delegate = context.coordinator
textView.layoutManager.delegate = context.coordinator
let font = textStyle
let fontMetrics = UIFontMetrics(forTextStyle: .largeTitle)
textView.font = fontMetrics.scaledFont(for: font)
textView.backgroundColor = UIColor.clear
return textView
}
func makeCoordinator() -> PostTitleCoordinator {
- return Coordinator(self, text: $text, isFirstResponder: $isFirstResponder)
+ return Coordinator(
+ self,
+ text: $text,
+ isFirstResponder: $isFirstResponder,
+ lineSpacingMultiplier: lineSpacing
+ )
}
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<PostTitleTextView>) {
uiView.text = text
let font = textStyle
let fontMetrics = UIFontMetrics(forTextStyle: .largeTitle)
uiView.font = fontMetrics.scaledFont(for: font)
// We don't want the text field to become first responder every time SwiftUI refreshes the view.
if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
uiView.becomeFirstResponder()
context.coordinator.didBecomeFirstResponder = true
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 20, 1:51 AM (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3136556

Event Timeline