ソースを参照

Merge pull request #47 from writeas/set-collection-for-post

Set collection for post
pull/42/head
Angelo Stavrow 3年前
committed by GitHub
コミット
888de9e6a3
この署名に対応する既知のキーがデータベースに存在しません GPGキーID: 4AEE18F83AFDEB23
10個のファイルの変更71行の追加32行の削除
  1. +17
    -0
      Shared/Extensions/NSManagedObjectContext+ExecuteAndMergeChanges.swift
  2. +1
    -3
      Shared/LocalStorageManager.swift
  3. +15
    -3
      Shared/Models/WriteFreelyModel.swift
  4. +12
    -0
      Shared/Navigation/ContentView.swift
  5. +9
    -2
      Shared/PostEditor/PostEditorView.swift
  6. +1
    -3
      Shared/PostList/PostListModel.swift
  7. +5
    -14
      Shared/PostList/PostListView.swift
  8. +6
    -0
      WriteFreely-MultiPlatform.xcodeproj/project.pbxproj
  9. +3
    -3
      iOS/Settings/SettingsHeaderView.swift
  10. +2
    -4
      iOS/Settings/SettingsView.swift

+ 17
- 0
Shared/Extensions/NSManagedObjectContext+ExecuteAndMergeChanges.swift ファイルの表示

@@ -0,0 +1,17 @@
import CoreData

extension NSManagedObjectContext {
/// Executes the given `NSBatchDeleteRequest` and directly merges the changes to bring the given
/// managed object context up to date.
///
/// Credit: https://www.avanderlee.com/swift/nsbatchdeleterequest-core-data/
///
/// - Parameter batchDeleteRequest: The `NSBatchDeleteRequest` to execute.
/// - Throws: An error if anything went wrong executing the batch deletion.
public func executeAndMergeChanges(using batchDeleteRequest: NSBatchDeleteRequest) throws {
batchDeleteRequest.resultType = .resultTypeObjectIDs
let result = try execute(batchDeleteRequest) as? NSBatchDeleteResult
let changes: [AnyHashable: Any] = [NSDeletedObjectsKey: result?.result as? [NSManagedObjectID] ?? []]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [self])
}
}

+ 1
- 3
Shared/LocalStorageManager.swift ファイルの表示

@@ -50,9 +50,7 @@ class LocalStorageManager {
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

do {
try LocalStorageManager.persistentContainer.persistentStoreCoordinator.execute(
deleteRequest, with: LocalStorageManager.persistentContainer.viewContext
)
try LocalStorageManager.persistentContainer.viewContext.executeAndMergeChanges(using: deleteRequest)
} catch {
print("Error: Failed to purge cached collections.")
}


+ 15
- 3
Shared/Models/WriteFreelyModel.swift ファイルの表示

@@ -11,6 +11,10 @@ class WriteFreelyModel: ObservableObject {
@Published var isLoggingIn: Bool = false
@Published var selectedPost: WFAPost?

#if os(iOS)
@Published var isPresentingSettingsView: Bool = false
#endif

private var client: WFClient?
private let defaults = UserDefaults.standard

@@ -112,7 +116,12 @@ extension WriteFreelyModel {
DispatchQueue.main.async {
self.selectedPost = post
}
loggedInClient.getPost(byId: postId, completion: updateFromServerHandler)
if let postCollectionAlias = post.collectionAlias,
let postSlug = post.slug {
loggedInClient.getPost(bySlug: postSlug, from: postCollectionAlias, completion: updateFromServerHandler)
} else {
loggedInClient.getPost(byId: postId, completion: updateFromServerHandler)
}
}
}

@@ -169,8 +178,8 @@ private extension WriteFreelyModel {
try purgeTokenFromKeychain(username: account.user?.username, server: account.server)
client = nil
DispatchQueue.main.async {
LocalStorageManager().purgeUserCollections()
self.account.logout()
LocalStorageManager().purgeUserCollections()
self.posts.purgeAllPosts()
}
} catch {
@@ -280,12 +289,15 @@ private extension WriteFreelyModel {
}

func updateFromServerHandler(result: Result<WFPost, Error>) {
// ⚠️ NOTE:
// The API does not return a collection alias, so we take care not to overwrite the
// cached post's collection alias with the 'nil' value from the fetched post.
// See: https://github.com/writeas/writefreely-swift/issues/20
do {
let fetchedPost = try result.get()
guard let cachedPost = self.selectedPost else { return }
cachedPost.appearance = fetchedPost.appearance
cachedPost.body = fetchedPost.body
cachedPost.collectionAlias = fetchedPost.collectionAlias
cachedPost.createdDate = fetchedPost.createdDate
cachedPost.language = fetchedPost.language
cachedPost.postId = fetchedPost.postId


+ 12
- 0
Shared/Navigation/ContentView.swift ファイルの表示

@@ -13,6 +13,18 @@ struct ContentView: View {
.foregroundColor(.secondary)
}
.environmentObject(model)

#if os(iOS)
EmptyView()
.sheet(
isPresented: $model.isPresentingSettingsView,
onDismiss: { model.isPresentingSettingsView = false },
content: {
SettingsView()
.environmentObject(model)
}
)
#endif
}
}



+ 9
- 2
Shared/PostEditor/PostEditorView.swift ファイルの表示

@@ -30,8 +30,7 @@ struct PostEditorView: View {
}
ToolbarItem(placement: .primaryAction) {
Button(action: {
model.publish(post: post)
post.status = PostStatus.published.rawValue
publishPost()
}, label: {
Image(systemName: "paperplane")
})
@@ -50,6 +49,14 @@ struct PostEditorView: View {
}
})
}

