Embed text editor fields into ScrollView (#227)

* Embed text editor fields into ScrollView

* Bump version/build number and update change log

* Fix truncated post badges on status change

When going from a shorter label (e.g., ‘LOCAL’) to a longer one (e.g., ‘PUBLISHED’), the SwiftUI render loop would not expand the size of the post badge to fit the extra characters, so on change it would be truncated (e.g., read ‘PUBL…’). This change fixes the bug.
This commit is contained in:
Angelo Stavrow 2022-10-05 09:23:43 -04:00 committed by GitHub
parent 884da073e9
commit 4a3874abcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 11 deletions

View File

@ -21,7 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Mac] New drafts are created in the currently-selected blog, rather than being created in Drafts (or "Anonymous" for Write.as accounts). - [Mac] New drafts are created in the currently-selected blog, rather than being created in Drafts (or "Anonymous" for Write.as accounts).
- [Mac] Updated the URL and minimum version of the WriteFreely Swift package. - [Mac] Updated the URL and minimum version of the WriteFreely Swift package.
- [Mac] Upgraded the Sparkle package to v2. - [Mac] Upgraded the Sparkle package to v2.
- [Mac] The app now prompts you to reach out to our user forums if it detects a crash - [Mac] The app now prompts you to reach out to our user forums if it detects a crash.
- [iOS] The post editor now scrolls in its entirety, including the title field.
### Fixed ### Fixed

View File

