diff --git a/macOS/Navigation/ActivePostToolbarView.swift b/macOS/Navigation/ActivePostToolbarView.swift index 15955f2..1c2c5fd 100644 --- a/macOS/Navigation/ActivePostToolbarView.swift +++ b/macOS/Navigation/ActivePostToolbarView.swift @@ -1,141 +1,140 @@ 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(model.selectedPost?.body.isEmpty ?? true) .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) { + .background( 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 = model.selectedPost?.postId else { return [] } var urlString: String if let postSlug = model.selectedPost?.slug, let postCollectionAlias = model.selectedPost?.collectionAlias { // This post is in a collection, so share the URL as baseURL/postSlug let urls = collections.filter { $0.alias == postCollectionAlias } let baseURL = urls.first?.url ?? "\(model.account.server)/\(postCollectionAlias)/" urlString = "\(baseURL)\(postSlug)" } else { - // This is a draft post, sho share the URL as server/postID + // This is a draft post, so share the URL as server/postID urlString = "\(model.account.server)/\(postId)" } guard let data = URL(string: urlString) else { return [] } return [data as NSURL] } private func publishPost(_ post: WFAPost) { if post != model.selectedPost { return } DispatchQueue.main.async { LocalStorageManager.standard.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) } } diff --git a/macOS/PostEditor/PostEditorSharingPicker.swift b/macOS/PostEditor/PostEditorSharingPicker.swift index 02f7c96..6a5cc33 100644 --- a/macOS/PostEditor/PostEditorSharingPicker.swift +++ b/macOS/PostEditor/PostEditorSharingPicker.swift @@ -1,39 +1,42 @@ import SwiftUI struct PostEditorSharingPicker: NSViewRepresentable { @Binding var isPresented: Bool var sharingItems: [Any] = [] func makeNSView(context: Context) -> some NSView { let view = NSView() - let picker = NSSharingServicePicker(items: sharingItems) - picker.delegate = context.coordinator - - DispatchQueue.main.async { - picker.show(relativeTo: .zero, of: view, preferredEdge: .minY) - } return view } func updateNSView(_ nsView: NSViewType, context: Context) { + if isPresented { + let picker = NSSharingServicePicker(items: sharingItems) + picker.delegate = context.coordinator + + DispatchQueue.main.async { + picker.show(relativeTo: .zero, of: nsView, preferredEdge: .minY) + } + } } func makeCoordinator() -> Coordinator { Coordinator(owner: self) } class Coordinator: NSObject, NSSharingServicePickerDelegate { let owner: PostEditorSharingPicker + init(owner: PostEditorSharingPicker) { self.owner = owner } func sharingServicePicker( _ sharingServicePicker: NSSharingServicePicker, didChoose service: NSSharingService? ) { sharingServicePicker.delegate = nil self.owner.isPresented = false } } }