private func publishPost() {
DispatchQueue.main.async {
LocalStorageManager().saveContext()
model.posts.loadCachedPosts()
model.publish(post: post)
}
}
}

struct PostEditorView_Previews: PreviewProvider {


+ 1
- 3
Shared/PostList/PostListModel.swift ファイルの表示

@@ -28,9 +28,7 @@ class PostListModel: ObservableObject {
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

do {
try LocalStorageManager.persistentContainer.persistentStoreCoordinator.execute(
deleteRequest, with: LocalStorageManager.persistentContainer.viewContext
)
try LocalStorageManager.persistentContainer.viewContext.executeAndMergeChanges(using: deleteRequest)
} catch {
print("Error: Failed to purge cached posts.")
}


+ 5
- 14
Shared/PostList/PostListView.swift ファイルの表示

@@ -7,10 +7,6 @@ struct PostListView: View {
@State var selectedCollection: WFACollection?
@State var showAllPosts: Bool = false

#if os(iOS)
@State private var isPresentingSettings = false
#endif

var body: some View {
#if os(iOS)
GeometryReader { geometry in
@@ -31,18 +27,10 @@ struct PostListView: View {
ToolbarItem(placement: .bottomBar) {
HStack {
Button(action: {
isPresentingSettings = true
model.isPresentingSettingsView = true
}, label: {
Image(systemName: "gear")
}).sheet(
isPresented: $isPresentingSettings,
onDismiss: {
isPresentingSettings = false
},
content: {
SettingsView(isPresented: $isPresentingSettings)
}
)
})
.padding(.leading)
Spacer()
Text(pluralizedPostCount(for: showPosts(for: selectedCollection)))
@@ -117,6 +105,9 @@ struct PostListView: View {
managedPost.title = ""
managedPost.body = ""
managedPost.status = PostStatus.local.rawValue
if let selectedCollectionAlias = selectedCollection?.alias {
managedPost.collectionAlias = selectedCollectionAlias
}
DispatchQueue.main.async {
LocalStorageManager().saveContext()
}


+ 6
- 0
WriteFreely-MultiPlatform.xcodeproj/project.pbxproj ファイルの表示

@@ -54,6 +54,8 @@
17C42E632507D8E600072984 /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E612507D8E600072984 /* PostStatus.swift */; };
17C42E652509237800072984 /* PostListFilteredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E642509237800072984 /* PostListFilteredView.swift */; };
17C42E662509237800072984 /* PostListFilteredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E642509237800072984 /* PostListFilteredView.swift */; };
17C42E70250AA12300072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */; };
17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */; };
17D435E824E3128F0036B539 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
17D435E924E3128F0036B539 /* PreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D435E724E3128F0036B539 /* PreferencesModel.swift */; };
17DF329D24C87D3500BCE2E3 /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DF329C24C87D3500BCE2E3 /* Tests_iOS.swift */; };
@@ -114,6 +116,7 @@
17B996D72502D23E0017B536 /* WFAPost+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WFAPost+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; };
17C42E612507D8E600072984 /* PostStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostStatus.swift; sourceTree = "<group>"; };
17C42E642509237800072984 /* PostListFilteredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostListFilteredView.swift; sourceTree = "<group>"; };
17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+ExecuteAndMergeChanges.swift"; sourceTree = "<group>"; };
17D435E724E3128F0036B539 /* PreferencesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesModel.swift; sourceTree = "<group>"; };
17DF328124C87D3300BCE2E3 /* WriteFreely_MultiPlatformApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteFreely_MultiPlatformApp.swift; sourceTree = "<group>"; };
17DF328224C87D3300BCE2E3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@@ -193,6 +196,7 @@
isa = PBXGroup;
children = (
1756AE8024CB844500FD7257 /* View+Keyboard.swift */,
17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */,
);
path = Extensions;
sourceTree = "<group>";
@@ -591,6 +595,7 @@
17120DA324E19A42002B9F6C /* PreferencesView.swift in Sources */,
1756AE6E24CB255B00FD7257 /* PostListModel.swift in Sources */,
174D313224EC2831006CA9EE /* WriteFreelyModel.swift in Sources */,
17C42E70250AA12300072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */,
17120DA124E19839002B9F6C /* AccountView.swift in Sources */,
1756AE7424CB26FA00FD7257 /* PostCellView.swift in Sources */,
);
@@ -610,6 +615,7 @@
17DF32D624C8CA3400BCE2E3 /* PostStatusBadgeView.swift in Sources */,
17C42E662509237800072984 /* PostListFilteredView.swift in Sources */,
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */,
17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */,
1756AE7B24CB65DF00FD7257 /* PostListView.swift in Sources */,
1753F6AC24E431CC00309365 /* MacPreferencesView.swift in Sources */,
1756DC0424FEE18400207AB8 /* WFACollection+CoreDataProperties.swift in Sources */,


