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 @@ -1,147 +1,140 @@ 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 ) withAnimation { self.sidebarIsHidden.toggle() } }, label: { Image(systemName: "sidebar.left") } ) Spacer() 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 { DispatchQueue.main.async { self.model.selectedPost = managedPost } } }, 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: { 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 + }) + ) + }) } 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) } } } #else PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) #endif Text("Select a post, or create a new local draft.") .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() .sheet( isPresented: $model.isPresentingSettingsView, onDismiss: { model.isPresentingSettingsView = false }, content: { SettingsView() .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 } } struct ContentView_Previews: PreviewProvider { static var previews: some View { let context = LocalStorageManager.persistentContainer.viewContext let model = WriteFreelyModel() return ContentView(sidebarIsHidden: .constant(false)) .environment(\.managedObjectContext, context) .environmentObject(model) } } 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 @@ -1,116 +1,135 @@ import SwiftUI struct PostListFilteredView: View { @EnvironmentObject var model: WriteFreelyModel @Binding var postCount: Int @FetchRequest(entity: WFACollection.entity(), sortDescriptors: []) var collections: FetchedResults var fetchRequest: FetchRequest var showAllPosts: Bool init(filter: String?, showAllPosts: Bool, postCount: Binding) { self.showAllPosts = showAllPosts if showAllPosts { fetchRequest = FetchRequest( entity: WFAPost.entity(), sortDescriptors: [NSSortDescriptor(key: "createdDate", ascending: false)] ) } else { if let filter = filter { fetchRequest = FetchRequest( entity: WFAPost.entity(), sortDescriptors: [NSSortDescriptor(key: "createdDate", ascending: false)], predicate: NSPredicate(format: "collectionAlias == %@", filter) ) } else { fetchRequest = FetchRequest( entity: WFAPost.entity(), sortDescriptors: [NSSortDescriptor(key: "createdDate", ascending: false)], predicate: NSPredicate(format: "collectionAlias == nil") ) } } _postCount = postCount } var body: some View { #if os(iOS) List { ForEach(fetchRequest.wrappedValue, id: \.self) { post in NavigationLink( destination: PostEditorView(post: post), tag: post, selection: $model.selectedPost ) { if showAllPosts { if let collection = collections.filter { $0.alias == post.collectionAlias }.first { PostCellView(post: post, collectionName: collection.title) } else { let collectionName = model.account.server == "https://write.as" ? "Anonymous" : "Drafts" PostCellView(post: post, collectionName: collectionName) } } else { PostCellView(post: post) } } .deleteDisabled(post.status != PostStatus.local.rawValue) } .onDelete(perform: { indexSet in for index in indexSet { let post = fetchRequest.wrappedValue[index] delete(post) } }) } .onAppear(perform: { self.postCount = fetchRequest.wrappedValue.count }) .onChange(of: fetchRequest.wrappedValue.count, perform: { value in self.postCount = value }) #else List { ForEach(fetchRequest.wrappedValue, id: \.self) { post in NavigationLink( destination: PostEditorView(post: post), tag: post, selection: $model.selectedPost ) { PostCellView(post: post) } .deleteDisabled(post.status != PostStatus.local.rawValue) } .onDelete(perform: { indexSet in for index in indexSet { let post = fetchRequest.wrappedValue[index] delete(post) } }) } + .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 }) .onChange(of: fetchRequest.wrappedValue.count, perform: { value in self.postCount = value }) .onDeleteCommand(perform: { guard let selectedPost = model.selectedPost else { return } if selectedPost.status == PostStatus.local.rawValue { model.postToDelete = selectedPost model.isPresentingDeleteAlert = true } }) #endif } func delete(_ post: WFAPost) { DispatchQueue.main.async { + model.selectedPost = nil model.posts.remove(post) } } } struct PostListFilteredView_Previews: PreviewProvider { static var previews: some View { return PostListFilteredView(filter: nil, showAllPosts: false, postCount: .constant(999)) } }