mirror of
https://github.com/abue-ammar/tinycast.git
synced 2026-10-02 08:14:38 +08:00
Retain the picker, and one comment (#1195)
Apple documents no retention for show(relativeTo:of:preferredEdge:), so the sheet is held here rather than left to an unstated behaviour -- my own test showed it surviving, but a comment is not a contract. The share doc comment is one line now.
This commit is contained in:
@@ -8,6 +8,7 @@ final class FileSearchCoordinator {
|
||||
private let palette: PaletteState
|
||||
private let paletteCoordinator: PaletteCoordinator
|
||||
private let windowController: PaletteWindowController
|
||||
private var sharePicker: NSSharingServicePicker?
|
||||
private unowned let core: AppCore
|
||||
|
||||
init(
|
||||
@@ -62,6 +63,19 @@ final class FileSearchCoordinator {
|
||||
AppLauncher.showInFinder(result.url)
|
||||
}
|
||||
|
||||
/// macOS's own share sheet, anchored to the palette's trailing edge so the row stays beside it.
|
||||
func share(_ result: FileSearchResult) {
|
||||
guard let provider = NSItemProvider(contentsOf: result.url),
|
||||
let anchor = paletteCoordinator.anchorView
|
||||
else { return }
|
||||
let picker = NSSharingServicePicker(items: [provider])
|
||||
sharePicker = picker
|
||||
picker.show(
|
||||
relativeTo: CGRect(
|
||||
x: anchor.bounds.maxX, y: anchor.bounds.midY, width: 0, height: 0),
|
||||
of: anchor, preferredEdge: .maxX)
|
||||
}
|
||||
|
||||
func copyPath(_ result: FileSearchResult) {
|
||||
Paster.copyPlainText(result.id)
|
||||
core.showMessage("Copied path")
|
||||
|
||||
@@ -159,6 +159,9 @@ enum FileSearchActionsMenu {
|
||||
PopoverMenuItem(title: "Quick Look", systemImage: "eye", shortcut: "⌘Y") {
|
||||
vm.fileSearchQuickLook = true
|
||||
},
|
||||
PopoverMenuItem(title: "Share…", systemImage: "square.and.arrow.up") {
|
||||
coordinator.share(result)
|
||||
},
|
||||
PopoverMenuItem(
|
||||
title: "Copy File", systemImage: "doc.on.clipboard", startsSection: true,
|
||||
shortcut: "⇧⌘C"
|
||||
|
||||
@@ -39,6 +39,9 @@ final class PaletteCoordinator {
|
||||
|
||||
var panelFrame: CGRect? { windowController.visibleFrame }
|
||||
|
||||
/// The palette's own view, for AppKit UI anchored to it — a sharing picker, say.
|
||||
var anchorView: NSView? { windowController.anchorView }
|
||||
|
||||
/// The app an action acts on: the one displaced, else what a hotkey found frontmost.
|
||||
var targetApp: NSRunningApplication? {
|
||||
windowController.isVisible
|
||||
|
||||
@@ -50,6 +50,9 @@ final class PaletteWindowController: NSObject, NSWindowDelegate {
|
||||
/// Where the panel sits in screen coordinates, so an overlay drawn under it can avoid it.
|
||||
var visibleFrame: CGRect? { panel.flatMap { $0.isVisible ? $0.frame : nil } }
|
||||
|
||||
/// The palette's own view, for AppKit UI that must be anchored to it rather than drawn.
|
||||
var anchorView: NSView? { panel?.isVisible == true ? panel?.contentView : nil }
|
||||
|
||||
/// What the palette covered when it was summoned, for anything it expands into on dismissal.
|
||||
var previousTarget: InjectionTarget? {
|
||||
InjectionTarget.behindPalette(ownWindow: previousOwnWindow, app: previousApp)
|
||||
|
||||
@@ -41,6 +41,15 @@ feature is enabled in Settings.
|
||||
after the synchronous Spotlight call, so a late result cannot replace the newer query's rows. Editing
|
||||
the scopes or the patterns cancels the session for the same reason: a result found under the old
|
||||
rules must not land under the new ones.
|
||||
- **Share is the one system popover, and the palette stays up under it.** `AGENTS.md` keeps Tinycast's
|
||||
own dialogs because a question or a report is Tinycast's to word. A share sheet is neither: it is
|
||||
AirDrop, Mail and Messages, and re-drawing it would mean re-implementing the transports and losing
|
||||
whatever the system adds. So this row hands off, and the two rules it does keep are that the palette
|
||||
is never hidden and that the row stays visible beside the sheet — which is what anchoring to
|
||||
`PaletteWindowController.anchorView` buys. The picker is retained on the coordinator, because it
|
||||
dies with its last reference, and `NSItemProvider(contentsOf:)` failing (a file that vanished between
|
||||
the query and the keystroke) leaves the palette exactly as it was, which is the only failure this row
|
||||
can have.
|
||||
|
||||
## Query path
|
||||
|
||||
@@ -215,6 +224,7 @@ not outlive the window.
|
||||
| Open File / Open Folder | ↵ | `NSWorkspace`'s asynchronous configuration API; hides the palette without restoring focus, and reports a failure through the dialog controller |
|
||||
| Show in Finder | ⌘↵ | reveals and dismisses |
|
||||
| Quick Look | ⌘Y | the in-panel overlay above |
|
||||
| Share… | — | `NSSharingServicePicker`, anchored to the palette's trailing edge so the row it was opened from stays visible beside it. Escape or a click elsewhere dismisses it, and the palette is never hidden, so the flow returns to the same row. There is no chord: the destinations are the system's, and it is the only place a system popover is right |
|
||||
| Copy File | ⇧⌘C | the file itself on the pasteboard through `PasteboardFiles.write`, which declares `.fileURL` and the path as `.string` |
|
||||
| Copy Name | ⌥⌘C | through `Paster`, palette stays open |
|
||||
| Copy Path | ⌃⌘C | the standardized path, palette stays open |
|
||||
|
||||
Reference in New Issue
Block a user