Restored files from old Mac, force pushing

This commit is contained in:
Hariharan Mudaliar 2025-07-13 20:26:03 +05:30
commit 5040381840
126 changed files with 10431 additions and 67 deletions

View file

@ -0,0 +1,40 @@
//
// AirDrop.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/7.
//
import Cocoa
class AirDrop: NSObject, NSSharingServiceDelegate {
let files: [URL]
init(files: [URL]) {
self.files = files
super.init()
}
func begin() {
do {
try sendEx(files)
} catch {
NSAlert.popError(error)
}
}
private func sendEx(_ files: [URL]) throws {
guard let service = NSSharingService(named: .sendViaAirDrop) else {
throw NSError(domain: "AirDrop", code: 1, userInfo: [
NSLocalizedDescriptionKey: NSLocalizedString("AirDrop service not available", comment: ""),
])
}
guard service.canPerform(withItems: files) else {
throw NSError(domain: "AirDrop", code: 2, userInfo: [
NSLocalizedDescriptionKey: NSLocalizedString("AirDrop service not available", comment: ""),
])
}
service.delegate = self
service.perform(withItems: files)
}
}

View file

@ -0,0 +1,70 @@
//
// AirDrop+View.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/8.
//
import SwiftUI
import UniformTypeIdentifiers
struct AirDropView: View {
@EnvironmentObject var vm: DynamicIslandViewModel
@State var trigger: UUID = .init()
@State var targeting = false
var body: some View {
dropArea
.onDrop(of: [.data], isTargeted: $vm.dropZoneTargeting) { providers in
trigger = .init()
vm.dropEvent = true
DispatchQueue.global().async { beginDrop(providers) }
return true
}
}
var dropArea: some View {
Rectangle()
.fill(.white.opacity(0.1))
.opacity(0.5)
.clipShape(RoundedRectangle(cornerRadius: 10))
.overlay { dropLabel }
.aspectRatio(1, contentMode: .fit)
.contentShape(Rectangle())
}
var dropLabel: some View {
VStack(spacing: 8) {
Image(systemName: "airplayaudio")
Text("AirDrop")
}
.foregroundStyle(.gray)
.font(.system(.headline, design: .rounded))
.contentShape(Rectangle())
.onTapGesture {
trigger = .init()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
let picker = NSOpenPanel()
picker.allowsMultipleSelection = true
picker.canChooseDirectories = true
picker.canChooseFiles = true
picker.begin { response in
if response == .OK {
let drop = AirDrop(files: picker.urls)
drop.begin()
}
}
}
}
}
func beginDrop(_ providers: [NSItemProvider]) {
assert(!Thread.isMainThread)
guard let urls = providers.interfaceConvert() else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
let drop = AirDrop(files: urls)
drop.begin()
}
}
}

View file

@ -0,0 +1,56 @@
//
// DragDropView.swift
// boringNotch
//
// Created by Richard Kunkli on 2024. 10. 19..
//
import SwiftUI
import AppKit
class DragDropView: NSView {
var onDragEntered: () -> Void = {}
var onDragExited: () -> Void = {}
var onDrop: () -> Void = {}
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
registerForDraggedTypes([.fileURL])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
onDragEntered()
return .copy
}
override func draggingExited(_ sender: NSDraggingInfo?) {
onDragExited()
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
onDrop()
return true
}
}
struct DragDropViewRepresentable: NSViewRepresentable {
@Binding var isTargeted: Bool
var onDrop: () -> Void
func makeNSView(context: Context) -> DragDropView {
let view = DragDropView()
view.onDragEntered = { isTargeted = true }
view.onDragExited = { isTargeted = false }
view.onDrop = onDrop
view.autoresizingMask = [.width, .height]
return view
}
func updateNSView(_ nsView: DragDropView, context: Context) {}
}

View file

