mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 23:24:32 +00:00
174 lines
7.1 KiB
Swift
174 lines
7.1 KiB
Swift
//
|
|
// NSItemProvider+LoadHelpers.swift
|
|
// DynamicIsland
|
|
//
|
|
// Ported shelf drop helpers from boringNotch.
|
|
//
|
|
|
|
import AppKit
|
|
import Foundation
|
|
import UniformTypeIdentifiers
|
|
|
|
extension NSItemProvider {
|
|
func extractItem() async -> URL? {
|
|
await loadFileURL(typeIdentifier: UTType.item.identifier)
|
|
}
|
|
|
|
/// Detects if this is a file dragged from the filesystem
|
|
func extractFileURL() async -> URL? {
|
|
if hasItemConformingToTypeIdentifier(UTType.fileURL.identifier) {
|
|
return await loadFileURL(typeIdentifier: UTType.fileURL.identifier)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Loads raw data for the given type identifier
|
|
func loadData() async -> Data? {
|
|
guard hasItemConformingToTypeIdentifier(UTType.data.identifier) else { return nil }
|
|
return await withCheckedContinuation { (cont: CheckedContinuation<Data?, Never>) in
|
|
loadItem(forTypeIdentifier: UTType.data.identifier, options: nil) { item, error in
|
|
if let error {
|
|
print("Error loading data for type \(UTType.data.identifier): \(error.localizedDescription)")
|
|
cont.resume(returning: nil)
|
|
return
|
|
}
|
|
if let url = item as? URL, let data = try? Data(contentsOf: url) {
|
|
if !url.absoluteString.contains("com.apple.SwiftUI.filePromises") {
|
|
cont.resume(returning: nil)
|
|
return
|
|
}
|
|
self.suggestedName = self.suggestedName ?? url.lastPathComponent
|
|
let fileManager = FileManager.default
|
|
let folderURL = url.deletingLastPathComponent()
|
|
do {
|
|
try fileManager.removeItem(at: url)
|
|
let contents = try fileManager.contentsOfDirectory(atPath: folderURL.path)
|
|
if contents.isEmpty {
|
|
try fileManager.removeItem(at: folderURL)
|
|
}
|
|
} catch {
|
|
print("Error: \(error.localizedDescription)")
|
|
}
|
|
cont.resume(returning: data)
|
|
} else if let data = item as? Data {
|
|
cont.resume(returning: data)
|
|
} else {
|
|
cont.resume(returning: nil)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Attempts to extract a URL (web link) from the provider
|
|
func extractURL() async -> URL? {
|
|
if hasItemConformingToTypeIdentifier(UTType.url.identifier) {
|
|
if let url = await loadURL(typeIdentifier: UTType.url.identifier) {
|
|
guard url.scheme != nil else { return nil }
|
|
return url
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func extractText() async -> String? {
|
|
let textTypes = [UTType.utf8PlainText.identifier, UTType.plainText.identifier]
|
|
for typeIdentifier in textTypes where hasItemConformingToTypeIdentifier(typeIdentifier) {
|
|
if let text = await loadText(typeIdentifier: typeIdentifier) {
|
|
return text
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Loads a file URL from the provider for the given type identifier.
|
|
func loadFileURL(typeIdentifier: String) async -> URL? {
|
|
await withCheckedContinuation { (cont: CheckedContinuation<URL?, Never>) in
|
|
loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, error in
|
|
if let error {
|
|
print("❌ Error loading item for type \(typeIdentifier): \(error.localizedDescription)")
|
|
cont.resume(returning: nil)
|
|
return
|
|
}
|
|
var resolvedURL: URL?
|
|
if let url = item as? URL {
|
|
resolvedURL = url
|
|
} else if let data = item as? Data {
|
|
if let string = String(data: data, encoding: .utf8) {
|
|
if let url = URL(string: string) {
|
|
resolvedURL = url
|
|
} else if string.hasPrefix("/") {
|
|
resolvedURL = URL(fileURLWithPath: string)
|
|
}
|
|
}
|
|
if resolvedURL == nil {
|
|
let bookmark = Bookmark(data: data)
|
|
resolvedURL = bookmark.resolveURL()
|
|
}
|
|
} else if let string = item as? String {
|
|
if let url = URL(string: string) {
|
|
resolvedURL = url
|
|
} else if string.hasPrefix("/") {
|
|
resolvedURL = URL(fileURLWithPath: string)
|
|
}
|
|
}
|
|
cont.resume(returning: resolvedURL)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Loads a URL from the provider for the given type identifier.
|
|
func loadURL(typeIdentifier: String) async -> URL? {
|
|
await withCheckedContinuation { (cont: CheckedContinuation<URL?, Never>) in
|
|
loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, error in
|
|
if error != nil {
|
|
cont.resume(returning: nil)
|
|
return
|
|
}
|
|
if let url = item as? URL {
|
|
cont.resume(returning: url)
|
|
} else if let data = item as? Data {
|
|
if let string = String(data: data, encoding: .utf8) {
|
|
if let url = URL(string: string) {
|
|
cont.resume(returning: url)
|
|
return
|
|
} else if string.hasPrefix("/") {
|
|
cont.resume(returning: URL(fileURLWithPath: string))
|
|
return
|
|
}
|
|
}
|
|
cont.resume(returning: nil)
|
|
} else if let string = item as? String {
|
|
if let url = URL(string: string) {
|
|
cont.resume(returning: url)
|
|
} else if string.hasPrefix("/") {
|
|
cont.resume(returning: URL(fileURLWithPath: string))
|
|
} else {
|
|
cont.resume(returning: nil)
|
|
}
|
|
} else {
|
|
cont.resume(returning: nil)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Loads text from the provider for the given type identifier.
|
|
func loadText(typeIdentifier: String) async -> String? {
|
|
await withCheckedContinuation { (cont: CheckedContinuation<String?, Never>) in
|
|
loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, error in
|
|
if error != nil {
|
|
cont.resume(returning: nil)
|
|
return
|
|
}
|
|
if let string = item as? String {
|
|
cont.resume(returning: string)
|
|
} else if let data = item as? Data,
|
|
let string = String(data: data, encoding: .utf8) {
|
|
cont.resume(returning: string)
|
|
} else {
|
|
cont.resume(returning: nil)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|