mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Improve offline experience (#255)
This commit is contained in:
parent
5efdde96cc
commit
3f424b399a
@ -17,6 +17,14 @@ final class WriteFreelyModel: ObservableObject {
|
||||
@Published var hasError: Bool = false
|
||||
var currentError: Error? {
|
||||
didSet {
|
||||
if let localizedErrorDescription = currentError?.localizedDescription,
|
||||
localizedErrorDescription == "The operation couldn’t be completed. (WriteFreely.WFError error -2.)",
|
||||
!hasNetworkConnection {
|
||||
#if DEBUG
|
||||
print("⚠️ currentError is WriteFreely.WFError -2 and there is no network connection.")
|
||||
#endif
|
||||
currentError = NetworkError.noConnectionError
|
||||
}
|
||||
#if DEBUG
|
||||
print("⚠️ currentError -> didSet \(currentError?.localizedDescription ?? "nil")")
|
||||
print(" > hasError was: \(self.hasError)")
|
||||
@ -66,6 +74,10 @@ final class WriteFreelyModel: ObservableObject {
|
||||
self.preferences.appearance = self.defaults.integer(forKey: WFDefaults.colorSchemeIntegerKey)
|
||||
self.preferences.font = self.defaults.integer(forKey: WFDefaults.defaultFontIntegerKey)
|
||||
self.account.restoreState()
|
||||
|
||||
// Set the appearance
|
||||
self.preferences.updateAppearance(to: Appearance(rawValue: self.preferences.appearance) ?? .system)
|
||||
|
||||
if self.account.isLoggedIn {
|
||||
guard let serverURL = URL(string: self.account.server) else {
|
||||
self.currentError = AccountError.invalidServerURL
|
||||
|
@ -59,14 +59,7 @@ struct ContentView: View {
|
||||
.withErrorHandling()
|
||||
#endif
|
||||
|
||||
#if os(macOS)
|
||||
Text("Select a post, or create a new local draft.")
|
||||
.foregroundColor(.secondary)
|
||||
.frame(width: 500, height: 500)
|
||||
#else
|
||||
Text("Select a post, or create a new local draft.")
|
||||
.foregroundColor(.secondary)
|
||||
#endif
|
||||
NoSelectedPostView(isConnected: $model.hasNetworkConnection)
|
||||
}
|
||||
.environmentObject(model)
|
||||
.onChange(of: model.hasError) { value in
|
||||
|
29
Shared/Navigation/NoSelectedPostView.swift
Normal file
29
Shared/Navigation/NoSelectedPostView.swift
Normal file
@ -0,0 +1,29 @@
|
||||
import SwiftUI
|
||||
|
||||
struct NoSelectedPostView: View {
|
||||
@Binding var isConnected: Bool
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 8) {
|
||||
Text("Select a post, or create a new local draft.")
|
||||
if !isConnected {
|
||||
Label("You are not connected to the internet", systemImage: "wifi.exclamationmark")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
.frame(width: 500, height: 500)
|
||||
}
|
||||
}
|
||||
|
||||
struct NoSelectedPostViewIsDisconnected_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NoSelectedPostView(isConnected: Binding.constant(true))
|
||||
}
|
||||
}
|
||||
|
||||
struct NoSelectedPostViewIsConnected_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NoSelectedPostView(isConnected: Binding.constant(false))
|
||||
}
|
||||
}
|
@ -97,19 +97,26 @@ struct PostListView: View {
|
||||
.padding(.vertical, 4)
|
||||
.padding(.horizontal, 8)
|
||||
} else {
|
||||
Button(action: {
|
||||
DispatchQueue.main.async {
|
||||
model.fetchUserCollections()
|
||||
model.fetchUserPosts()
|
||||
}
|
||||
}, label: {
|
||||
Image(systemName: "arrow.clockwise")
|
||||
if model.hasNetworkConnection {
|
||||
Button(action: {
|
||||
DispatchQueue.main.async {
|
||||
model.fetchUserCollections()
|
||||
model.fetchUserPosts()
|
||||
}
|
||||
}, label: {
|
||||
Image(systemName: "arrow.clockwise")
|
||||
.padding(.vertical, 4)
|
||||
.padding(.horizontal, 8)
|
||||
})
|
||||
.accessibilityLabel(Text("Refresh Posts"))
|
||||
.accessibilityHint(Text("Fetch changes from the server"))
|
||||
.disabled(!model.account.isLoggedIn)
|
||||
} else {
|
||||
Image(systemName: "wifi.exclamationmark")
|
||||
.padding(.vertical, 4)
|
||||
.padding(.horizontal, 8)
|
||||
})
|
||||
.accessibilityLabel(Text("Refresh Posts"))
|
||||
.accessibilityHint(Text("Fetch changes from the server"))
|
||||
.disabled(!model.account.isLoggedIn)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, 8)
|
||||
|
@ -1,67 +1,54 @@
|
||||
import SwiftUI
|
||||
|
||||
enum Appearance: Int {
|
||||
case system = 0
|
||||
case light = 1
|
||||
case dark = 2
|
||||
}
|
||||
|
||||
class PreferencesModel: ObservableObject {
|
||||
private let defaults = UserDefaults.shared
|
||||
|
||||
/* We're stuck dropping into AppKit/UIKit to set light/dark schemes for now,
|
||||
* because setting the .preferredColorScheme modifier on views in SwiftUI is
|
||||
* currently unreliable.
|
||||
*
|
||||
* Feedback submitted to Apple:
|
||||
*
|
||||
* FB8382883: "On macOS 11β4, preferredColorScheme modifier does not respect .light ColorScheme"
|
||||
* FB8383053: "On iOS 14β4/macOS 11β4, it is not possible to unset preferredColorScheme after setting
|
||||
* it to either .light or .dark"
|
||||
*/
|
||||
|
||||
#if os(iOS)
|
||||
@available(iOSApplicationExtension, unavailable)
|
||||
var window: UIWindow? {
|
||||
guard let scene = UIApplication.shared.connectedScenes.first,
|
||||
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
|
||||
let window = windowSceneDelegate.window else {
|
||||
return nil
|
||||
}
|
||||
return window
|
||||
}
|
||||
#endif
|
||||
|
||||
@available(iOSApplicationExtension, unavailable)
|
||||
@Published var selectedColorScheme: ColorScheme?
|
||||
|
||||
@available(iOSApplicationExtension, unavailable)
|
||||
@Published var appearance: Int = 0 {
|
||||
didSet {
|
||||
switch appearance {
|
||||
case 1:
|
||||
// selectedColorScheme = .light
|
||||
#if os(macOS)
|
||||
NSApp.appearance = NSAppearance(named: .aqua)
|
||||
#else
|
||||
window?.overrideUserInterfaceStyle = .light
|
||||
#endif
|
||||
case 2:
|
||||
// selectedColorScheme = .dark
|
||||
#if os(macOS)
|
||||
NSApp.appearance = NSAppearance(named: .darkAqua)
|
||||
#else
|
||||
window?.overrideUserInterfaceStyle = .dark
|
||||
#endif
|
||||
default:
|
||||
// selectedColorScheme = .none
|
||||
#if os(macOS)
|
||||
NSApp.appearance = nil
|
||||
#else
|
||||
window?.overrideUserInterfaceStyle = .unspecified
|
||||
#endif
|
||||
}
|
||||
|
||||
defaults.set(appearance, forKey: WFDefaults.colorSchemeIntegerKey)
|
||||
}
|
||||
}
|
||||
@Published var appearance: Int = 0
|
||||
@Published var font: Int = 0 {
|
||||
didSet {
|
||||
defaults.set(font, forKey: WFDefaults.defaultFontIntegerKey)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOSApplicationExtension, unavailable)
|
||||
func updateAppearance(to appearance: Appearance) {
|
||||
#if os(iOS)
|
||||
var window: UIWindow? {
|
||||
guard let scene = UIApplication.shared.connectedScenes.first,
|
||||
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
|
||||
let window = windowSceneDelegate.window else {
|
||||
return nil
|
||||
}
|
||||
return window
|
||||
}
|
||||
#endif
|
||||
|
||||
switch appearance {
|
||||
case .light:
|
||||
#if os(macOS)
|
||||
NSApp.appearance = NSAppearance(named: .aqua)
|
||||
#else
|
||||
window?.overrideUserInterfaceStyle = .light
|
||||
#endif
|
||||
case .dark:
|
||||
#if os(macOS)
|
||||
NSApp.appearance = NSAppearance(named: .darkAqua)
|
||||
#else
|
||||
window?.overrideUserInterfaceStyle = .dark
|
||||
#endif
|
||||
default:
|
||||
#if os(macOS)
|
||||
NSApp.appearance = nil
|
||||
#else
|
||||
window?.overrideUserInterfaceStyle = .unspecified
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,28 @@ import SwiftUI
|
||||
struct PreferencesView: View {
|
||||
@ObservedObject var preferences: PreferencesModel
|
||||
|
||||
/* We're stuck dropping into AppKit/UIKit to set light/dark schemes for now,
|
||||
* because setting the .preferredColorScheme modifier on views in SwiftUI is
|
||||
* currently unreliable.
|
||||
*
|
||||
* Feedback submitted to Apple:
|
||||
*
|
||||
* FB8382883: "On macOS 11β4, preferredColorScheme modifier does not respect .light ColorScheme"
|
||||
* FB8383053: "On iOS 14β4/macOS 11β4, it is not possible to unset preferredColorScheme after setting
|
||||
* it to either .light or .dark"
|
||||
*/
|
||||
|
||||
#if os(iOS)
|
||||
var window: UIWindow? {
|
||||
guard let scene = UIApplication.shared.connectedScenes.first,
|
||||
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
|
||||
let window = windowSceneDelegate.window else {
|
||||
return nil
|
||||
}
|
||||
return window
|
||||
}
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
VStack {
|
||||
@ -46,6 +68,10 @@ struct PreferencesView: View {
|
||||
}
|
||||
.padding(.bottom)
|
||||
}
|
||||
.onChange(of: preferences.appearance) { value in
|
||||
preferences.updateAppearance(to: Appearance(rawValue: value) ?? .system)
|
||||
UserDefaults.shared.set(value, forKey: WFDefaults.colorSchemeIntegerKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,8 @@
|
||||
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 */; };
|
||||
17E5DF8A2543610700DCDC9B /* PostTextEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E5DF892543610700DCDC9B /* PostTextEditingView.swift */; };
|
||||
37095AE02AA4A0E700C9C5F8 /* NoSelectedPostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37113EF82A98C10A00B36B98 /* NoSelectedPostView.swift */; };
|
||||
37113EF92A98C10A00B36B98 /* NoSelectedPostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37113EF82A98C10A00B36B98 /* NoSelectedPostView.swift */; };
|
||||
375A67E828FC555C007A1AC0 /* MultilineTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 375A67E728FC555C007A1AC0 /* MultilineTextView.swift */; };
|
||||
3779389729EC0C880032D6C1 /* HelpCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3779389629EC0C880032D6C1 /* HelpCommands.swift */; };
|
||||
37F749D129B4D3090087F0BF /* SearchablePostListFilteredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F749D029B4D3090087F0BF /* SearchablePostListFilteredView.swift */; };
|
||||
@ -270,6 +272,7 @@
|
||||
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>"; };
|
||||
17E5DF892543610700DCDC9B /* PostTextEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTextEditingView.swift; sourceTree = "<group>"; };
|
||||
37113EF82A98C10A00B36B98 /* NoSelectedPostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoSelectedPostView.swift; sourceTree = "<group>"; };
|
||||
375A67E728FC555C007A1AC0 /* MultilineTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineTextView.swift; sourceTree = "<group>"; };
|
||||
3779389629EC0C880032D6C1 /* HelpCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCommands.swift; sourceTree = "<group>"; };
|
||||
37F749D029B4D3090087F0BF /* SearchablePostListFilteredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchablePostListFilteredView.swift; sourceTree = "<group>"; };
|
||||
@ -586,6 +589,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
17DF328224C87D3300BCE2E3 /* ContentView.swift */,
|
||||
37113EF82A98C10A00B36B98 /* NoSelectedPostView.swift */,
|
||||
);
|
||||
path = Navigation;
|
||||
sourceTree = "<group>";
|
||||
@ -922,6 +926,7 @@
|
||||
173E19D1254318F600440F0F /* RemoteChangePromptView.swift in Sources */,
|
||||
17B37C5625C8679800FE75E9 /* WriteFreelyModel+API.swift in Sources */,
|
||||
17C42E622507D8E600072984 /* PostStatus.swift in Sources */,
|
||||
37095AE02AA4A0E700C9C5F8 /* NoSelectedPostView.swift in Sources */,
|
||||
1756DBBA24FED45500207AB8 /* LocalStorageManager.swift in Sources */,
|
||||
1727526A2809991A003D0A6A /* ErrorHandling.swift in Sources */,
|
||||
1756AE8124CB844500FD7257 /* View+Keyboard.swift in Sources */,
|
||||
@ -975,6 +980,7 @@
|
||||
17120DAA24E1B2F5002B9F6C /* AccountLogoutView.swift in Sources */,
|
||||
17DF32D624C8CA3400BCE2E3 /* PostStatusBadgeView.swift in Sources */,
|
||||
172C492E2593981900E20ADF /* MacUpdatesView.swift in Sources */,
|
||||
37113EF92A98C10A00B36B98 /* NoSelectedPostView.swift in Sources */,
|
||||
1727526728099802003D0A6A /* ErrorConstants.swift in Sources */,
|
||||
17479F152583D8E40072B7FB /* PostEditorSharingPicker.swift in Sources */,
|
||||
17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */,
|
||||
@ -1060,7 +1066,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 704;
|
||||
CURRENT_PROJECT_VERSION = 706;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
||||
@ -1072,7 +1078,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.16;
|
||||
MARKETING_VERSION = 1.0.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform.ActionExtension-iOS";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
@ -1091,7 +1097,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 704;
|
||||
CURRENT_PROJECT_VERSION = 706;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
||||
@ -1103,7 +1109,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.16;
|
||||
MARKETING_VERSION = 1.0.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform.ActionExtension-iOS";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
@ -1234,7 +1240,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 704;
|
||||
CURRENT_PROJECT_VERSION = 706;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = iOS/Info.plist;
|
||||
@ -1243,7 +1249,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.16;
|
||||
MARKETING_VERSION = 1.0.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform";
|
||||
PRODUCT_NAME = "WriteFreely-MultiPlatform";
|
||||
SDKROOT = iphoneos;
|
||||
@ -1260,7 +1266,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 704;
|
||||
CURRENT_PROJECT_VERSION = 706;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = iOS/Info.plist;
|
||||
@ -1269,7 +1275,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.16;
|
||||
MARKETING_VERSION = 1.0.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.abunchtell.WriteFreely-MultiPlatform";
|
||||
PRODUCT_NAME = "WriteFreely-MultiPlatform";
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -50,7 +50,10 @@ struct PostEditorView: View {
|
||||
PostEditorStatusToolbarView(post: post)
|
||||
}
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
if model.isProcessingRequest {
|
||||
if !model.hasNetworkConnection {
|
||||
Image(systemName: "wifi.exclamationmark")
|
||||
.foregroundColor(.secondary)
|
||||
} else if model.isProcessingRequest {
|
||||
ProgressView()
|
||||
} else {
|
||||
Menu(content: {
|
||||
|
@ -115,6 +115,7 @@ final class CustomTextView: NSView {
|
||||
let scrollView = NSScrollView()
|
||||
scrollView.drawsBackground = false
|
||||
scrollView.borderType = .noBorder
|
||||
scrollView.autohidesScrollers = true
|
||||
scrollView.hasVerticalScroller = true
|
||||
scrollView.hasHorizontalRuler = false
|
||||
scrollView.autoresizingMask = [.width, .height]
|
||||
@ -167,6 +168,8 @@ final class CustomTextView: NSView {
|
||||
.font: font ?? NSFont.systemFont(ofSize: 17), // Fall back to system font if we can't unwrap font argument
|
||||
.foregroundColor: NSColor.labelColor
|
||||
]
|
||||
textView.textContainer?.lineFragmentPadding = 16
|
||||
textView.textContainerInset = NSSize(width: 0, height: 16)
|
||||
|
||||
return textView
|
||||
}()
|
||||
|
@ -9,65 +9,72 @@ struct PostEditorView: View {
|
||||
@State private var updatingFromServer: Bool = false
|
||||
|
||||
var body: some View {
|
||||
PostTextEditingView(
|
||||
post: post,
|
||||
updatingFromServer: $updatingFromServer
|
||||
)
|
||||
.padding()
|
||||
.background(Color(NSColor.controlBackgroundColor))
|
||||
.onAppear(perform: {
|
||||
model.editor.setInitialValues(for: post)
|
||||
if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
self.model.editor.saveLastDraft(post)
|
||||
}
|
||||
} else {
|
||||
self.model.editor.clearLastDraft()
|
||||
VStack {
|
||||
if !model.hasNetworkConnection {
|
||||
Label("You are not connected to the internet", systemImage: "wifi.exclamationmark")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
})
|
||||
.onChange(of: post.hasNewerRemoteCopy, perform: { _ in
|
||||
if !post.hasNewerRemoteCopy {
|
||||
self.updatingFromServer = true
|
||||
}
|
||||
})
|
||||
.onChange(of: post.status, perform: { value in
|
||||
if value != PostStatus.published.rawValue {
|
||||
self.model.editor.saveLastDraft(post)
|
||||
} else {
|
||||
self.model.editor.clearLastDraft()
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager.standard.saveContext()
|
||||
}
|
||||
})
|
||||
.onChange(of: model.hasError) { value in
|
||||
if value {
|
||||
if let error = model.currentError {
|
||||
self.errorHandling.handle(error: error)
|
||||
PostTextEditingView(
|
||||
post: post,
|
||||
updatingFromServer: $updatingFromServer
|
||||
)
|
||||
.background(Color(NSColor.controlBackgroundColor))
|
||||
.onAppear(perform: {
|
||||
model.editor.setInitialValues(for: post)
|
||||
if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
self.model.editor.saveLastDraft(post)
|
||||
}
|
||||
} else {
|
||||
self.errorHandling.handle(error: AppError.genericError())
|
||||
self.model.editor.clearLastDraft()
|
||||
}
|
||||
model.hasError = false
|
||||
}
|
||||
}
|
||||
.onDisappear(perform: {
|
||||
DispatchQueue.main.async {
|
||||
model.editor.clearLastDraft()
|
||||
}
|
||||
if post.title.count == 0
|
||||
&& post.body.count == 0
|
||||
&& post.status == PostStatus.local.rawValue
|
||||
&& post.updatedDate == nil
|
||||
&& post.postId == nil {
|
||||
DispatchQueue.main.async {
|
||||
model.posts.remove(post)
|
||||
})
|
||||
.onChange(of: post.hasNewerRemoteCopy, perform: { _ in
|
||||
if !post.hasNewerRemoteCopy {
|
||||
self.updatingFromServer = true
|
||||
}
|
||||
})
|
||||
.onChange(of: post.status, perform: { value in
|
||||
if value != PostStatus.published.rawValue {
|
||||
self.model.editor.saveLastDraft(post)
|
||||
} else {
|
||||
self.model.editor.clearLastDraft()
|
||||
}
|
||||
} else if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager.standard.saveContext()
|
||||
}
|
||||
})
|
||||
.onChange(of: model.hasError) { value in
|
||||
if value {
|
||||
if let error = model.currentError {
|
||||
self.errorHandling.handle(error: error)
|
||||
} else {
|
||||
self.errorHandling.handle(error: AppError.genericError())
|
||||
}
|
||||
model.hasError = false
|
||||
}
|
||||
}
|
||||
})
|
||||
.onDisappear(perform: {
|
||||
DispatchQueue.main.async {
|
||||
model.editor.clearLastDraft()
|
||||
}
|
||||
if post.title.count == 0
|
||||
&& post.body.count == 0
|
||||
&& post.status == PostStatus.local.rawValue
|
||||
&& post.updatedDate == nil
|
||||
&& post.postId == nil {
|
||||
DispatchQueue.main.async {
|
||||
model.posts.remove(post)
|
||||
}
|
||||
} else if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager.standard.saveContext()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,8 @@ struct PostTextEditingView: View {
|
||||
if combinedText.count == 0 {
|
||||
Text("Write…")
|
||||
.foregroundColor(Color(NSColor.placeholderTextColor))
|
||||
.padding(.horizontal, 5)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 16)
|
||||
.font(.custom(appearance.rawValue, size: 17, relativeTo: .body))
|
||||
}
|
||||
if post.appearance == "sans" {
|
||||
|
Loading…
Reference in New Issue
Block a user