@ -0,0 +1,58 @@
//
// TrayDrop+DropItem.swift
// TrayDrop
//
// Created by 秋星桥 on 2024/7/8.
//
import Cocoa
import Foundation
import QuickLook
extension TrayDrop {
struct DropItem: Identifiable, Codable, Equatable, Hashable {
let id: UUID
let fileName: String
let size: Int
let copiedDate: Date
let workspacePreviewImageData: Data
init(url: URL) throws {
assert(!Thread.isMainThread)
id = UUID()
fileName = url.lastPathComponent
size = (try? url.resourceValues(forKeys: [.fileSizeKey]))?.fileSize ?? 0
copiedDate = Date()
workspacePreviewImageData = url.snapshotPreview().pngRepresentation
try FileManager.default.createDirectory(
at: storageURL.deletingLastPathComponent(),
withIntermediateDirectories: true
)
try FileManager.default.copyItem(at: url, to: storageURL)
}
}
}
extension TrayDrop.DropItem {
static let mainDir = "CopiedItems"
var storageURL: URL {
documentsDirectory
.appendingPathComponent(Self.mainDir)
.appendingPathComponent(id.uuidString)
.appendingPathComponent(fileName)
}
var workspacePreviewImage: NSImage {
.init(data: workspacePreviewImageData) ?? .init()
}
var shouldClean: Bool { // TODO: In the future clean if old
return false
}
}

View file

@ -0,0 +1,79 @@
//
// TrayDrop+DropItemView.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/8.
//
import Foundation
import SwiftUI
import UniformTypeIdentifiers
struct DropItemView: View {
let item: TrayDrop.DropItem
@EnvironmentObject var vm: DynamicIslandViewModel
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
@StateObject var tvm = TrayDrop.shared
@State var hover = false
var body: some View {
ZStack(alignment: .topTrailing) {
VStack {
RoundedRectangle(cornerRadius: 6)
.fill(.clear)
.background {
Image(nsImage: item.workspacePreviewImage)
.resizable()
.aspectRatio(contentMode: .fit)
.clipShape(RoundedRectangle(cornerRadius: 6))
}
Text(item.fileName)
.multilineTextAlignment(.center)
.font(.footnote)
.foregroundStyle(hover ? .white : .gray)
.lineLimit(2)
.allowsTightening(true)
}
.contentShape(Rectangle())
.onDrag {
handleOnDrag(for: item)
}
.frame(width: 64, height: 64)
if hover {
Circle()
.fill(.white)
.overlay(Image(systemName: "xmark").foregroundStyle(.black).font(.system(size: 7)).fontWeight(.semibold))
.frame(width: spacing, height: spacing)
.opacity(hover ? 1 : 0) // TODO: Use option key pressed to show delete
.scaleEffect(coordinator.optionKeyPressed ? 1 : 0.5)
.transition(.blurReplace.combined(with: .scale))
.offset(x: spacing / 2, y: -spacing / 2)
.onTapGesture { tvm.delete(item.id) }
.shadow(color: .black, radius: 3)
}
}
.onHover { hovering in
withAnimation(.smooth) {
if hovering {
hover.toggle()
} else {
hover.toggle()
}
}
}
}
private func handleOnDrag(for item: TrayDrop.DropItem) -> NSItemProvider {
guard let itemProvider = NSItemProvider(contentsOf: item.storageURL) else {
return NSItemProvider()
}
let nameWithoutExtension = (item.fileName as NSString).deletingPathExtension
itemProvider.suggestedName = nameWithoutExtension
return itemProvider
}
}

View file

@ -0,0 +1,61 @@
//
// Ext+FileProvider.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/8.
//
import Cocoa
import Foundation
import UniformTypeIdentifiers
extension NSItemProvider {
private func duplicateToOurStorage(_ url: URL?) throws -> URL? {
guard let url else { return nil }
let temp = temporaryDirectory
.appendingPathComponent("TemporaryDrop")
.appendingPathComponent(UUID().uuidString)
.appendingPathComponent(url.lastPathComponent)
try? FileManager.default.createDirectory(
at: temp.deletingLastPathComponent(),
withIntermediateDirectories: true
)
try FileManager.default.copyItem(at: url, to: temp)
return temp
}
func convertToFilePathThatIsWhatWeThinkItWillWorkWithNotchDrop() -> URL? {
var url: URL?
let sem = DispatchSemaphore(value: 0)
_ = loadObject(ofClass: URL.self) { item, _ in
url = try? self.duplicateToOurStorage(item)
sem.signal()
}
sem.wait()
if url == nil {
loadInPlaceFileRepresentation(
forTypeIdentifier: UTType.data.identifier
) { input, _, _ in
defer { sem.signal() }
url = try? self.duplicateToOurStorage(input)
}
sem.wait()
}
return url
}
}
extension [NSItemProvider] {
func interfaceConvert() -> [URL]? {
let urls = compactMap { provider -> URL? in
provider.convertToFilePathThatIsWhatWeThinkItWillWorkWithNotchDrop()
}
guard urls.count == count else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
NSAlert.popError(NSLocalizedString("One or more files failed to load", comment: ""))
}
return nil
}
return urls
}
}

