mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 02:29:55 +02:00
feat(apple): native SwiftUI app for iOS and macOS
Add a native SwiftUI VniDrop app (Send/Receive/Settings) talking to the Rust core via generated UniFFI Swift bindings, plus the uniffi-bindgen helper crate. iOS uses a TabView, macOS a NavigationSplitView sidebar.
This commit is contained in:
55
apple/VniDrop/Platform/FileSystemService+macOS.swift
Normal file
55
apple/VniDrop/Platform/FileSystemService+macOS.swift
Normal file
@@ -0,0 +1,55 @@
|
||||
#if os(macOS)
|
||||
import Foundation
|
||||
import AppKit
|
||||
import VnidropCore
|
||||
|
||||
/// macOS file system service. Mirrors the desktop JVM behavior: default Downloads
|
||||
/// receive folder, custom folders enabled via security-scoped bookmarks, reveal in
|
||||
/// Finder. The Rust core streams bytes; Swift passes filesystem paths.
|
||||
struct MacFileSystemService: FileSystemService {
|
||||
var supportsCustomReceiveFolders: Bool { true }
|
||||
|
||||
func defaultReceiveFolder() -> ReceiveFolder {
|
||||
let url = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
|
||||
?? FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("Downloads")
|
||||
return ReceiveFolder(kind: .fileSystemPath, value: url.path, displayName: url.lastPathComponent)
|
||||
}
|
||||
|
||||
func validateReceiveFolder(_ folder: ReceiveFolder) async -> FolderAccessStatus {
|
||||
FileManager.default.isWritableFile(atPath: folder.value) ? .writable : .unavailable
|
||||
}
|
||||
|
||||
func canRevealReceiveFolder(_ folder: ReceiveFolder) -> Bool { true }
|
||||
|
||||
func revealReceiveFolder(_ folder: ReceiveFolder) async -> Result<Void, Error> {
|
||||
let url = URL(fileURLWithPath: folder.value, isDirectory: true)
|
||||
NSWorkspace.shared.activateFileViewerSelecting([url])
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func discardPickedFiles(_ files: [PickedShareFile]) async {
|
||||
let paths = Set(files.filter { $0.isTemporaryCopy }.map { $0.value })
|
||||
for path in paths {
|
||||
try? FileManager.default.removeItem(atPath: path)
|
||||
}
|
||||
}
|
||||
|
||||
func sharePickedFiles(
|
||||
repository: CoreRepository,
|
||||
files: [PickedShareFile],
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy
|
||||
) async -> Result<Share, Error> {
|
||||
guard !files.isEmpty else {
|
||||
return .failure(InvitationError.message("Select at least one file to share"))
|
||||
}
|
||||
let sources = files.map {
|
||||
ShareSource(kind: .path, value: $0.value, displayName: $0.displayName, isDirectory: $0.isDirectory)
|
||||
}
|
||||
return await repository.shareSources(
|
||||
sources, transferName: transferName, senderName: senderName, accessPolicy: accessPolicy
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user