+ 3
- 3
iOS/Settings/SettingsHeaderView.swift ファイルの表示

@@ -1,7 +1,7 @@
import SwiftUI

struct SettingsHeaderView: View {
@Binding var isPresented: Bool
@Environment(\.presentationMode) var presentationMode

var body: some View {
HStack {
@@ -10,7 +10,7 @@ struct SettingsHeaderView: View {
.fontWeight(.bold)
Spacer()
Button(action: {
isPresented = false
presentationMode.wrappedValue.dismiss()
}, label: {
Image(systemName: "xmark.circle")
})
@@ -21,6 +21,6 @@ struct SettingsHeaderView: View {

struct SettingsHeaderView_Previews: PreviewProvider {
static var previews: some View {
SettingsHeaderView(isPresented: .constant(true))
SettingsHeaderView()
}
}

+ 2
- 4
iOS/Settings/SettingsView.swift ファイルの表示

@@ -3,11 +3,9 @@ import SwiftUI
struct SettingsView: View {
@EnvironmentObject var model: WriteFreelyModel

@Binding var isPresented: Bool

var body: some View {
VStack {
SettingsHeaderView(isPresented: $isPresented)
SettingsHeaderView()
Form {
Section(header: Text("Login Details")) {
AccountView()
@@ -23,7 +21,7 @@ struct SettingsView: View {

struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
SettingsView(isPresented: .constant(true))
SettingsView()
.environmentObject(WriteFreelyModel())
}
}

読み込み中…
キャンセル
保存