View file

@ -0,0 +1,36 @@
//
// Ext+NSAlert.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/9.
//
import Cocoa
extension NSAlert {
static func popError(_ error: String) {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Error", comment: "")
alert.alertStyle = .critical
alert.informativeText = error
alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
alert.runModal()
}
static func popRestart(_ error: String, completion: @escaping () -> Void) {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Need Restart", comment: "")
alert.alertStyle = .critical
alert.informativeText = error
alert.addButton(withTitle: NSLocalizedString("Exit", comment: ""))
alert.addButton(withTitle: NSLocalizedString("Later", comment: ""))
let response = alert.runModal()
if response == .alertFirstButtonReturn {
completion()
}
}
static func popError(_ error: Error) {
popError(error.localizedDescription)
}
}

View file

@ -0,0 +1,19 @@
//
// Ext+NSImage.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/8.
//
import Cocoa
extension NSImage {
var pngRepresentation: Data {
guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else {
return .init()
}
let imageRep = NSBitmapImageRep(cgImage: cgImage)
imageRep.size = size
return imageRep.representation(using: .png, properties: [:]) ?? .init()
}
}

View file

@ -0,0 +1,24 @@
//
// Ext+URL.swift
// NotchDrop
//
// Created by 秋星桥 on 2024/7/8.
//
import Cocoa
import Foundation
import QuickLook
extension URL {
func snapshotPreview() -> NSImage {
if let preview = QLThumbnailImageCreate(
kCFAllocatorDefault,
self as CFURL,
CGSize(width: 128, height: 128),
nil
)?.takeRetainedValue() {
return NSImage(cgImage: preview, size: .zero)
}
return NSWorkspace.shared.icon(forFile: path)
}
}

View file

@ -0,0 +1,77 @@
import Cocoa
import Combine
import Foundation
import OrderedCollections
class TrayDrop: ObservableObject {
static let shared = TrayDrop()
@Published var items: OrderedSet<DropItem>
var isEmpty: Bool { items.isEmpty }
@Published var isLoading: Int = 0
init(items: OrderedSet<DropItem> = .init(), isLoading: Int = 0) {
self.items = items
self.isLoading = isLoading
}
func load(_ providers: [NSItemProvider]) {
assert(!Thread.isMainThread)
DispatchQueue.main.asyncAndWait { isLoading += 1 }
guard let urls = providers.interfaceConvert() else {
DispatchQueue.main.asyncAndWait { isLoading -= 1 }
print("Faield to load items")
return
}
let dropItems = urls.map { url in
try? DropItem(url: url)
}.compactMap { $0 }
DispatchQueue.main.async {
dropItems.forEach { self.items.updateOrInsert($0, at: 0) }
self.isLoading -= 1
}
print("DONE")
}
func cleanExpiredFiles() {
var inEdit = items
let shouldCleanItems = items.filter(\.shouldClean)
for item in shouldCleanItems {
inEdit.remove(item)
}
items = inEdit
}
func delete(_ item: DropItem.ID) {
guard let item = items.first(where: { $0.id == item }) else { return }
delete(item: item)
}
private func delete(item: DropItem) {
var inEdit = items
var url = item.storageURL
try? FileManager.default.removeItem(at: url)
do {
// loops up to the main directory
url = url.deletingLastPathComponent()
while url.lastPathComponent != DropItem.mainDir, url != documentsDirectory {
let contents = try FileManager.default.contentsOfDirectory(atPath: url.path)
guard contents.isEmpty else { break }
try FileManager.default.removeItem(at: url)
url = url.deletingLastPathComponent()
}
} catch {}
inEdit.remove(item)
items = inEdit
}
func removeAll() {
items.forEach { delete(item: $0) }
}
}