WIP: add Quick Look preview groundwork
This commit is contained in:
@@ -182,6 +182,23 @@ final class ClipboardCacheService {
|
||||
}
|
||||
}
|
||||
|
||||
func temporaryPreviewURL(for item: ClipboardItem) -> URL? {
|
||||
switch item.kind {
|
||||
case .file:
|
||||
let urls = FilePayload.urls(from: item.payload)
|
||||
return urls.first { fileManager.fileExists(atPath: $0.path) }
|
||||
case .text, .unknown:
|
||||
let text = item.payload.clipboardTrimmed.isEmpty ? item.displayText : item.payload
|
||||
guard !text.clipboardTrimmed.isEmpty else { return nil }
|
||||
return writeTemporaryCopy(data: Data(text.utf8), id: item.id, fileExtension: "txt")
|
||||
case .url:
|
||||
guard let data = webLocationData(for: item.payload) else { return nil }
|
||||
return writeTemporaryCopy(data: data, id: item.id, fileExtension: "webloc")
|
||||
case .image, .pdf, .audio, .richText:
|
||||
return temporaryReadableURL(for: item)
|
||||
}
|
||||
}
|
||||
|
||||
func encryptCachedReferencesIfNeeded(for items: [ClipboardItem]) {
|
||||
queue.async { [weak self] in
|
||||
guard let self else { return }
|
||||
@@ -320,6 +337,16 @@ final class ClipboardCacheService {
|
||||
}
|
||||
}
|
||||
|
||||
private func webLocationData(for value: String) -> Data? {
|
||||
let trimmed = value.clipboardTrimmed
|
||||
guard !trimmed.isEmpty else { return nil }
|
||||
return try? PropertyListSerialization.data(
|
||||
fromPropertyList: ["URL": trimmed],
|
||||
format: .xml,
|
||||
options: 0
|
||||
)
|
||||
}
|
||||
|
||||
private func removeTemporaryPreviewFiles() {
|
||||
guard fileManager.fileExists(atPath: temporaryPreviewDirectory.path) else {
|
||||
return
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import AppKit
|
||||
import QuickLook
|
||||
|
||||
struct ClipboardPanelAnimationProfile {
|
||||
let showDuration: TimeInterval
|
||||
@@ -15,10 +16,11 @@ struct ClipboardPanelReflowPlan {
|
||||
enum ClipboardPanelShortcutAction: Equatable {
|
||||
case copy
|
||||
case open
|
||||
case preview
|
||||
case reveal
|
||||
}
|
||||
|
||||
final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
final class ClipboardPanelController: NSObject, NSWindowDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate {
|
||||
private enum Animation {
|
||||
static let showDuration: TimeInterval = 0.16
|
||||
static let hideDuration: TimeInterval = 0.12
|
||||
@@ -44,6 +46,7 @@ final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
private let preferredScreenProvider: () -> NSScreen?
|
||||
private let openSettings: () -> Void
|
||||
private var isAnimating = false
|
||||
private var quickLookURL: URL?
|
||||
private var screenParametersObserver: NSObjectProtocol?
|
||||
private static let collectionShortcuts: [UInt16: ClipboardSortMode] = [
|
||||
18: .mostRecent,
|
||||
@@ -82,7 +85,8 @@ final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
panelView = ClipboardPanelView(
|
||||
viewModel: viewModel,
|
||||
onClose: { [weak self] in self?.hide() },
|
||||
onSettings: { [weak self] in self?.openSettings() }
|
||||
onSettings: { [weak self] in self?.openSettings() },
|
||||
onPreview: { [weak self] in self?.previewSelected() }
|
||||
)
|
||||
|
||||
let contentSize = NSSize(width: 1200, height: 420)
|
||||
@@ -333,6 +337,9 @@ final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
case 53:
|
||||
self.hide()
|
||||
return nil
|
||||
case 49:
|
||||
self.previewSelected()
|
||||
return nil
|
||||
case 36:
|
||||
self.viewModel.pasteSelected()
|
||||
return nil
|
||||
@@ -360,11 +367,26 @@ final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
viewModel.copySelected()
|
||||
case .open:
|
||||
viewModel.openSelected()
|
||||
case .preview:
|
||||
previewSelected()
|
||||
case .reveal:
|
||||
viewModel.revealSelected()
|
||||
}
|
||||
}
|
||||
|
||||
private func previewSelected() {
|
||||
guard let url = viewModel.previewURLForSelected() else { return }
|
||||
quickLookURL = url
|
||||
guard let previewPanel = QLPreviewPanel.shared() else {
|
||||
NSWorkspace.shared.open(url)
|
||||
return
|
||||
}
|
||||
previewPanel.dataSource = self
|
||||
previewPanel.delegate = self
|
||||
previewPanel.currentPreviewItemIndex = 0
|
||||
previewPanel.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
|
||||
private func shouldHandlePanelKeyEvent(_ event: NSEvent) -> Bool {
|
||||
shouldHandlePanelKeyEvent(event, allowSearchFieldEditing: false)
|
||||
}
|
||||
@@ -399,6 +421,8 @@ final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
return .copy
|
||||
case 31:
|
||||
return .open
|
||||
case 16:
|
||||
return .preview
|
||||
case 15:
|
||||
return .reveal
|
||||
default:
|
||||
@@ -406,6 +430,14 @@ final class ClipboardPanelController: NSObject, NSWindowDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func numberOfPreviewItems(in panel: QLPreviewPanel!) -> Int {
|
||||
quickLookURL == nil ? 0 : 1
|
||||
}
|
||||
|
||||
func previewPanel(_ panel: QLPreviewPanel!, previewItemAt index: Int) -> QLPreviewItem! {
|
||||
quickLookURL as NSURL?
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
var debugPanelFrame: NSRect {
|
||||
panel.frame
|
||||
|
||||
@@ -168,6 +168,15 @@ final class ClipboardPanelViewModel {
|
||||
return pasteService.pasteboardWriters(for: visibleItems[index])
|
||||
}
|
||||
|
||||
func previewURLForSelected() -> URL? {
|
||||
guard let item = selectedItem else { return nil }
|
||||
return previewURL(for: item)
|
||||
}
|
||||
|
||||
internal func previewURL(for item: ClipboardItem) -> URL? {
|
||||
cacheService.temporaryPreviewURL(for: item)
|
||||
}
|
||||
|
||||
func openSelected() {
|
||||
guard let item = selectedItem else { return }
|
||||
switch item.kind {
|
||||
|
||||
Reference in New Issue
Block a user