From 1a8ae1d4d30ee8d6230161676ed6714521bb12e3 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 24 Nov 2020 15:15:28 -0500 Subject: [PATCH 01/21] Remove PostEditorView toolbar (post status badge and publish button) --- macOS/PostEditor/PostEditorView.swift | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/macOS/PostEditor/PostEditorView.swift b/macOS/PostEditor/PostEditorView.swift index a026563..f0f3d36 100644 --- a/macOS/PostEditor/PostEditorView.swift +++ b/macOS/PostEditor/PostEditorView.swift @@ -15,26 +15,6 @@ struct PostEditorView: View { ) .padding() .background(Color(NSColor.controlBackgroundColor)) - .toolbar { - ToolbarItem(placement: .status) { - PostEditorStatusToolbarView(post: post) - } - ToolbarItem(placement: .primaryAction) { - Button(action: { - if model.account.isLoggedIn { - publishPost() - } else { - let mainMenu = NSApplication.shared.mainMenu - let appMenuItem = mainMenu?.item(withTitle: "WriteFreely") - let prefsItem = appMenuItem?.submenu?.item(withTitle: "Preferences…") - NSApplication.shared.sendAction(prefsItem!.action!, to: prefsItem?.target, from: nil) - } - }, label: { - Image(systemName: "paperplane") - }) - .disabled(post.status == PostStatus.published.rawValue || post.body.count == 0) - } - } .onChange(of: post.hasNewerRemoteCopy, perform: { _ in if !post.hasNewerRemoteCopy { self.updatingFromServer = true @@ -56,13 +36,6 @@ struct PostEditorView: View { } }) } - - private func publishPost() { - DispatchQueue.main.async { - LocalStorageManager().saveContext() - model.publish(post: post) - } - } } struct PostEditorView_EmptyPostPreviews: PreviewProvider { From 1215a1727a826efd9b4541df5053b7b9792ea548 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 24 Nov 2020 15:24:08 -0500 Subject: [PATCH 02/21] Remove PostListView toolbar (new post and reload from server) --- Shared/PostList/PostListView.swift | 48 ------------------------------ 1 file changed, 48 deletions(-) diff --git a/Shared/PostList/PostListView.swift b/Shared/PostList/PostListView.swift index dddca79..564a097 100644 --- a/Shared/PostList/PostListView.swift +++ b/Shared/PostList/PostListView.swift @@ -61,56 +61,8 @@ struct PostListView: View { ) ) .navigationSubtitle(postCount == 1 ? "\(postCount) post" : "\(postCount) posts") - .toolbar { - Button(action: { - createNewLocalDraft() - }, label: { - Image(systemName: "square.and.pencil") - }) - Button(action: { - reloadFromServer() - }, label: { - Image(systemName: "arrow.clockwise") - }) - .disabled(!model.account.isLoggedIn) - } #endif } - - private func reloadFromServer() { - DispatchQueue.main.async { - model.fetchUserCollections() - model.fetchUserPosts() - } - } - - private func createNewLocalDraft() { - let managedPost = WFAPost(context: self.managedObjectContext) - managedPost.createdDate = Date() - managedPost.title = "" - managedPost.body = "" - managedPost.status = PostStatus.local.rawValue - managedPost.collectionAlias = nil - switch model.preferences.font { - case 1: - managedPost.appearance = "sans" - case 2: - managedPost.appearance = "wrap" - default: - managedPost.appearance = "serif" - } - if let languageCode = Locale.current.languageCode { - managedPost.language = languageCode - managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft - } - DispatchQueue.main.async { - self.selectedCollection = nil - self.showAllPosts = false - withAnimation { - self.model.selectedPost = managedPost - } - } - } } struct PostListView_Previews: PreviewProvider { From 39ae83905225e3a01bcf4a3f02a176b8ac72e89e Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 24 Nov 2020 15:35:26 -0500 Subject: [PATCH 03/21] Add toolbar button and menu entry to toggle sidebar --- Shared/Navigation/ContentView.swift | 12 ++++++++++++ Shared/WriteFreely_MultiPlatformApp.swift | 3 +++ 2 files changed, 15 insertions(+) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 6831b7c..69b9daa 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -5,7 +5,19 @@ struct ContentView: View { var body: some View { NavigationView { + #if os(macOS) SidebarView() + .toolbar { + Button(action: { + NSApp.keyWindow?.contentViewController?.tryToPerform( + #selector(NSSplitViewController.toggleSidebar(_:)), + with: nil + ) + }, label: { Image(systemName: "sidebar.left") }) + } + #else + SidebarView() + #endif PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index ef3a31f..787111b 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -22,6 +22,9 @@ struct WriteFreely_MultiPlatformApp: App { .environment(\.managedObjectContext, LocalStorageManager.persistentContainer.viewContext) // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info. } + .commands { + SidebarCommands() + } #if os(macOS) Settings { From 1e432c6adb3c6d72db1eee6ce8d0c74bdbd73fd0 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Wed, 25 Nov 2020 14:11:57 -0500 Subject: [PATCH 04/21] Fix spacing when collapsing sidebar, add other buttons to toolbar --- Shared/Navigation/ContentView.swift | 44 +++++++++++++++++++---- Shared/WriteFreely_MultiPlatformApp.swift | 13 +++++-- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 69b9daa..38ad408 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -2,24 +2,54 @@ import SwiftUI struct ContentView: View { @EnvironmentObject var model: WriteFreelyModel + @Binding var sidebarIsHidden: Bool var body: some View { NavigationView { #if os(macOS) SidebarView() .toolbar { - Button(action: { - NSApp.keyWindow?.contentViewController?.tryToPerform( - #selector(NSSplitViewController.toggleSidebar(_:)), - with: nil - ) - }, label: { Image(systemName: "sidebar.left") }) + Button( + action: { + NSApp.keyWindow?.contentViewController?.tryToPerform( + #selector(NSSplitViewController.toggleSidebar(_:)), with: nil + ) + withAnimation { self.sidebarIsHidden.toggle() } + }, + label: { Image(systemName: "sidebar.left") } + ) + Spacer() + Button(action: {}, label: { Image(systemName: "square.and.pencil") }) } #else SidebarView() #endif + #if os(macOS) PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) + .toolbar { + ToolbarItem(placement: .navigation) { + Button(action: {}, label: { Image(systemName: "arrow.clockwise") }) + .padding(.leading, sidebarIsHidden ? 8 : 0) + .animation(.linear) + } + ToolbarItem(placement: .status) { + if let selectedPost = model.selectedPost { + PostStatusBadgeView(post: selectedPost) + } + } + ToolbarItemGroup(placement: .primaryAction) { + if let selectedPost = model.selectedPost { + Button(action: {}, label: { Image(systemName: "paperplane") }) + .disabled(selectedPost.body.isEmpty) + Button(action: {}, label: { Image(systemName: "square.and.arrow.up") }) + .disabled(selectedPost.status == PostStatus.local.rawValue) + } + } + } + #else + PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) + #endif Text("Select a post, or create a new local draft.") .foregroundColor(.secondary) @@ -72,7 +102,7 @@ struct ContentView_Previews: PreviewProvider { let context = LocalStorageManager.persistentContainer.viewContext let model = WriteFreelyModel() - return ContentView() + return ContentView(sidebarIsHidden: .constant(false)) .environment(\.managedObjectContext, context) .environmentObject(model) } diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index 787111b..b4d8b46 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -6,11 +6,12 @@ struct WriteFreely_MultiPlatformApp: App { #if os(macOS) @State private var selectedTab = 0 + @State private var sidebarIsHidden: Bool = false #endif var body: some Scene { WindowGroup { - ContentView() + ContentView(sidebarIsHidden: $sidebarIsHidden) .onAppear(perform: { if let lastDraft = model.editor.fetchLastDraftFromUserDefaults() { self.model.selectedPost = lastDraft @@ -23,7 +24,15 @@ struct WriteFreely_MultiPlatformApp: App { // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info. } .commands { - SidebarCommands() + CommandGroup(after: .sidebar) { + Button("Toggle Sidebar") { + NSApp.keyWindow?.contentViewController?.tryToPerform( + #selector(NSSplitViewController.toggleSidebar(_:)), with: nil + ) + withAnimation { self.sidebarIsHidden.toggle() } + } + .keyboardShortcut("s", modifiers: [.command, .option]) + } } #if os(macOS) From 735867a94043f889692e591f87d635d6b57f5abe Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Wed, 25 Nov 2020 14:41:53 -0500 Subject: [PATCH 05/21] Add new-post logic to toolbar button and menu, fix broken iOS code --- Shared/Navigation/ContentView.swift | 27 ++++++++++++++++++++- Shared/PostList/PostListModel.swift | 6 +++-- Shared/PostList/PostListView.swift | 29 +++++++++++++++++++++-- Shared/WriteFreely_MultiPlatformApp.swift | 17 +++++++++++-- 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 38ad408..2bb11f6 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -19,7 +19,32 @@ struct ContentView: View { label: { Image(systemName: "sidebar.left") } ) Spacer() - Button(action: {}, label: { Image(systemName: "square.and.pencil") }) + Button(action: { + withAnimation { + self.model.selectedPost = nil + } + let managedPost = WFAPost(context: LocalStorageManager.persistentContainer.viewContext) + managedPost.createdDate = Date() + managedPost.title = "" + managedPost.body = "" + managedPost.status = PostStatus.local.rawValue + managedPost.collectionAlias = nil + switch model.preferences.font { + case 1: + managedPost.appearance = "sans" + case 2: + managedPost.appearance = "wrap" + default: + managedPost.appearance = "serif" + } + if let languageCode = Locale.current.languageCode { + managedPost.language = languageCode + managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft + } + withAnimation { + self.model.selectedPost = managedPost + } + }, label: { Image(systemName: "square.and.pencil") }) } #else SidebarView() diff --git a/Shared/PostList/PostListModel.swift b/Shared/PostList/PostListModel.swift index 98e158b..c7ada24 100644 --- a/Shared/PostList/PostListModel.swift +++ b/Shared/PostList/PostListModel.swift @@ -3,8 +3,10 @@ import CoreData class PostListModel: ObservableObject { func remove(_ post: WFAPost) { - LocalStorageManager.persistentContainer.viewContext.delete(post) - LocalStorageManager().saveContext() + withAnimation { + LocalStorageManager.persistentContainer.viewContext.delete(post) + LocalStorageManager().saveContext() + } } func purgePublishedPosts() { diff --git a/Shared/PostList/PostListView.swift b/Shared/PostList/PostListView.swift index 564a097..ffc545b 100644 --- a/Shared/PostList/PostListView.swift +++ b/Shared/PostList/PostListView.swift @@ -21,7 +21,29 @@ struct PostListView: View { .toolbar { ToolbarItem(placement: .primaryAction) { Button(action: { - createNewLocalDraft() + let managedPost = WFAPost(context: self.managedObjectContext) + managedPost.createdDate = Date() + managedPost.title = "" + managedPost.body = "" + managedPost.status = PostStatus.local.rawValue + managedPost.collectionAlias = nil + switch model.preferences.font { + case 1: + managedPost.appearance = "sans" + case 2: + managedPost.appearance = "wrap" + default: + managedPost.appearance = "serif" + } + if let languageCode = Locale.current.languageCode { + managedPost.language = languageCode + managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft + } + withAnimation { + self.selectedCollection = nil + self.showAllPosts = false + self.model.selectedPost = managedPost + } }, label: { Image(systemName: "square.and.pencil") }) @@ -41,7 +63,10 @@ struct PostListView: View { ProgressView() } else { Button(action: { - reloadFromServer() + DispatchQueue.main.async { + model.fetchUserCollections() + model.fetchUserPosts() + } }, label: { Image(systemName: "arrow.clockwise") }) diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index b4d8b46..af749bd 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -3,10 +3,10 @@ import SwiftUI @main struct WriteFreely_MultiPlatformApp: App { @StateObject private var model = WriteFreelyModel() + @State private var sidebarIsHidden: Bool = false #if os(macOS) @State private var selectedTab = 0 - @State private var sidebarIsHidden: Bool = false #endif var body: some Scene { @@ -24,6 +24,13 @@ struct WriteFreely_MultiPlatformApp: App { // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info. } .commands { + CommandGroup(replacing: .newItem, addition: { + Button("New Local Draft") { + createNewLocalPost() + } + .keyboardShortcut("n", modifiers: [.command]) + }) + #if os(macOS) CommandGroup(after: .sidebar) { Button("Toggle Sidebar") { NSApp.keyWindow?.contentViewController?.tryToPerform( @@ -33,6 +40,7 @@ struct WriteFreely_MultiPlatformApp: App { } .keyboardShortcut("s", modifiers: [.command, .option]) } + #endif } #if os(macOS) @@ -60,6 +68,9 @@ struct WriteFreely_MultiPlatformApp: App { } private func createNewLocalPost() { + withAnimation { + self.model.selectedPost = nil + } let managedPost = WFAPost(context: LocalStorageManager.persistentContainer.viewContext) managedPost.createdDate = Date() managedPost.title = "" @@ -78,6 +89,8 @@ struct WriteFreely_MultiPlatformApp: App { managedPost.language = languageCode managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft } - self.model.selectedPost = managedPost + withAnimation { + self.model.selectedPost = managedPost + } } } From acde0c8978f5ee17ffa45371af14515f5e6528a1 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Wed, 25 Nov 2020 15:10:22 -0500 Subject: [PATCH 06/21] Add toolbar button logic, menu item, keyboard shortcut for server reload --- Shared/Navigation/ContentView.swift | 7 ++++++- Shared/WriteFreely_MultiPlatformApp.swift | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 2bb11f6..7141da4 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -54,7 +54,12 @@ struct ContentView: View { PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) .toolbar { ToolbarItem(placement: .navigation) { - Button(action: {}, label: { Image(systemName: "arrow.clockwise") }) + Button(action: { + DispatchQueue.main.async { + model.fetchUserCollections() + model.fetchUserPosts() + } + }, label: { Image(systemName: "arrow.clockwise") }) .padding(.leading, sidebarIsHidden ? 8 : 0) .animation(.linear) } diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index af749bd..0221e4d 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -30,6 +30,15 @@ struct WriteFreely_MultiPlatformApp: App { } .keyboardShortcut("n", modifiers: [.command]) }) + CommandGroup(after: .newItem) { + Button("Reload From Server") { + DispatchQueue.main.async { + model.fetchUserCollections() + model.fetchUserPosts() + } + } + .keyboardShortcut("r", modifiers: [.command]) + } #if os(macOS) CommandGroup(after: .sidebar) { Button("Toggle Sidebar") { From 7398c1d3cf54c2802e848fc895104a1d4e72b653 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Wed, 25 Nov 2020 16:06:52 -0500 Subject: [PATCH 07/21] Implement basic publishing --- Shared/Navigation/ContentView.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 7141da4..f270ca8 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -70,8 +70,13 @@ struct ContentView: View { } ToolbarItemGroup(placement: .primaryAction) { if let selectedPost = model.selectedPost { - Button(action: {}, label: { Image(systemName: "paperplane") }) - .disabled(selectedPost.body.isEmpty) + Button(action: { + DispatchQueue.main.async { + LocalStorageManager().saveContext() + model.publish(post: selectedPost) + } + }, label: { Image(systemName: "paperplane") }) + .disabled(selectedPost.body.isEmpty || selectedPost.status == PostStatus.published.rawValue) Button(action: {}, label: { Image(systemName: "square.and.arrow.up") }) .disabled(selectedPost.status == PostStatus.local.rawValue) } From 7cb7fa3017df2d2cb16677dbc96b53c943d0940e Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Thu, 26 Nov 2020 12:05:20 -0500 Subject: [PATCH 08/21] Use AppStorage dynamic property instead of direct UserDefaults update Known issue: the menubar File > Reload From Server command will not update based on changes to model.account.isLoggedIn, but instead defaults to whatever the value was on app launch. Filed as FB8918303 with Apple. --- Shared/Account/AccountModel.swift | 8 ++------ Shared/Navigation/ContentView.swift | 5 +++-- Shared/WriteFreely_MultiPlatformApp.swift | 1 + 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Shared/Account/AccountModel.swift b/Shared/Account/AccountModel.swift index 4ce81b2..25683a5 100644 --- a/Shared/Account/AccountModel.swift +++ b/Shared/Account/AccountModel.swift @@ -1,4 +1,4 @@ -import Foundation +import SwiftUI import WriteFreely enum AccountError: Error { @@ -30,8 +30,8 @@ extension AccountError: LocalizedError { } struct AccountModel { + @AppStorage("isLoggedIn") var isLoggedIn: Bool = false private let defaults = UserDefaults.standard - let isLoggedInFlag = "isLoggedInFlag" let usernameStringKey = "usernameStringKey" let serverStringKey = "serverStringKey" @@ -39,13 +39,11 @@ struct AccountModel { var username: String = "" private(set) var user: WFUser? - private(set) var isLoggedIn: Bool = false mutating func login(_ user: WFUser) { self.user = user self.username = user.username ?? "" self.isLoggedIn = true - defaults.set(true, forKey: isLoggedInFlag) defaults.set(user.username, forKey: usernameStringKey) defaults.set(server, forKey: serverStringKey) } @@ -53,13 +51,11 @@ struct AccountModel { mutating func logout() { self.user = nil self.isLoggedIn = false - defaults.set(false, forKey: isLoggedInFlag) defaults.removeObject(forKey: usernameStringKey) defaults.removeObject(forKey: serverStringKey) } mutating func restoreState() { - isLoggedIn = defaults.bool(forKey: isLoggedInFlag) server = defaults.string(forKey: serverStringKey) ?? "" username = defaults.string(forKey: usernameStringKey) ?? "" } diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index f270ca8..bc5e6ce 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -60,8 +60,9 @@ struct ContentView: View { model.fetchUserPosts() } }, label: { Image(systemName: "arrow.clockwise") }) - .padding(.leading, sidebarIsHidden ? 8 : 0) - .animation(.linear) + .disabled(!model.account.isLoggedIn) + .padding(.leading, sidebarIsHidden ? 8 : 0) + .animation(.linear) } ToolbarItem(placement: .status) { if let selectedPost = model.selectedPost { diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index 0221e4d..f0918c5 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -37,6 +37,7 @@ struct WriteFreely_MultiPlatformApp: App { model.fetchUserPosts() } } + .disabled(!model.account.isLoggedIn) .keyboardShortcut("r", modifiers: [.command]) } #if os(macOS) From 5ca32ddcfcf54cbadf5834e99295dfdee7da374c Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Thu, 26 Nov 2020 15:01:12 -0500 Subject: [PATCH 09/21] Show prompt if there are server-side changes to post --- Shared/Navigation/ContentView.swift | 2 +- .../PostEditorStatusToolbarView.swift | 52 +++++++++++-------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index bc5e6ce..c4d878f 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -66,7 +66,7 @@ struct ContentView: View { } ToolbarItem(placement: .status) { if let selectedPost = model.selectedPost { - PostStatusBadgeView(post: selectedPost) + PostEditorStatusToolbarView(post: selectedPost) } } ToolbarItemGroup(placement: .primaryAction) { diff --git a/Shared/PostEditor/PostEditorStatusToolbarView.swift b/Shared/PostEditor/PostEditorStatusToolbarView.swift index 580e051..7d8cac4 100644 --- a/Shared/PostEditor/PostEditorStatusToolbarView.swift +++ b/Shared/PostEditor/PostEditorStatusToolbarView.swift @@ -11,16 +11,21 @@ struct PostEditorStatusToolbarView: View { PostStatusBadgeView(post: post) #else HStack { + HStack { + Text("⚠️ Newer copy on server. Replace local copy?") + .font(.callout) + .foregroundColor(.secondary) + Button(action: { + model.updateFromServer(post: post) + }, label: { + Image(systemName: "square.and.arrow.down") + }) + } + .padding(.horizontal) + .background(Color.primary.opacity(0.1)) + .clipShape(Capsule()) + .padding(.trailing) PostStatusBadgeView(post: post) - .padding(.trailing) - Text("⚠️ Newer copy on server. Replace local copy?") - .font(.callout) - .foregroundColor(.secondary) - Button(action: { - model.updateFromServer(post: post) - }, label: { - Image(systemName: "square.and.arrow.down") - }) } #endif } else if post.wasDeletedFromServer && post.status != PostStatus.local.rawValue { @@ -28,19 +33,24 @@ struct PostEditorStatusToolbarView: View { PostStatusBadgeView(post: post) #else HStack { + HStack { + Text("⚠️ Post deleted from server. Delete local copy?") + .font(.callout) + .foregroundColor(.secondary) + Button(action: { + model.selectedPost = nil + DispatchQueue.main.async { + model.posts.remove(post) + } + }, label: { + Image(systemName: "trash") + }) + } + .padding(.horizontal) + .background(Color.primary.opacity(0.1)) + .clipShape(Capsule()) + .padding(.trailing) PostStatusBadgeView(post: post) - .padding(.trailing) - Text("⚠️ Post deleted from server. Delete local copy?") - .font(.callout) - .foregroundColor(.secondary) - Button(action: { - model.selectedPost = nil - DispatchQueue.main.async { - model.posts.remove(post) - } - }, label: { - Image(systemName: "trash") - }) } #endif } else { From 8ff1de188b738c0128cd1a614515e023e1215d6d Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Thu, 26 Nov 2020 15:52:00 -0500 Subject: [PATCH 10/21] Make adding and deleting posts more reliable/crashproof --- Shared/Navigation/ContentView.swift | 4 +++- Shared/PostList/PostListFilteredView.swift | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index c4d878f..df5e0ae 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -42,7 +42,9 @@ struct ContentView: View { managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft } withAnimation { - self.model.selectedPost = managedPost + DispatchQueue.main.async { + self.model.selectedPost = managedPost + } } }, label: { Image(systemName: "square.and.pencil") }) } diff --git a/Shared/PostList/PostListFilteredView.swift b/Shared/PostList/PostListFilteredView.swift index 6b37511..899eb74 100644 --- a/Shared/PostList/PostListFilteredView.swift +++ b/Shared/PostList/PostListFilteredView.swift @@ -103,7 +103,9 @@ struct PostListFilteredView: View { } func delete(_ post: WFAPost) { - model.posts.remove(post) + DispatchQueue.main.async { + model.posts.remove(post) + } } } From b78899414439a2cc0e3eaf7c7707e5c43c0ff64b Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Thu, 26 Nov 2020 15:53:17 -0500 Subject: [PATCH 11/21] Save/load last draft per editor launching policy --- macOS/PostEditor/PostEditorView.swift | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/macOS/PostEditor/PostEditorView.swift b/macOS/PostEditor/PostEditorView.swift index f0f3d36..08d0b9a 100644 --- a/macOS/PostEditor/PostEditorView.swift +++ b/macOS/PostEditor/PostEditorView.swift @@ -1,7 +1,6 @@ import SwiftUI struct PostEditorView: View { - private let bodyLineSpacing: CGFloat = 17 * 0.5 @EnvironmentObject var model: WriteFreelyModel @ObservedObject var post: WFAPost @@ -15,11 +14,30 @@ struct PostEditorView: View { ) .padding() .background(Color(NSColor.controlBackgroundColor)) + .onAppear(perform: { + if post.status != PostStatus.published.rawValue { + DispatchQueue.main.async { + self.model.editor.saveLastDraft(post) + } + } else { + self.model.editor.clearLastDraft() + } + }) .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().saveContext() + } + }) .onDisappear(perform: { if post.title.count == 0 && post.body.count == 0 From 5dabe97db4fa7eb31b82ac34a45d7988d86e79b2 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Thu, 26 Nov 2020 16:38:39 -0500 Subject: [PATCH 12/21] Restore alerts on Edit > Delete, no-network failure --- Shared/Navigation/ContentView.swift | 47 +++++++++------------- Shared/PostList/PostListFilteredView.swift | 19 +++++++++ 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index df5e0ae..5ed54b7 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -65,6 +65,17 @@ struct ContentView: View { .disabled(!model.account.isLoggedIn) .padding(.leading, sidebarIsHidden ? 8 : 0) .animation(.linear) + .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: { + Alert( + title: Text("Connection Error"), + message: Text(""" + There is no internet connection at the moment. Please reconnect or try again later. + """), + dismissButton: .default(Text("OK"), action: { + model.isPresentingNetworkErrorAlert = false + }) + ) + }) } ToolbarItem(placement: .status) { if let selectedPost = model.selectedPost { @@ -93,33 +104,6 @@ struct ContentView: View { .foregroundColor(.secondary) } .environmentObject(model) - .alert(isPresented: $model.isPresentingDeleteAlert) { - Alert( - title: Text("Delete Post?"), - message: Text("This action cannot be undone."), - primaryButton: .destructive(Text("Delete"), action: { - if let postToDelete = model.postToDelete { - model.selectedPost = nil - DispatchQueue.main.async { - model.posts.remove(postToDelete) - } - model.postToDelete = nil - } - }), - secondaryButton: .cancel() { - model.postToDelete = nil - } - ) - } - .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: { - Alert( - title: Text("Connection Error"), - message: Text("There is no internet connection at the moment. Please reconnect or try again later"), - dismissButton: .default(Text("OK"), action: { - model.isPresentingNetworkErrorAlert = false - }) - ) - }) #if os(iOS) EmptyView() @@ -131,6 +115,15 @@ struct ContentView: View { .environmentObject(model) } ) + .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: { + Alert( + title: Text("Connection Error"), + message: Text("There is no internet connection at the moment. Please reconnect or try again later."), + dismissButton: .default(Text("OK"), action: { + model.isPresentingNetworkErrorAlert = false + }) + ) + }) #endif } } diff --git a/Shared/PostList/PostListFilteredView.swift b/Shared/PostList/PostListFilteredView.swift index 899eb74..04f9eaa 100644 --- a/Shared/PostList/PostListFilteredView.swift +++ b/Shared/PostList/PostListFilteredView.swift @@ -86,6 +86,24 @@ struct PostListFilteredView: View { } }) } + .alert(isPresented: $model.isPresentingDeleteAlert) { + Alert( + title: Text("Delete Post?"), + message: Text("This action cannot be undone."), + primaryButton: .destructive(Text("Delete"), action: { + if let postToDelete = model.postToDelete { + model.selectedPost = nil + DispatchQueue.main.async { + model.posts.remove(postToDelete) + } + model.postToDelete = nil + } + }), + secondaryButton: .cancel() { + model.postToDelete = nil + } + ) + } .onAppear(perform: { self.postCount = fetchRequest.wrappedValue.count }) @@ -104,6 +122,7 @@ struct PostListFilteredView: View { func delete(_ post: WFAPost) { DispatchQueue.main.async { + model.selectedPost = nil model.posts.remove(post) } } From 28d3b6f8313aa9af0a0251529d0722d3d08a320b Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Thu, 26 Nov 2020 17:01:33 -0500 Subject: [PATCH 13/21] Make sure to always clear the last draft when we unset the selectedPost --- Shared/Navigation/ContentView.swift | 4 +++- Shared/PostList/PostListFilteredView.swift | 6 +++++- Shared/PostList/PostListView.swift | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 5ed54b7..d8c908b 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -118,7 +118,9 @@ struct ContentView: View { .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: { Alert( title: Text("Connection Error"), - message: Text("There is no internet connection at the moment. Please reconnect or try again later."), + message: Text(""" + There is no internet connection at the moment. Please reconnect or try again later. + """), dismissButton: .default(Text("OK"), action: { model.isPresentingNetworkErrorAlert = false }) diff --git a/Shared/PostList/PostListFilteredView.swift b/Shared/PostList/PostListFilteredView.swift index 04f9eaa..7df2c7c 100644 --- a/Shared/PostList/PostListFilteredView.swift +++ b/Shared/PostList/PostListFilteredView.swift @@ -94,6 +94,7 @@ struct PostListFilteredView: View { if let postToDelete = model.postToDelete { model.selectedPost = nil DispatchQueue.main.async { + model.editor.clearLastDraft() model.posts.remove(postToDelete) } model.postToDelete = nil @@ -122,7 +123,10 @@ struct PostListFilteredView: View { func delete(_ post: WFAPost) { DispatchQueue.main.async { - model.selectedPost = nil + if post == model.selectedPost { + model.selectedPost = nil + model.editor.clearLastDraft() + } model.posts.remove(post) } } diff --git a/Shared/PostList/PostListView.swift b/Shared/PostList/PostListView.swift index ffc545b..2fb4b7a 100644 --- a/Shared/PostList/PostListView.swift +++ b/Shared/PostList/PostListView.swift @@ -86,6 +86,12 @@ struct PostListView: View { ) ) .navigationSubtitle(postCount == 1 ? "\(postCount) post" : "\(postCount) posts") + .onChange(of: selectedCollection, perform: { _ in + DispatchQueue.main.async { + self.model.selectedPost = nil + self.model.editor.clearLastDraft() + } + }) #endif } } From 3114d037b3d77fbe099c55531c3e8b87918ecbcf Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Fri, 27 Nov 2020 11:02:18 -0500 Subject: [PATCH 14/21] Refactor active-post toolbar buttons into extracted view --- Shared/Navigation/ContentView.swift | 15 +---------- .../project.pbxproj | 12 +++++++++ macOS/Navigation/ActivePostToolbarView.swift | 25 +++++++++++++++++++ 3 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 macOS/Navigation/ActivePostToolbarView.swift diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index d8c908b..ab1cd05 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -77,22 +77,9 @@ struct ContentView: View { ) }) } - ToolbarItem(placement: .status) { - if let selectedPost = model.selectedPost { - PostEditorStatusToolbarView(post: selectedPost) - } - } ToolbarItemGroup(placement: .primaryAction) { if let selectedPost = model.selectedPost { - Button(action: { - DispatchQueue.main.async { - LocalStorageManager().saveContext() - model.publish(post: selectedPost) - } - }, label: { Image(systemName: "paperplane") }) - .disabled(selectedPost.body.isEmpty || selectedPost.status == PostStatus.published.rawValue) - Button(action: {}, label: { Image(systemName: "square.and.arrow.up") }) - .disabled(selectedPost.status == PostStatus.local.rawValue) + ActivePostToolbarView(activePost: selectedPost) } } } diff --git a/WriteFreely-MultiPlatform.xcodeproj/project.pbxproj b/WriteFreely-MultiPlatform.xcodeproj/project.pbxproj index 6829399..489cd38 100644 --- a/WriteFreely-MultiPlatform.xcodeproj/project.pbxproj +++ b/WriteFreely-MultiPlatform.xcodeproj/project.pbxproj @@ -62,6 +62,7 @@ 17B996D92502D23E0017B536 /* WFAPost+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B996D62502D23E0017B536 /* WFAPost+CoreDataClass.swift */; }; 17B996DA2502D23E0017B536 /* WFAPost+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B996D72502D23E0017B536 /* WFAPost+CoreDataProperties.swift */; }; 17B996DB2502D23E0017B536 /* WFAPost+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B996D72502D23E0017B536 /* WFAPost+CoreDataProperties.swift */; }; + 17BC618A25715318003363CA /* ActivePostToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17BC617825715068003363CA /* ActivePostToolbarView.swift */; }; 17C42E622507D8E600072984 /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E612507D8E600072984 /* PostStatus.swift */; }; 17C42E632507D8E600072984 /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E612507D8E600072984 /* PostStatus.swift */; }; 17C42E652509237800072984 /* PostListFilteredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C42E642509237800072984 /* PostListFilteredView.swift */; }; @@ -151,6 +152,7 @@ 17B5103A2515448D00E9631F /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; 17B996D62502D23E0017B536 /* WFAPost+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WFAPost+CoreDataClass.swift"; sourceTree = SOURCE_ROOT; }; 17B996D72502D23E0017B536 /* WFAPost+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WFAPost+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; }; + 17BC617825715068003363CA /* ActivePostToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivePostToolbarView.swift; sourceTree = ""; }; 17C42E612507D8E600072984 /* PostStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostStatus.swift; sourceTree = ""; }; 17C42E642509237800072984 /* PostListFilteredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostListFilteredView.swift; sourceTree = ""; }; 17C42E6F250AA12200072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+ExecuteAndMergeChanges.swift"; sourceTree = ""; }; @@ -316,6 +318,14 @@ path = PostEditor; sourceTree = ""; }; + 17BC617725715042003363CA /* Navigation */ = { + isa = PBXGroup; + children = ( + 17BC617825715068003363CA /* ActivePostToolbarView.swift */, + ); + path = Navigation; + sourceTree = ""; + }; 17D4F3722514EE4400517CE6 /* Resources */ = { isa = PBXGroup; children = ( @@ -393,6 +403,7 @@ children = ( 17DF329224C87D3500BCE2E3 /* Info.plist */, 17DF329324C87D3500BCE2E3 /* macOS.entitlements */, + 17BC617725715042003363CA /* Navigation */, 17A67CAC251A5D8D002F163D /* PostEditor */, 17A5388924DDA50500DEFF9A /* Settings */, 17B5103A2515448D00E9631F /* Credits.rtf */, @@ -754,6 +765,7 @@ 1753F6AC24E431CC00309365 /* MacPreferencesView.swift in Sources */, 1756DC0424FEE18400207AB8 /* WFACollection+CoreDataProperties.swift in Sources */, 17B996DB2502D23E0017B536 /* WFAPost+CoreDataProperties.swift in Sources */, + 17BC618A25715318003363CA /* ActivePostToolbarView.swift in Sources */, 171BFDFB24D4AF8300888236 /* CollectionListView.swift in Sources */, 17A67CAF251A5DD7002F163D /* PostEditorView.swift in Sources */, 17DF32AB24C87D3500BCE2E3 /* WriteFreely_MultiPlatformApp.swift in Sources */, diff --git a/macOS/Navigation/ActivePostToolbarView.swift b/macOS/Navigation/ActivePostToolbarView.swift new file mode 100644 index 0000000..58e223c --- /dev/null +++ b/macOS/Navigation/ActivePostToolbarView.swift @@ -0,0 +1,25 @@ +import SwiftUI + +struct ActivePostToolbarView: View { + @EnvironmentObject var model: WriteFreelyModel + @ObservedObject var activePost: WFAPost + + var body: some View { + HStack(spacing: 16) { + PostEditorStatusToolbarView(post: activePost) + HStack(spacing: 4) { + Button(action: { publishPost(activePost) }, label: { Image(systemName: "paperplane") }) + .disabled(activePost.body.isEmpty || activePost.status == PostStatus.published.rawValue) + Button(action: {}, label: { Image(systemName: "square.and.arrow.up") }) + .disabled(activePost.status == PostStatus.local.rawValue) + } + } + } + + private func publishPost(_ post: WFAPost) { + DispatchQueue.main.async { + LocalStorageManager().saveContext() + model.publish(post: post) + } + } +} From 1c9ca0552764360c910e5b50c4a1a1b5b6b45ea3 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Fri, 27 Nov 2020 16:25:49 -0500 Subject: [PATCH 15/21] Move clear-last-draft call to PostEditor.onDisappear --- Shared/PostList/PostListView.swift | 6 ------ .../angelo.xcuserdatad/xcschemes/xcschememanagement.plist | 4 ++-- macOS/PostEditor/PostEditorView.swift | 3 +++ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Shared/PostList/PostListView.swift b/Shared/PostList/PostListView.swift index 2fb4b7a..ffc545b 100644 --- a/Shared/PostList/PostListView.swift +++ b/Shared/PostList/PostListView.swift @@ -86,12 +86,6 @@ struct PostListView: View { ) ) .navigationSubtitle(postCount == 1 ? "\(postCount) post" : "\(postCount) posts") - .onChange(of: selectedCollection, perform: { _ in - DispatchQueue.main.async { - self.model.selectedPost = nil - self.model.editor.clearLastDraft() - } - }) #endif } } diff --git a/WriteFreely-MultiPlatform.xcodeproj/xcuserdata/angelo.xcuserdatad/xcschemes/xcschememanagement.plist b/WriteFreely-MultiPlatform.xcodeproj/xcuserdata/angelo.xcuserdatad/xcschemes/xcschememanagement.plist index 2723ebe..6cd8075 100644 --- a/WriteFreely-MultiPlatform.xcodeproj/xcuserdata/angelo.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/WriteFreely-MultiPlatform.xcodeproj/xcuserdata/angelo.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ WriteFreely-MultiPlatform (iOS).xcscheme_^#shared#^_ orderHint - 0 + 1 WriteFreely-MultiPlatform (macOS).xcscheme_^#shared#^_ orderHint - 1 + 0 diff --git a/macOS/PostEditor/PostEditorView.swift b/macOS/PostEditor/PostEditorView.swift index 08d0b9a..4b7ab68 100644 --- a/macOS/PostEditor/PostEditorView.swift +++ b/macOS/PostEditor/PostEditorView.swift @@ -39,6 +39,9 @@ struct PostEditorView: View { } }) .onDisappear(perform: { + DispatchQueue.main.async { + model.editor.clearLastDraft() + } if post.title.count == 0 && post.body.count == 0 && post.status == PostStatus.local.rawValue From 24897aae937ffd768f20706c864682863565385a Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 1 Dec 2020 09:38:46 -0500 Subject: [PATCH 16/21] Update menu item from "New Local Draft" to "New Post" --- Shared/WriteFreely_MultiPlatformApp.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index f0918c5..d35aa58 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -25,7 +25,7 @@ struct WriteFreely_MultiPlatformApp: App { } .commands { CommandGroup(replacing: .newItem, addition: { - Button("New Local Draft") { + Button("New Post") { createNewLocalPost() } .keyboardShortcut("n", modifiers: [.command]) From 7902bff33df8f304e1d5cea6f95c3e56e4889285 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 1 Dec 2020 09:53:09 -0500 Subject: [PATCH 17/21] Remove reload button from toolbar --- Shared/Navigation/ContentView.swift | 37 ++++++++--------------- Shared/WriteFreely_MultiPlatformApp.swift | 3 +- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index ab1cd05..ce8f253 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -2,7 +2,6 @@ import SwiftUI struct ContentView: View { @EnvironmentObject var model: WriteFreelyModel - @Binding var sidebarIsHidden: Bool var body: some View { NavigationView { @@ -14,7 +13,6 @@ struct ContentView: View { NSApp.keyWindow?.contentViewController?.tryToPerform( #selector(NSSplitViewController.toggleSidebar(_:)), with: nil ) - withAnimation { self.sidebarIsHidden.toggle() } }, label: { Image(systemName: "sidebar.left") } ) @@ -55,31 +53,20 @@ struct ContentView: View { #if os(macOS) PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) .toolbar { - ToolbarItem(placement: .navigation) { - Button(action: { - DispatchQueue.main.async { - model.fetchUserCollections() - model.fetchUserPosts() - } - }, label: { Image(systemName: "arrow.clockwise") }) - .disabled(!model.account.isLoggedIn) - .padding(.leading, sidebarIsHidden ? 8 : 0) - .animation(.linear) - .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: { - Alert( - title: Text("Connection Error"), - message: Text(""" - There is no internet connection at the moment. Please reconnect or try again later. - """), - dismissButton: .default(Text("OK"), action: { - model.isPresentingNetworkErrorAlert = false - }) - ) - }) - } ToolbarItemGroup(placement: .primaryAction) { if let selectedPost = model.selectedPost { ActivePostToolbarView(activePost: selectedPost) + .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: { + Alert( + title: Text("Connection Error"), + message: Text(""" + There is no internet connection at the moment. Please reconnect or try again later. + """), + dismissButton: .default(Text("OK"), action: { + model.isPresentingNetworkErrorAlert = false + }) + ) + }) } } } @@ -122,7 +109,7 @@ struct ContentView_Previews: PreviewProvider { let context = LocalStorageManager.persistentContainer.viewContext let model = WriteFreelyModel() - return ContentView(sidebarIsHidden: .constant(false)) + return ContentView() .environment(\.managedObjectContext, context) .environmentObject(model) } diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index d35aa58..a8ecb42 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -3,7 +3,6 @@ import SwiftUI @main struct WriteFreely_MultiPlatformApp: App { @StateObject private var model = WriteFreelyModel() - @State private var sidebarIsHidden: Bool = false #if os(macOS) @State private var selectedTab = 0 @@ -11,7 +10,7 @@ struct WriteFreely_MultiPlatformApp: App { var body: some Scene { WindowGroup { - ContentView(sidebarIsHidden: $sidebarIsHidden) + ContentView() .onAppear(perform: { if let lastDraft = model.editor.fetchLastDraftFromUserDefaults() { self.model.selectedPost = lastDraft From c1be3276945d5d8cfd80389173ccfc7bd444fc50 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 1 Dec 2020 09:55:11 -0500 Subject: [PATCH 18/21] Use native SwiftUI SidebarCommands() for toggle-sidebar menu item --- Shared/WriteFreely_MultiPlatformApp.swift | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index a8ecb42..a70e0d5 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -40,15 +40,7 @@ struct WriteFreely_MultiPlatformApp: App { .keyboardShortcut("r", modifiers: [.command]) } #if os(macOS) - CommandGroup(after: .sidebar) { - Button("Toggle Sidebar") { - NSApp.keyWindow?.contentViewController?.tryToPerform( - #selector(NSSplitViewController.toggleSidebar(_:)), with: nil - ) - withAnimation { self.sidebarIsHidden.toggle() } - } - .keyboardShortcut("s", modifiers: [.command, .option]) - } + SidebarCommands() #endif } From 68fd0c91e7da1a9e0fd635e57450520f3d9bfa00 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 1 Dec 2020 09:58:04 -0500 Subject: [PATCH 19/21] Make cancel the default action in the delete-confirmation alert --- Shared/PostList/PostListFilteredView.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Shared/PostList/PostListFilteredView.swift b/Shared/PostList/PostListFilteredView.swift index 7df2c7c..cc65779 100644 --- a/Shared/PostList/PostListFilteredView.swift +++ b/Shared/PostList/PostListFilteredView.swift @@ -90,7 +90,10 @@ struct PostListFilteredView: View { Alert( title: Text("Delete Post?"), message: Text("This action cannot be undone."), - primaryButton: .destructive(Text("Delete"), action: { + primaryButton: .cancel() { + model.postToDelete = nil + }, + secondaryButton: .destructive(Text("Delete"), action: { if let postToDelete = model.postToDelete { model.selectedPost = nil DispatchQueue.main.async { @@ -99,10 +102,7 @@ struct PostListFilteredView: View { } model.postToDelete = nil } - }), - secondaryButton: .cancel() { - model.postToDelete = nil - } + }) ) } .onAppear(perform: { From 43088fdc44582a5a324aaf1206ea403c46d431a4 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 1 Dec 2020 10:01:56 -0500 Subject: [PATCH 20/21] Swap order of share and publish buttons in toolbar --- macOS/Navigation/ActivePostToolbarView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macOS/Navigation/ActivePostToolbarView.swift b/macOS/Navigation/ActivePostToolbarView.swift index 58e223c..68b9d93 100644 --- a/macOS/Navigation/ActivePostToolbarView.swift +++ b/macOS/Navigation/ActivePostToolbarView.swift @@ -8,10 +8,10 @@ struct ActivePostToolbarView: View { HStack(spacing: 16) { PostEditorStatusToolbarView(post: activePost) HStack(spacing: 4) { - Button(action: { publishPost(activePost) }, label: { Image(systemName: "paperplane") }) - .disabled(activePost.body.isEmpty || activePost.status == PostStatus.published.rawValue) Button(action: {}, label: { Image(systemName: "square.and.arrow.up") }) .disabled(activePost.status == PostStatus.local.rawValue) + Button(action: { publishPost(activePost) }, label: { Image(systemName: "paperplane") }) + .disabled(activePost.body.isEmpty || activePost.status == PostStatus.published.rawValue) } } } From eff423f79ea4b74814504887b4735ff0bdd4fa85 Mon Sep 17 00:00:00 2001 From: Angelo Stavrow Date: Tue, 1 Dec 2020 11:24:55 -0500 Subject: [PATCH 21/21] Change "Reload From Server" File menu item to read "Refresh Posts" --- Shared/WriteFreely_MultiPlatformApp.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift index a70e0d5..4aeb385 100644 --- a/Shared/WriteFreely_MultiPlatformApp.swift +++ b/Shared/WriteFreely_MultiPlatformApp.swift @@ -30,7 +30,7 @@ struct WriteFreely_MultiPlatformApp: App { .keyboardShortcut("n", modifiers: [.command]) }) CommandGroup(after: .newItem) { - Button("Reload From Server") { + Button("Refresh Posts") { DispatchQueue.main.async { model.fetchUserCollections() model.fetchUserPosts()