mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Use PostBodyTitleView and PostBodyTextView for post editor
This commit is contained in:
parent
86cf0e976d
commit
3becfcbf73
@ -3,8 +3,8 @@ import CoreData
|
|||||||
|
|
||||||
enum PostAppearance: String {
|
enum PostAppearance: String {
|
||||||
case sans = "OpenSans-Regular"
|
case sans = "OpenSans-Regular"
|
||||||
case mono = "Hack"
|
case mono = "Hack-Regular"
|
||||||
case serif = "Lora"
|
case serif = "Lora-Regular"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PostEditorModel {
|
struct PostEditorModel {
|
||||||
|
@ -24,6 +24,7 @@ struct PostBodyTextView: UIViewRepresentable {
|
|||||||
@Binding var text: String
|
@Binding var text: String
|
||||||
@Binding var textStyle: UIFont
|
@Binding var textStyle: UIFont
|
||||||
@Binding var isFirstResponder: Bool
|
@Binding var isFirstResponder: Bool
|
||||||
|
var lineSpacing: CGFloat
|
||||||
|
|
||||||
func makeUIView(context: UIViewRepresentableContext<PostBodyTextView>) -> UITextView {
|
func makeUIView(context: UIViewRepresentableContext<PostBodyTextView>) -> UITextView {
|
||||||
let textView = UITextView(frame: .zero)
|
let textView = UITextView(frame: .zero)
|
||||||
@ -40,7 +41,16 @@ struct PostBodyTextView: UIViewRepresentable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<PostBodyTextView>) {
|
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<PostBodyTextView>) {
|
||||||
uiView.text = text
|
let attributedString = NSMutableAttributedString(string: text)
|
||||||
|
let paragraphStyle = NSMutableParagraphStyle()
|
||||||
|
paragraphStyle.lineSpacing = lineSpacing
|
||||||
|
attributedString.addAttribute(
|
||||||
|
NSAttributedString.Key.paragraphStyle,
|
||||||
|
value: paragraphStyle,
|
||||||
|
range: NSMakeRange(0, attributedString.length) // swiftlint:disable:this legacy_constructor
|
||||||
|
)
|
||||||
|
|
||||||
|
uiView.attributedText = attributedString
|
||||||
let font = textStyle
|
let font = textStyle
|
||||||
let fontMetrics = UIFontMetrics(forTextStyle: .largeTitle)
|
let fontMetrics = UIFontMetrics(forTextStyle: .largeTitle)
|
||||||
uiView.font = fontMetrics.scaledFont(for: font)
|
uiView.font = fontMetrics.scaledFont(for: font)
|
||||||
|
@ -6,6 +6,11 @@ struct PostTextEditingView: View {
|
|||||||
@Binding var updatingTitleFromServer: Bool
|
@Binding var updatingTitleFromServer: Bool
|
||||||
@Binding var updatingBodyFromServer: Bool
|
@Binding var updatingBodyFromServer: Bool
|
||||||
@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 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 bodyLineSpacingMultiplier: CGFloat = 0.5
|
private let bodyLineSpacingMultiplier: CGFloat = 0.5
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@ -19,41 +24,69 @@ struct PostTextEditingView: View {
|
|||||||
UITextView.appearance().backgroundColor = .clear
|
UITextView.appearance().backgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var titleFieldHeight: CGFloat {
|
||||||
|
let minHeight: CGFloat = 50
|
||||||
|
if titleTextHeight < minHeight {
|
||||||
|
return minHeight
|
||||||
|
}
|
||||||
|
return titleTextHeight
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
TextField("Title (optional)", text: $post.title)
|
|
||||||
.font(.custom(appearance.rawValue, size: 26, relativeTo: .largeTitle))
|
|
||||||
.padding(.horizontal, 4)
|
|
||||||
.onChange(of: post.title) { _ in
|
|
||||||
if post.status == PostStatus.published.rawValue && !updatingTitleFromServer {
|
|
||||||
post.status = PostStatus.edited.rawValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ZStack(alignment: .topLeading) {
|
ZStack(alignment: .topLeading) {
|
||||||
if post.body.count == 0 {
|
if post.title.count == 0 {
|
||||||
Text("Write…")
|
Text("Title (optional)")
|
||||||
.font(.custom(appearance.rawValue, size: 17, relativeTo: .body))
|
.font(Font(titleTextStyle))
|
||||||
.foregroundColor(Color(UIColor.placeholderText))
|
.foregroundColor(Color(UIColor.placeholderText))
|
||||||
.padding(.horizontal, 4)
|
.padding(.horizontal, 4)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
TextEditor(text: $post.body)
|
PostTitleTextView(
|
||||||
.font(.custom(appearance.rawValue, size: 17, relativeTo: .body))
|
text: $post.title,
|
||||||
.lineSpacing(
|
textStyle: $titleTextStyle,
|
||||||
17 * (
|
height: $titleTextHeight,
|
||||||
horizontalSizeClass == .compact ? bodyLineSpacingMultiplier / 2 : bodyLineSpacingMultiplier
|
isFirstResponder: $titleIsFirstResponder
|
||||||
)
|
)
|
||||||
)
|
.frame(height: titleFieldHeight)
|
||||||
.onChange(of: post.body) { _ in
|
.onChange(of: post.title) { _ in
|
||||||
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
|
if post.status == PostStatus.published.rawValue && !updatingTitleFromServer {
|
||||||
post.status = PostStatus.edited.rawValue
|
post.status = PostStatus.edited.rawValue
|
||||||
}
|
|
||||||
if updatingBodyFromServer {
|
|
||||||
updatingBodyFromServer = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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: 17 * (
|
||||||
|
horizontalSizeClass == .compact ? bodyLineSpacingMultiplier / 2 : bodyLineSpacingMultiplier
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.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: {
|
.onAppear(perform: {
|
||||||
switch post.appearance {
|
switch post.appearance {
|
||||||
case "sans":
|
case "sans":
|
||||||
@ -63,6 +96,8 @@ struct PostTextEditingView: View {
|
|||||||
default:
|
default:
|
||||||
self.appearance = .serif
|
self.appearance = .serif
|
||||||
}
|
}
|
||||||
|
self.titleTextStyle = UIFont(name: appearance.rawValue, size: 26)!
|
||||||
|
self.bodyTextStyle = UIFont(name: appearance.rawValue, size: 17)!
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class Coordinator: NSObject, UITextViewDelegate, NSLayoutManagerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||||
if (text == "\n") {
|
if text == "\n" {
|
||||||
self.isFirstResponder.toggle()
|
self.isFirstResponder.toggle()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user