mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Somewhat working file tray
This commit is contained in:
parent
4c7e79b954
commit
30422c3d95
29 changed files with 4032 additions and 65 deletions
115
DynamicIsland/components/Shelf/Views/ShelfView.swift
Normal file
115
DynamicIsland/components/Shelf/Views/ShelfView.swift
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// ShelfItemView.swift
|
||||
// boringNotch
|
||||
//
|
||||
// Created by Alexander on 2025-09-24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
|
||||
struct ShelfView: View {
|
||||
@EnvironmentObject var vm: DynamicIslandViewModel
|
||||
@StateObject var tvm = ShelfStateViewModel.shared
|
||||
@StateObject var selection = ShelfSelectionModel.shared
|
||||
@StateObject private var quickLookService = QuickLookService()
|
||||
private let spacing: CGFloat = 8
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
FileShareView()
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.environmentObject(vm)
|
||||
panel
|
||||
.onDrop(of: [.fileURL, .url, .utf8PlainText, .plainText, .data], isTargeted: $vm.dragDetectorTargeting) { providers in
|
||||
handleDrop(providers: providers)
|
||||
}
|
||||
}
|
||||
// Bind Quick Look to shelf selection
|
||||
.onChange(of: selection.selectedIDs) {
|
||||
updateQuickLookSelection()
|
||||
}
|
||||
.quickLookPresenter(using: quickLookService)
|
||||
}
|
||||
|
||||
private func handleDrop(providers: [NSItemProvider]) -> Bool {
|
||||
guard !selection.isDragging else { return false }
|
||||
vm.dropEvent = true
|
||||
ShelfStateViewModel.shared.load(providers)
|
||||
return true
|
||||
}
|
||||
|
||||
private func updateQuickLookSelection() {
|
||||
guard quickLookService.isQuickLookOpen && !selection.selectedIDs.isEmpty else { return }
|
||||
|
||||
let selectedItems = selection.selectedItems(in: tvm.items)
|
||||
let urls: [URL] = selectedItems.compactMap { item in
|
||||
if let fileURL = item.fileURL {
|
||||
return fileURL
|
||||
}
|
||||
if case .link(let url) = item.kind {
|
||||
return url
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !urls.isEmpty {
|
||||
quickLookService.updateSelection(urls: urls)
|
||||
}
|
||||
}
|
||||
|
||||
var panel: some View {
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.stroke(
|
||||
vm.dragDetectorTargeting
|
||||
? Color.accentColor.opacity(0.9)
|
||||
: Color.white.opacity(0.1),
|
||||
style: StrokeStyle(lineWidth: 3, lineCap: .round, dash: [10])
|
||||
)
|
||||
.overlay {
|
||||
content
|
||||
.padding()
|
||||
}
|
||||
.transaction { transaction in
|
||||
transaction.animation = vm.animation
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { selection.clear() }
|
||||
}
|
||||
|
||||
var content: some View {
|
||||
Group {
|
||||
if tvm.isEmpty {
|
||||
VStack(spacing: 10) {
|
||||
Image(systemName: "tray.and.arrow.down")
|
||||
.symbolVariant(.fill)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.foregroundStyle(.white, .gray)
|
||||
.imageScale(.large)
|
||||
|
||||
Text("Drop files here")
|
||||
.foregroundStyle(.gray)
|
||||
.font(.system(.title3, design: .rounded))
|
||||
.fontWeight(.medium)
|
||||
}
|
||||
} else {
|
||||
ScrollView(.horizontal) {
|
||||
HStack(spacing: spacing) {
|
||||
ForEach(tvm.items) { item in
|
||||
ShelfItemView(item: item)
|
||||
.environmentObject(quickLookService)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(-spacing)
|
||||
.scrollIndicators(.never)
|
||||
.onDrop(of: [.fileURL, .url, .utf8PlainText, .plainText, .data], isTargeted: $vm.dragDetectorTargeting) { providers in
|
||||
handleDrop(providers: providers)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
ShelfStateViewModel.shared.cleanupInvalidItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue