Refactor text-editing views out of PostEditorView [Mac]

This commit is contained in:
Angelo Stavrow 2020-10-23 16:01:37 -04:00
parent fea9160a15
commit a542afa405
No known key found for this signature in database
GPG Key ID: 1A49C7064E060EEE
5 changed files with 87 additions and 130 deletions

View File

@ -1,6 +1,12 @@
import Foundation import Foundation
import CoreData import CoreData
enum PostAppearance: String {
case sans = "OpenSans-Regular"
case mono = "Hack"
case serif = "Lora"
}
struct PostEditorModel { struct PostEditorModel {
let lastDraftObjectURLKey = "lastDraftObjectURLKey" let lastDraftObjectURLKey = "lastDraftObjectURLKey"
private(set) var lastDraft: WFAPost? private(set) var lastDraft: WFAPost?

View File

@ -91,6 +91,7 @@
17DFDE8A251D309400A25F31 /* Lora-Cyrillic-OFL.txt in Resources */ = {isa = PBXBuildFile; fileRef = 17DFDE85251D309400A25F31 /* Lora-Cyrillic-OFL.txt */; }; 17DFDE8A251D309400A25F31 /* Lora-Cyrillic-OFL.txt in Resources */ = {isa = PBXBuildFile; fileRef = 17DFDE85251D309400A25F31 /* Lora-Cyrillic-OFL.txt */; };
17DFDE8B251D309400A25F31 /* OpenSans-License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 17DFDE86251D309400A25F31 /* OpenSans-License.txt */; }; 17DFDE8B251D309400A25F31 /* OpenSans-License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 17DFDE86251D309400A25F31 /* OpenSans-License.txt */; };
17DFDE8C251D309400A25F31 /* OpenSans-License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 17DFDE86251D309400A25F31 /* OpenSans-License.txt */; }; 17DFDE8C251D309400A25F31 /* OpenSans-License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 17DFDE86251D309400A25F31 /* OpenSans-License.txt */; };
17E5DF8A2543610700DCDC9B /* PostTextEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E5DF892543610700DCDC9B /* PostTextEditingView.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -174,6 +175,7 @@
17DFDE84251D309400A25F31 /* Hack-License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Hack-License.txt"; sourceTree = "<group>"; }; 17DFDE84251D309400A25F31 /* Hack-License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Hack-License.txt"; sourceTree = "<group>"; };
17DFDE85251D309400A25F31 /* Lora-Cyrillic-OFL.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Lora-Cyrillic-OFL.txt"; sourceTree = "<group>"; }; 17DFDE85251D309400A25F31 /* Lora-Cyrillic-OFL.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Lora-Cyrillic-OFL.txt"; sourceTree = "<group>"; };
17DFDE86251D309400A25F31 /* OpenSans-License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "OpenSans-License.txt"; sourceTree = "<group>"; }; 17DFDE86251D309400A25F31 /* OpenSans-License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "OpenSans-License.txt"; sourceTree = "<group>"; };
17E5DF892543610700DCDC9B /* PostTextEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTextEditingView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -300,6 +302,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
17A67CAE251A5DD7002F163D /* PostEditorView.swift */, 17A67CAE251A5DD7002F163D /* PostEditorView.swift */,
17E5DF892543610700DCDC9B /* PostTextEditingView.swift */,
); );
path = PostEditor; path = PostEditor;
sourceTree = "<group>"; sourceTree = "<group>";
@ -733,6 +736,7 @@
17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */, 17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */,
17C42E662509237800072984 /* PostListFilteredView.swift in Sources */, 17C42E662509237800072984 /* PostListFilteredView.swift in Sources */,
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */, 17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */,
17E5DF8A2543610700DCDC9B /* PostTextEditingView.swift in Sources */,
17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */, 17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */,
1756AE7B24CB65DF00FD7257 /* PostListView.swift in Sources */, 1756AE7B24CB65DF00FD7257 /* PostListView.swift in Sources */,
1753F6AC24E431CC00309365 /* MacPreferencesView.swift in Sources */, 1753F6AC24E431CC00309365 /* MacPreferencesView.swift in Sources */,

View File

@ -1,11 +1,5 @@
import SwiftUI import SwiftUI
enum PostAppearance: String {
case sans = "OpenSans-Regular"
case mono = "Hack"
case serif = "Lora"
}
struct PostTextEditingView: View { struct PostTextEditingView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) var horizontalSizeClass
@ObservedObject var post: WFAPost @ObservedObject var post: WFAPost
@ -45,7 +39,11 @@ struct PostTextEditingView: View {
} }
TextEditor(text: $post.body) TextEditor(text: $post.body)
.font(.custom(appearance.rawValue, size: 17, relativeTo: .body)) .font(.custom(appearance.rawValue, size: 17, relativeTo: .body))
.lineSpacing(17 * (horizontalSizeClass == .compact ? 0.25 : bodyLineSpacingMultiplier)) .lineSpacing(
17 * (
horizontalSizeClass == .compact ? bodyLineSpacingMultiplier / 2 : bodyLineSpacingMultiplier
)
)
.onChange(of: post.body) { _ in .onChange(of: post.body) { _ in
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer { if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
post.status = PostStatus.edited.rawValue post.status = PostStatus.edited.rawValue

View File

@ -10,129 +10,12 @@ struct PostEditorView: View {
@State private var updatingBodyFromServer: Bool = false @State private var updatingBodyFromServer: Bool = false
var body: some View { var body: some View {
VStack { PostTextEditingView(
switch post.appearance { post: post,
case "sans": updatingTitleFromServer: $updatingTitleFromServer,
TextField("Title (optional)", text: $post.title) updatingBodyFromServer: $updatingBodyFromServer
.textFieldStyle(PlainTextFieldStyle()) )
.padding(.horizontal, 4)
.padding(.bottom)
.font(.custom("OpenSans-Regular", size: 26, relativeTo: Font.TextStyle.largeTitle))
.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...")
.foregroundColor(Color(NSColor.placeholderTextColor))
.padding(.horizontal, 4)
.padding(.vertical, 2)
.font(.custom("OpenSans-Regular", size: 17, relativeTo: Font.TextStyle.body))
}
TextEditor(text: $post.body)
.font(.custom("OpenSans-Regular", size: 17, relativeTo: Font.TextStyle.body))
.lineSpacing(bodyLineSpacing)
.opacity(post.body.count == 0 && !isHovering ? 0.0 : 1.0)
.onChange(of: post.body) { _ in
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingBodyFromServer {
updatingBodyFromServer = false
}
}
.onHover(perform: { hovering in
self.isHovering = hovering
})
}
.background(Color(NSColor.controlBackgroundColor))
case "wrap", "mono", "code":
TextField("Title (optional)", text: $post.title)
.textFieldStyle(PlainTextFieldStyle())
.padding(.horizontal, 4)
.padding(.bottom)
.font(.custom("Hack", size: 26, relativeTo: Font.TextStyle.largeTitle))
.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...")
.foregroundColor(Color(NSColor.placeholderTextColor))
.padding(.horizontal, 4)
.padding(.vertical, 2)
.font(.custom("Hack", size: 17, relativeTo: Font.TextStyle.body))
}
TextEditor(text: $post.body)
.font(.custom("Hack", size: 17, relativeTo: Font.TextStyle.body))
.lineSpacing(bodyLineSpacing)
.opacity(post.body.count == 0 && !isHovering ? 0.0 : 1.0)
.onChange(of: post.body) { _ in
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingBodyFromServer {
updatingBodyFromServer = false
}
}
.onHover(perform: { hovering in
self.isHovering = hovering
})
}
.background(Color(NSColor.controlBackgroundColor))
default:
TextField("Title (optional)", text: $post.title)
.textFieldStyle(PlainTextFieldStyle())
.padding(.horizontal, 4)
.padding(.bottom)
.font(.custom("Lora", size: 26, relativeTo: Font.TextStyle.largeTitle))
.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...")
.foregroundColor(Color(NSColor.placeholderTextColor))
.padding(.horizontal, 4)
.padding(.vertical, 2)
.font(.custom("Lora", size: 17, relativeTo: Font.TextStyle.body))
}
TextEditor(text: $post.body)
.font(.custom("Lora", size: 17, relativeTo: Font.TextStyle.body))
.lineSpacing(bodyLineSpacing)
.opacity(post.body.count == 0 && !isHovering ? 0.0 : 1.0)
.onChange(of: post.body) { _ in
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingBodyFromServer {
updatingBodyFromServer = false
}
}
.onHover(perform: { hovering in
self.isHovering = hovering
})
}
.background(Color(NSColor.controlBackgroundColor))
}
}
.padding() .padding()
.background(Color.white)
.toolbar { .toolbar {
ToolbarItem(placement: .status) { ToolbarItem(placement: .status) {
PostEditorStatusToolbarView(post: post) PostEditorStatusToolbarView(post: post)
@ -150,7 +33,7 @@ struct PostEditorView: View {
}, label: { }, label: {
Image(systemName: "paperplane") Image(systemName: "paperplane")
}) })
.disabled(post.status == PostStatus.published.rawValue || || post.body.count == 0) .disabled(post.status == PostStatus.published.rawValue || post.body.count == 0)
} }
} }
.onChange(of: post.hasNewerRemoteCopy, perform: { _ in .onChange(of: post.hasNewerRemoteCopy, perform: { _ in

View File

@ -0,0 +1,66 @@
import SwiftUI
struct PostTextEditingView: View {
@ObservedObject var post: WFAPost
@Binding var updatingTitleFromServer: Bool
@Binding var updatingBodyFromServer: Bool
@State private var isHovering: Bool = false
@State private var appearance: PostAppearance = .serif
private let bodyLineSpacingMultiplier: CGFloat = 0.5
var body: some View {
VStack {
TextField("Title (optional)", text: $post.title)
.textFieldStyle(PlainTextFieldStyle())
.padding(.horizontal, 4)
.font(.custom(appearance.rawValue, size: 26, relativeTo: .largeTitle))
.onChange(of: post.title) { _ in
if post.status == PostStatus.published.rawValue && !updatingTitleFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingTitleFromServer {
updatingTitleFromServer = false
}
}
.padding(4)
.background(Color(NSColor.controlBackgroundColor))
.padding(.bottom)
ZStack(alignment: .topLeading) {
if post.body.count == 0 {
Text("Write…")
.foregroundColor(Color(NSColor.placeholderTextColor))
.padding(.horizontal, 4)
.padding(.vertical, 2)
.font(.custom(appearance.rawValue, size: 17, relativeTo: .body))
}
TextEditor(text: $post.body)
.font(.custom(appearance.rawValue, size: 17, relativeTo: .body))
.lineSpacing(17 * bodyLineSpacingMultiplier)
.opacity(post.body.count == 0 && !isHovering ? 0.0 : 1.0)
.onChange(of: post.body) { _ in
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
post.status = PostStatus.edited.rawValue
}
if updatingBodyFromServer {
updatingBodyFromServer = false
}
}
.onHover(perform: { hovering in
self.isHovering = hovering
})
}
.padding(4)
.background(Color(NSColor.controlBackgroundColor))
}
.onAppear(perform: {
switch post.appearance {
case "sans":
self.appearance = .sans
case "wrap", "mono", "code":
self.appearance = .mono
default:
self.appearance = .serif
}
})
}
}