diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index 327cdfa..e8cd97c 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -1,106 +1,108 @@ import SwiftUI struct ContentView: View { @EnvironmentObject var model: WriteFreelyModel 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") } ) + .help("Toggle the sidebar's visibility.") 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") }) + .help("Create a new local draft.") } #else SidebarView() #endif #if os(macOS) ZStack { PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) if model.isProcessingRequest { ZStack { Color(NSColor.controlBackgroundColor).opacity(0.75) ProgressView() } } } #else PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn) #endif Text("Select a post, or create a new local draft.") .foregroundColor(.secondary) } .environmentObject(model) #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() .environment(\.managedObjectContext, context) .environmentObject(model) } } diff --git a/macOS/Navigation/ActivePostToolbarView.swift b/macOS/Navigation/ActivePostToolbarView.swift index 57f8b73..20334f4 100644 --- a/macOS/Navigation/ActivePostToolbarView.swift +++ b/macOS/Navigation/ActivePostToolbarView.swift @@ -1,125 +1,128 @@ import SwiftUI struct ActivePostToolbarView: View { @EnvironmentObject var model: WriteFreelyModel @ObservedObject var activePost: WFAPost @State private var isPresentingSharingServicePicker: Bool = false @State private var selectedCollection: WFACollection? @FetchRequest( entity: WFACollection.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \WFACollection.title, ascending: true)] ) var collections: FetchedResults var body: some View { HStack { if model.account.isLoggedIn && activePost.status != PostStatus.local.rawValue && !(activePost.wasDeletedFromServer || activePost.hasNewerRemoteCopy) { Section(header: Text("Move To:")) { Picker(selection: $selectedCollection, label: Text("Move To…"), content: { Text("\(model.account.server == "https://write.as" ? "Anonymous" : "Drafts")") .tag(nil as WFACollection?) Divider() ForEach(collections) { collection in Text("\(collection.title)").tag(collection as WFACollection?) } }) } } PostEditorStatusToolbarView(post: activePost) .frame(minWidth: 50, alignment: .center) .layoutPriority(1) .padding(.horizontal) if activePost.status == PostStatus.local.rawValue { Menu(content: { Label("Publish To:", systemImage: "paperplane") Divider() Button(action: { if model.account.isLoggedIn { withAnimation { activePost.collectionAlias = nil publishPost(activePost) } } else { openSettingsWindow() } }, label: { Text("\(model.account.server == "https://write.as" ? "Anonymous" : "Drafts")") }) ForEach(collections) { collection in Button(action: { if model.account.isLoggedIn { withAnimation { activePost.collectionAlias = collection.alias publishPost(activePost) } } else { openSettingsWindow() } }, label: { Text("\(collection.title)") }) } }, label: { Label("Publish…", systemImage: "paperplane") }) .disabled(activePost.body.isEmpty) + .help("Publish the post to the web.\(model.account.isLoggedIn ? "" : " You must be logged in to do this.")") // swiftlint:disable:this line_length } else { HStack(spacing: 4) { Button( action: { self.isPresentingSharingServicePicker = true }, label: { Image(systemName: "square.and.arrow.up") } ) .disabled(activePost.status == PostStatus.local.rawValue) + .help("Copy the post's URL to your Mac's pasteboard.") .popover(isPresented: $isPresentingSharingServicePicker) { PostEditorSharingPicker( isPresented: $isPresentingSharingServicePicker, sharingItems: createPostUrl() ) .frame(width: .zero, height: .zero) } Button(action: { publishPost(activePost) }, label: { Image(systemName: "paperplane") }) .disabled(activePost.body.isEmpty || activePost.status == PostStatus.published.rawValue) + .help("Publish the post to the web.\(model.account.isLoggedIn ? "" : " You must be logged in to do this.")") // swiftlint:disable:this line_length } } } .onAppear(perform: { self.selectedCollection = collections.first { $0.alias == activePost.collectionAlias } }) .onChange(of: selectedCollection, perform: { [selectedCollection] newCollection in if activePost.collectionAlias == newCollection?.alias { return } else { withAnimation { activePost.collectionAlias = newCollection?.alias model.move(post: activePost, from: selectedCollection, to: newCollection) } } }) } private func createPostUrl() -> [Any] { guard let postId = activePost.postId else { return [] } guard let urlString = activePost.slug != nil ? "\(model.account.server)/\((activePost.collectionAlias)!)/\((activePost.slug)!)" : "\(model.account.server)/\((postId))" else { return [] } guard let data = URL(string: urlString) else { return [] } return [data as NSURL] } private func publishPost(_ post: WFAPost) { DispatchQueue.main.async { LocalStorageManager().saveContext() model.publish(post: post) } } private func openSettingsWindow() { guard let menuItem = NSApplication.shared.mainMenu?.item(at: 0)?.submenu?.item(at: 2) else { return } NSApplication.shared.sendAction(menuItem.action!, to: menuItem.target, from: nil) } }