@@ -10,7 +10,7 @@ enum PostStatus { | |||
class Post: Identifiable, ObservableObject, Hashable { | |||
@Published var wfPost: WFPost | |||
@Published var status: PostStatus | |||
@Published var collection: PostCollection | |||
@Published var collection: PostCollection? | |||
@Published var hasNewerRemoteCopy: Bool = false | |||
let id = UUID() | |||
@@ -19,15 +19,15 @@ class Post: Identifiable, ObservableObject, Hashable { | |||
title: String = "Title", | |||
body: String = "Write your post here...", | |||
createdDate: Date = Date(), | |||
status: PostStatus = .local, | |||
collection: PostCollection = draftsCollection | |||
status: PostStatus = .draft, | |||
collection: PostCollection? = nil | |||
) { | |||
self.wfPost = WFPost(body: body, title: title, createdDate: createdDate) | |||
self.status = status | |||
self.collection = collection | |||
} | |||
convenience init(wfPost: WFPost, in collection: PostCollection = draftsCollection) { | |||
convenience init(wfPost: WFPost, in collection: PostCollection? = nil) { | |||
self.init( | |||
title: wfPost.title ?? "", | |||
body: wfPost.body, | |||
@@ -50,6 +50,10 @@ extension Post { | |||
} | |||
#if DEBUG | |||
let userCollection1 = PostCollection(title: "Collection 1") | |||
let userCollection2 = PostCollection(title: "Collection 2") | |||
let userCollection3 = PostCollection(title: "Collection 3") | |||
let testPost = Post( | |||
title: "Test Post Title", | |||
body: """ | |||
@@ -1,10 +1,14 @@ | |||
import Foundation | |||
import WriteFreely | |||
struct PostCollection: Identifiable { | |||
class PostCollection: Identifiable { | |||
let id = UUID() | |||
let title: String | |||
var title: String | |||
var wfCollection: WFCollection? | |||
init(title: String) { | |||
self.title = title | |||
} | |||
} | |||
extension PostCollection { | |||
@@ -12,12 +16,3 @@ extension PostCollection { | |||
return lhs.id == rhs.id | |||
} | |||
} | |||
let allPostsCollection = PostCollection(title: "All Posts") | |||
let draftsCollection = PostCollection(title: "Drafts") | |||
#if DEBUG | |||
let userCollection1 = PostCollection(title: "Collection 1") | |||
let userCollection2 = PostCollection(title: "Collection 2") | |||
let userCollection3 = PostCollection(title: "Collection 3") | |||
#endif |
@@ -8,7 +8,7 @@ class WriteFreelyModel: ObservableObject { | |||
@Published var account = AccountModel() | |||
@Published var preferences = PreferencesModel() | |||
@Published var store = PostStore() | |||
@Published var collections = CollectionListModel(with: []) | |||
@Published var collections = CollectionListModel() | |||
@Published var isLoggingIn: Bool = false | |||
@Published var selectedPost: Post? | |||
@@ -96,7 +96,7 @@ extension WriteFreelyModel { | |||
} else { | |||
// This is a new local draft. | |||
loggedInClient.createPost( | |||
post: post.wfPost, in: post.collection.wfCollection?.alias, completion: publishHandler | |||
post: post.wfPost, in: post.collection?.wfCollection?.alias, completion: publishHandler | |||
) | |||
} | |||
} | |||
@@ -190,12 +190,24 @@ private extension WriteFreelyModel { | |||
let fetchedCollections = try result.get() | |||
var fetchedCollectionsArray: [PostCollection] = [] | |||
for fetchedCollection in fetchedCollections { | |||
var postCollection = PostCollection(title: fetchedCollection.title) | |||
let postCollection = PostCollection(title: fetchedCollection.title) | |||
postCollection.wfCollection = fetchedCollection | |||
fetchedCollectionsArray.append(postCollection) | |||
DispatchQueue.main.async { | |||
let localCollection = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
localCollection.alias = fetchedCollection.alias | |||
localCollection.blogDescription = fetchedCollection.description | |||
localCollection.email = fetchedCollection.email | |||
localCollection.isPublic = fetchedCollection.isPublic ?? false | |||
localCollection.styleSheet = fetchedCollection.styleSheet | |||
localCollection.title = fetchedCollection.title | |||
localCollection.url = fetchedCollection.url | |||
} | |||
} | |||
DispatchQueue.main.async { | |||
self.collections = CollectionListModel(with: fetchedCollectionsArray) | |||
// self.collections = CollectionListModel(with: fetchedCollectionsArray) | |||
PersistenceManager().saveContext() | |||
} | |||
} catch { | |||
print(error) | |||
@@ -209,10 +221,10 @@ private extension WriteFreelyModel { | |||
for fetchedPost in fetchedPosts { | |||
var post: Post | |||
if let matchingAlias = fetchedPost.collectionAlias { | |||
let postCollection = ( | |||
collections.userCollections.filter { $0.wfCollection?.alias == matchingAlias } | |||
).first | |||
post = Post(wfPost: fetchedPost, in: postCollection ?? draftsCollection) | |||
let postCollection = PostCollection(title: ( | |||
collections.userCollections.filter { $0.alias == matchingAlias } | |||
).first?.title ?? "NO TITLE") | |||
post = Post(wfPost: fetchedPost, in: postCollection) | |||
} else { | |||
post = Post(wfPost: fetchedPost) | |||
} | |||
@@ -7,7 +7,7 @@ struct ContentView: View { | |||
NavigationView { | |||
SidebarView() | |||
PostListView(selectedCollection: allPostsCollection) | |||
PostListView(selectedCollection: CollectionListModel.allPostsCollection) | |||
Text("Select a post, or create a new local draft.") | |||
.foregroundColor(.secondary) | |||
@@ -18,12 +18,21 @@ struct ContentView: View { | |||
struct ContentView_Previews: PreviewProvider { | |||
static var previews: some View { | |||
let userCollection1 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
let userCollection2 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
let userCollection3 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
userCollection1.title = "Collection 1" | |||
userCollection2.title = "Collection 2" | |||
userCollection3.title = "Collection 3" | |||
let model = WriteFreelyModel() | |||
model.collections = CollectionListModel(with: [userCollection1, userCollection2, userCollection3]) | |||
model.collections = CollectionListModel() | |||
for post in testPostData { | |||
model.store.add(post) | |||
} | |||
return ContentView() | |||
.environmentObject(model) | |||
.environment(\.managedObjectContext, PersistenceManager.persistentContainer.viewContext) | |||
} | |||
} |
@@ -8,9 +8,18 @@ struct SidebarView: View { | |||
struct SidebarView_Previews: PreviewProvider { | |||
static var previews: some View { | |||
let userCollection1 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
let userCollection2 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
let userCollection3 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
userCollection1.title = "Collection 1" | |||
userCollection2.title = "Collection 2" | |||
userCollection3.title = "Collection 3" | |||
let model = WriteFreelyModel() | |||
model.collections = CollectionListModel(with: [userCollection1, userCollection2, userCollection3]) | |||
model.collections = CollectionListModel() | |||
return SidebarView() | |||
.environmentObject(model) | |||
.environment(\.managedObjectContext, PersistenceManager.persistentContainer.viewContext) | |||
} | |||
} |
@@ -7,13 +7,14 @@ import AppKit | |||
#endif | |||
class PersistenceManager { | |||
let persistentContainer: NSPersistentContainer = { | |||
static let persistentContainer: NSPersistentContainer = { | |||
let container = NSPersistentContainer(name: "LocalStorageModel") | |||
container.loadPersistentStores(completionHandler: { (_, error) in | |||
container.loadPersistentStores { _, error in | |||
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy | |||
if let error = error { | |||
fatalError("Unresolved error loading persistent store: \(error)") | |||
} | |||
}) | |||
} | |||
return container | |||
}() | |||
@@ -38,9 +39,9 @@ class PersistenceManager { | |||
} | |||
func saveContext() { | |||
if persistentContainer.viewContext.hasChanges { | |||
if PersistenceManager.persistentContainer.viewContext.hasChanges { | |||
do { | |||
try persistentContainer.viewContext.save() | |||
try PersistenceManager.persistentContainer.viewContext.save() | |||
} catch { | |||
print("Error saving context: \(error)") | |||
} | |||
@@ -1,18 +1,25 @@ | |||
import SwiftUI | |||
import CoreData | |||
class CollectionListModel: ObservableObject { | |||
private(set) var userCollections: [PostCollection] = [] | |||
@Published private(set) var collectionsList: [PostCollection] = [ allPostsCollection, draftsCollection ] | |||
@Published var userCollections = [WFACollection]() | |||
init(with userCollections: [PostCollection]) { | |||
for userCollection in userCollections { | |||
self.userCollections.append(userCollection) | |||
} | |||
collectionsList.append(contentsOf: self.userCollections) | |||
static let allPostsCollection = PostCollection(title: "All Posts") | |||
static let draftsCollection = PostCollection(title: "Drafts") | |||
init() { | |||
// let request = WFACollection.createFetchRequest() | |||
// request.sortDescriptors = [] | |||
// do { | |||
// userCollections = try PersistenceManager.persistentContainer.viewContext.fetch(request) | |||
// } catch { | |||
// print("Error: Failed to fetch user collections from local store") | |||
// userCollections = [] | |||
// } | |||
} | |||
func clearUserCollection() { | |||
userCollections = [] | |||
collectionsList = [ allPostsCollection, draftsCollection ] | |||
// Clear collections from CoreData store. | |||
} | |||
} |
@@ -2,14 +2,25 @@ import SwiftUI | |||
struct CollectionListView: View { | |||
@EnvironmentObject var model: WriteFreelyModel | |||
@Environment(\.managedObjectContext) var moc | |||
@FetchRequest(entity: WFACollection.entity(), sortDescriptors: []) var collections: FetchedResults<WFACollection> | |||
var body: some View { | |||
List { | |||
ForEach(model.collections.collectionsList) { collection in | |||
NavigationLink( | |||
destination: PostListView(selectedCollection: collection) | |||
) { | |||
Text(collection.title) | |||
NavigationLink(destination: PostListView(selectedCollection: CollectionListModel.allPostsCollection)) { | |||
Text(CollectionListModel.allPostsCollection.title) | |||
} | |||
NavigationLink(destination: PostListView(selectedCollection: CollectionListModel.draftsCollection)) { | |||
Text(CollectionListModel.draftsCollection.title) | |||
} | |||
Section(header: Text("Your Blogs")) { | |||
ForEach(collections, id: \.alias) { collection in | |||
NavigationLink( | |||
destination: PostListView(selectedCollection: PostCollection(title: collection.title)) | |||
) { | |||
Text(collection.title) | |||
} | |||
} | |||
} | |||
} | |||
@@ -19,10 +30,21 @@ struct CollectionListView: View { | |||
} | |||
struct CollectionSidebar_Previews: PreviewProvider { | |||
@Environment(\.managedObjectContext) var moc | |||
static var previews: some View { | |||
let userCollection1 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
let userCollection2 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
let userCollection3 = WFACollection(context: PersistenceManager.persistentContainer.viewContext) | |||
userCollection1.title = "Collection 1" | |||
userCollection2.title = "Collection 2" | |||
userCollection3.title = "Collection 3" | |||
let model = WriteFreelyModel() | |||
model.collections = CollectionListModel(with: [userCollection1, userCollection2, userCollection3]) | |||
model.collections = CollectionListModel() | |||
return CollectionListView() | |||
.environmentObject(model) | |||
.environment(\.managedObjectContext, PersistenceManager.persistentContainer.viewContext) | |||
} | |||
} |
@@ -105,13 +105,15 @@ struct PostListView: View { | |||
} | |||
private func showPosts(for collection: PostCollection) -> [Post] { | |||
if collection == allPostsCollection { | |||
return model.store.posts | |||
var posts: [Post] | |||
if collection == CollectionListModel.allPostsCollection { | |||
posts = model.store.posts | |||
} else if collection == CollectionListModel.draftsCollection { | |||
posts = model.store.posts.filter { $0.collection == nil } | |||
} else { | |||
return model.store.posts.filter { | |||
$0.collection.title == collection.title | |||
} | |||
posts = model.store.posts.filter { $0.collection?.title == collection.title } | |||
} | |||
return posts | |||
} | |||
private func reloadFromServer() { | |||
@@ -130,7 +132,7 @@ struct PostList_Previews: PreviewProvider { | |||
model.store.add(post) | |||
} | |||
return Group { | |||
PostListView(selectedCollection: allPostsCollection) | |||
PostListView(selectedCollection: CollectionListModel.allPostsCollection) | |||
.environmentObject(model) | |||
} | |||
} | |||
@@ -12,6 +12,7 @@ struct WriteFreely_MultiPlatformApp: App { | |||
WindowGroup { | |||
ContentView() | |||
.environmentObject(model) | |||
.environment(\.managedObjectContext, PersistenceManager.persistentContainer.viewContext) | |||
// .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info. | |||
} | |||
@@ -3,7 +3,7 @@ import CoreData | |||
extension WFACollection { | |||
@nonobjc public class func fetchRequest() -> NSFetchRequest<WFACollection> { | |||
@nonobjc public class func createFetchRequest() -> NSFetchRequest<WFACollection> { | |||
return NSFetchRequest<WFACollection>(entityName: "WFACollection") | |||
} | |||
@@ -12,7 +12,7 @@ extension WFACollection { | |||
@NSManaged public var email: String? | |||
@NSManaged public var isPublic: Bool | |||
@NSManaged public var styleSheet: String? | |||
@NSManaged public var title: String? | |||
@NSManaged public var title: String | |||
@NSManaged public var url: String? | |||
} | |||