mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Handle undo of edited posts (#251)
This commit is contained in:
parent
ba3f44b287
commit
73d219d0ec
@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- [Mac] Added a context-menu item to delete local posts from the post list.
|
||||
- [Mac] Added methods to fetch device logs.
|
||||
- [iOS, Mac] Added a way to search for text across all posts.
|
||||
- [iOS, Mac] Added a way to refresh an edited post from the server copy.
|
||||
|
||||
### Changed
|
||||
|
||||
@ -25,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- [Mac] Updated the URL and minimum version of the WriteFreely Swift package.
|
||||
- [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.
|
||||
- [iOS, Mac] The app now reverts a post from edited to published status if you undo your changes.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -244,6 +244,7 @@ extension WriteFreelyModel {
|
||||
#if os(macOS)
|
||||
self.selectedPost = cachedPost
|
||||
#endif
|
||||
cachedPost.status = PostStatus.published.rawValue
|
||||
}
|
||||
} catch {
|
||||
self.currentError = AppError.genericError(error.localizedDescription)
|
||||
@ -280,7 +281,6 @@ extension WriteFreelyModel {
|
||||
cachedPost.postId = fetchedPost.postId
|
||||
cachedPost.rtl = fetchedPost.rtl ?? false
|
||||
cachedPost.slug = fetchedPost.slug
|
||||
cachedPost.status = PostStatus.published.rawValue
|
||||
cachedPost.title = fetchedPost.title ?? ""
|
||||
cachedPost.updatedDate = fetchedPost.updatedDate
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ struct PostEditorModel {
|
||||
@AppStorage(WFDefaults.selectedCollectionURL, store: UserDefaults.shared) var selectedCollectionURL: URL?
|
||||
@AppStorage(WFDefaults.lastDraftURL, store: UserDefaults.shared) var lastDraftURL: URL?
|
||||
|
||||
private(set) var initialPostTitle: String?
|
||||
private(set) var initialPostBody: String?
|
||||
|
||||
#if os(macOS)
|
||||
var postToUpdate: WFAPost?
|
||||
#endif
|
||||
@ -58,6 +61,21 @@ struct PostEditorModel {
|
||||
return collection
|
||||
}
|
||||
|
||||
/// Sets the initial values for title and body on a published post.
|
||||
///
|
||||
/// Used to detect if the title and body have changed back to their initial values. If the passed `WFAPost` isn't
|
||||
/// published, any title and post values already stored are reset to `nil`.
|
||||
/// - Parameter post: The `WFAPost` for which we're setting initial title/body values.
|
||||
mutating func setInitialValues(for post: WFAPost) {
|
||||
if post.status != PostStatus.published.rawValue {
|
||||
initialPostTitle = nil
|
||||
initialPostBody = nil
|
||||
return
|
||||
}
|
||||
initialPostTitle = post.title
|
||||
initialPostBody = post.body
|
||||
}
|
||||
|
||||
private func fetchManagedObject(from objectURL: URL) -> NSManagedObject? {
|
||||
let coordinator = LocalStorageManager.standard.container.persistentStoreCoordinator
|
||||
guard let managedObjectID = coordinator.managedObjectID(forURIRepresentation: objectURL) else { return nil }
|
||||
|
@ -1063,7 +1063,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 701;
|
||||
CURRENT_PROJECT_VERSION = 702;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
||||
@ -1094,7 +1094,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_ENTITLEMENTS = "ActionExtension-iOS/ActionExtension-iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 701;
|
||||
CURRENT_PROJECT_VERSION = 702;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "ActionExtension-iOS/Info.plist";
|
||||
@ -1237,7 +1237,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 701;
|
||||
CURRENT_PROJECT_VERSION = 702;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = iOS/Info.plist;
|
||||
@ -1263,7 +1263,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "WriteFreely-MultiPlatform (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 701;
|
||||
CURRENT_PROJECT_VERSION = 702;
|
||||
DEVELOPMENT_TEAM = TPPAB4YBA6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = iOS/Info.plist;
|
||||
|
@ -84,7 +84,7 @@ struct PostEditorView: View {
|
||||
})
|
||||
.accessibilityHint(Text("Choose the blog you want to publish this post to"))
|
||||
.disabled(post.body.count == 0)
|
||||
} else {
|
||||
} else if post.status == PostStatus.edited.rawValue {
|
||||
Button(action: {
|
||||
if model.account.isLoggedIn {
|
||||
publishPost()
|
||||
@ -95,6 +95,14 @@ struct PostEditorView: View {
|
||||
Label("Publish", systemImage: "paperplane")
|
||||
})
|
||||
.disabled(post.status == PostStatus.published.rawValue || post.body.count == 0)
|
||||
|
||||
Button(action: {
|
||||
model.updateFromServer(post: post)
|
||||
}, label: {
|
||||
Label("Revert", systemImage: "clock.arrow.circlepath")
|
||||
})
|
||||
.accessibilityHint(Text("Replace the edited post with the published version from the server"))
|
||||
.disabled(post.status != PostStatus.edited.rawValue)
|
||||
}
|
||||
Button(action: {
|
||||
sharePost()
|
||||
@ -160,6 +168,7 @@ struct PostEditorView: View {
|
||||
})
|
||||
.onAppear(perform: {
|
||||
self.selectedCollection = collections.first { $0.alias == post.collectionAlias }
|
||||
model.editor.setInitialValues(for: post)
|
||||
if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
self.model.editor.saveLastDraft(post)
|
||||
@ -201,9 +210,8 @@ struct PostEditorView: View {
|
||||
LocalStorageManager.standard.saveContext()
|
||||
model.publish(post: post)
|
||||
}
|
||||
#if os(iOS)
|
||||
model.editor.setInitialValues(for: post)
|
||||
self.hideKeyboard()
|
||||
#endif
|
||||
}
|
||||
|
||||
private func sharePost() {
|
||||
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||
|
||||
struct PostTextEditingView: View {
|
||||
@Environment(\.horizontalSizeClass) var horizontalSizeClass
|
||||
@EnvironmentObject var model: WriteFreelyModel
|
||||
@ObservedObject var post: WFAPost
|
||||
@Binding var updatingTitleFromServer: Bool
|
||||
@Binding var updatingBodyFromServer: Bool
|
||||
@ -35,13 +36,16 @@ struct PostTextEditingView: View {
|
||||
)
|
||||
.accessibilityLabel(Text("Title (optional)"))
|
||||
.accessibilityHint(Text("Add or edit the title for your post; use the Return key to skip to the body"))
|
||||
.onChange(of: post.title) { _ in
|
||||
.onChange(of: post.title) { value in
|
||||
if post.status == PostStatus.published.rawValue && !updatingTitleFromServer {
|
||||
post.status = PostStatus.edited.rawValue
|
||||
}
|
||||
if updatingTitleFromServer {
|
||||
updatingTitleFromServer = false
|
||||
}
|
||||
if post.status == PostStatus.edited.rawValue && value == model.editor.initialPostTitle {
|
||||
post.status = PostStatus.published.rawValue
|
||||
}
|
||||
}
|
||||
MultilineTextField(
|
||||
"Write...",
|
||||
@ -51,13 +55,16 @@ struct PostTextEditingView: View {
|
||||
)
|
||||
.accessibilityLabel(Text("Body"))
|
||||
.accessibilityHint(Text("Add or edit the body of your post"))
|
||||
.onChange(of: post.body) { _ in
|
||||
.onChange(of: post.body) { value in
|
||||
if post.status == PostStatus.published.rawValue && !updatingBodyFromServer {
|
||||
post.status = PostStatus.edited.rawValue
|
||||
}
|
||||
if updatingBodyFromServer {
|
||||
updatingBodyFromServer = false
|
||||
}
|
||||
if post.status == PostStatus.edited.rawValue && value == model.editor.initialPostBody {
|
||||
post.status = PostStatus.published.rawValue
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: titleIsFirstResponder, perform: { value in
|
||||
|
@ -31,6 +31,17 @@ struct ActivePostToolbarView: View {
|
||||
.frame(minWidth: 50, alignment: .center)
|
||||
.layoutPriority(1)
|
||||
.padding(.horizontal)
|
||||
if activePost.status == PostStatus.edited.rawValue {
|
||||
Button(action: {
|
||||
model.editor.postToUpdate = activePost
|
||||
model.updateFromServer(post: activePost)
|
||||
model.selectedPost = nil
|
||||
}, label: {
|
||||
Image(systemName: "clock.arrow.circlepath")
|
||||
.accessibilityLabel(Text("Revert post"))
|
||||
.accessibilityHint(Text("Replace the edited post with the published version from the server"))
|
||||
})
|
||||
}
|
||||
if activePost.status == PostStatus.local.rawValue {
|
||||
Menu(content: {
|
||||
Label("Publish To:", systemImage: "paperplane")
|
||||
@ -131,6 +142,7 @@ struct ActivePostToolbarView: View {
|
||||
LocalStorageManager.standard.saveContext()
|
||||
model.publish(post: post)
|
||||
}
|
||||
model.editor.setInitialValues(for: post)
|
||||
}
|
||||
|
||||
private func openSettingsWindow() {
|
||||
|
@ -16,6 +16,7 @@ struct PostEditorView: View {
|
||||
.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)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct PostTextEditingView: View {
|
||||
@EnvironmentObject var model: WriteFreelyModel
|
||||
@ObservedObject var post: WFAPost
|
||||
@Binding var updatingFromServer: Bool
|
||||
@State private var appearance: PostAppearance = .serif
|
||||
@ -74,9 +75,16 @@ struct PostTextEditingView: View {
|
||||
private func onTextChange(_ text: String) {
|
||||
extractTitle(text)
|
||||
|
||||
if post.status == PostStatus.published.rawValue && !updatingFromServer {
|
||||
if !updatingFromServer {
|
||||
if post.status == PostStatus.published.rawValue {
|
||||
post.status = PostStatus.edited.rawValue
|
||||
}
|
||||
if post.status == PostStatus.edited.rawValue,
|
||||
post.title == model.editor.initialPostTitle,
|
||||
post.body == model.editor.initialPostBody {
|
||||
post.status = PostStatus.published.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
if updatingFromServer {
|
||||
self.updatingFromServer = false
|
||||
|
Loading…
Reference in New Issue
Block a user