@ -14,6 +14,7 @@ struct PostStatusBadgeView: View {
.padding(EdgeInsets(top: 2.5, leading: 7.5, bottom: 2.5, trailing: 7.5)) .padding(EdgeInsets(top: 2.5, leading: 7.5, bottom: 2.5, trailing: 7.5))
.background(badgeColor) .background(badgeColor)
.clipShape(RoundedRectangle(cornerRadius: 5.0, style: .circular)) .clipShape(RoundedRectangle(cornerRadius: 5.0, style: .circular))
.frame(width: .infinity)
} }
func setupBadgeProperties(for status: PostStatus) -> (String, Color) { func setupBadgeProperties(for status: PostStatus) -> (String, Color) {

View File

@ -1054,7 +1054,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements"; CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 676; CURRENT_PROJECT_VERSION = 679;
DEVELOPMENT_TEAM = TPPAB4YBA6; DEVELOPMENT_TEAM = TPPAB4YBA6;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist"; INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
@ -1066,7 +1066,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.0.11; MARKETING_VERSION = 1.0.12;
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform.ActionExtension-iOS"; PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform.ActionExtension-iOS";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1085,7 +1085,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements"; CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 676; CURRENT_PROJECT_VERSION = 679;
DEVELOPMENT_TEAM = TPPAB4YBA6; DEVELOPMENT_TEAM = TPPAB4YBA6;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist"; INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
@ -1097,7 +1097,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.0.11; MARKETING_VERSION = 1.0.12;
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform.ActionExtension-iOS"; PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform.ActionExtension-iOS";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1228,7 +1228,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements"; CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 676; CURRENT_PROJECT_VERSION = 679;
DEVELOPMENT_TEAM = TPPAB4YBA6; DEVELOPMENT_TEAM = TPPAB4YBA6;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = iOS/Info.plist; INFOPLIST_FILE = iOS/Info.plist;
@ -1237,7 +1237,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.11; MARKETING_VERSION = 1.0.12;
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform"; PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform";
PRODUCT_NAME = "WriteFreely-MultiPlatform"; PRODUCT_NAME = "WriteFreely-MultiPlatform";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1254,7 +1254,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements"; CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 676; CURRENT_PROJECT_VERSION = 679;
DEVELOPMENT_TEAM = TPPAB4YBA6; DEVELOPMENT_TEAM = TPPAB4YBA6;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = iOS/Info.plist; INFOPLIST_FILE = iOS/Info.plist;
@ -1263,7 +1263,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.11; MARKETING_VERSION = 1.0.12;
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform"; PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform";
PRODUCT_NAME = "WriteFreely-MultiPlatform"; PRODUCT_NAME = "WriteFreely-MultiPlatform";
SDKROOT = iphoneos; SDKROOT = iphoneos;

View File

@ -21,6 +21,20 @@ class PostBodyCoordinator: NSObject, UITextViewDelegate, NSLayoutManagerDelegate
_text = text _text = text
_isFirstResponder = isFirstResponder _isFirstResponder = isFirstResponder
self.lineSpacingMultiplier = lineSpacingMultiplier self.lineSpacingMultiplier = lineSpacingMultiplier
super.init()
updateSize()
}
func updateSize() {
DispatchQueue.main.async {
guard let view = self.textView else { return }
let size = view.sizeThatFits(view.bounds.size)
if self.postBodyTextView.height != size.height {
self.postBodyTextView.height = size.height
}
}
} }
func textViewDidChange(_ textView: UITextView) { func textViewDidChange(_ textView: UITextView) {
@ -34,6 +48,14 @@ class PostBodyCoordinator: NSObject, UITextViewDelegate, NSLayoutManagerDelegate
self.didBecomeFirstResponder = false self.didBecomeFirstResponder = false
} }
func layoutManager(
_ layoutManager: NSLayoutManager,
didCompleteLayoutFor textContainer: NSTextContainer?,
atEnd layoutFinishedFlag: Bool
) {
updateSize()
}
func layoutManager( func layoutManager(
_ layoutManager: NSLayoutManager, _ layoutManager: NSLayoutManager,
lineSpacingAfterGlyphAt glyphIndex: Int, lineSpacingAfterGlyphAt glyphIndex: Int,
@ -59,6 +81,7 @@ class PostBodyCoordinator: NSObject, UITextViewDelegate, NSLayoutManagerDelegate
struct PostBodyTextView: UIViewRepresentable { struct PostBodyTextView: UIViewRepresentable {
@Binding var text: String @Binding var text: String
@Binding var textStyle: UIFont @Binding var textStyle: UIFont
@Binding var height: CGFloat
@Binding var isFirstResponder: Bool @Binding var isFirstResponder: Bool
@State var lineSpacing: CGFloat @State var lineSpacing: CGFloat

View File

@ -8,10 +8,12 @@ struct PostTextEditingView: View {
@State private var appearance: PostAppearance = .serif @State private var appearance: PostAppearance = .serif
@State private var titleTextStyle: UIFont = UIFont(name: "Lora-Regular", size: 26)! @State private var titleTextStyle: UIFont = UIFont(name: "Lora-Regular", size: 26)!
@State private var titleTextHeight: CGFloat = 50 @State private var titleTextHeight: CGFloat = 50
@State private var bodyTextHeight: CGFloat = 50
@State private var titleIsFirstResponder: Bool = true @State private var titleIsFirstResponder: Bool = true
@State private var bodyTextStyle: UIFont = UIFont(name: "Lora-Regular", size: 17)! @State private var bodyTextStyle: UIFont = UIFont(name: "Lora-Regular", size: 17)!
@State private var bodyIsFirstResponder: Bool = false @State private var bodyIsFirstResponder: Bool = false
private let lineSpacingMultiplier: CGFloat = 0.5 private let lineSpacingMultiplier: CGFloat = 0.5
private let textEditorHeight: CGFloat = 50
init( init(
post: ObservedObject<WFAPost>, post: ObservedObject<WFAPost>,
@ -25,15 +27,22 @@ struct PostTextEditingView: View {
} }
var titleFieldHeight: CGFloat { var titleFieldHeight: CGFloat {
let minHeight: CGFloat = 50 let minHeight: CGFloat = textEditorHeight
if titleTextHeight < minHeight { if titleTextHeight < minHeight {
return minHeight return minHeight
} }
return titleTextHeight return titleTextHeight
} }
var bodyFieldHeight: CGFloat {
let minHeight: CGFloat = textEditorHeight
if bodyTextHeight < minHeight {
return minHeight
}
return bodyTextHeight
}
var body: some View { var body: some View {
VStack { ScrollView(.vertical) {
ZStack(alignment: .topLeading) { ZStack(alignment: .topLeading) {
if post.title.count == 0 { if post.title.count == 0 {
Text("Title (optional)") Text("Title (optional)")
@ -74,9 +83,11 @@ struct PostTextEditingView: View {
PostBodyTextView( PostBodyTextView(
text: $post.body, text: $post.body,
textStyle: $bodyTextStyle, textStyle: $bodyTextStyle,
height: $bodyTextHeight,
isFirstResponder: $bodyIsFirstResponder, isFirstResponder: $bodyIsFirstResponder,
lineSpacing: horizontalSizeClass == .compact ? lineSpacingMultiplier / 2 : lineSpacingMultiplier lineSpacing: horizontalSizeClass == .compact ? lineSpacingMultiplier / 2 : lineSpacingMultiplier
) )
.frame(height: bodyFieldHeight)
.accessibilityLabel(Text("Body")) .accessibilityLabel(Text("Body"))
.accessibilityHint(Text("Add or edit the body of your post")) .accessibilityHint(Text("Add or edit the body of your post"))
.onChange(of: post.body) { _ in .onChange(of: post.body) { _ in