mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 10:29:58 +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:
40
apple/VniDrop/App/VniDropApp.swift
Normal file
40
apple/VniDrop/App/VniDropApp.swift
Normal file
@@ -0,0 +1,40 @@
|
||||
import SwiftUI
|
||||
|
||||
/// App entry point for iOS/iPadOS/macOS, ported from `iOSApp.swift` + `App.kt`.
|
||||
/// Opens `.vnd` invitations via `onOpenURL` and routes them to the receive flow.
|
||||
@main
|
||||
struct VniDropApp: App {
|
||||
@StateObject private var externalInvitations = ExternalInvitationController()
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
RootView(dependencies: makeAppDependencies(externalInvitations: externalInvitations))
|
||||
.ignoresSafeArea()
|
||||
.onOpenURL(perform: openInvitation)
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a `.vnd` invitation document under a security scope, enforcing the
|
||||
/// 64 KiB / strict-UTF-8 rules from `ContentView.swift`.
|
||||
private func openInvitation(_ url: URL) {
|
||||
guard url.pathExtension.caseInsensitiveCompare(vniDropInvitationExtension) == .orderedSame else {
|
||||
externalInvitations.reportOpenFailure(message: "This is not a VniDrop invitation")
|
||||
return
|
||||
}
|
||||
let started = url.startAccessingSecurityScopedResource()
|
||||
defer { if started { url.stopAccessingSecurityScopedResource() } }
|
||||
do {
|
||||
let values = try url.resourceValues(forKeys: [.fileSizeKey])
|
||||
if let size = values.fileSize, size > maxVniDropInvitationBytes {
|
||||
throw InvitationError.tooLarge
|
||||
}
|
||||
let data = try Data(contentsOf: url, options: .mappedIfSafe)
|
||||
let raw = try decodeInvitationBytes(data)
|
||||
externalInvitations.openInvitation(raw: raw)
|
||||
} catch {
|
||||
externalInvitations.reportOpenFailure(
|
||||
message: (error as? LocalizedError)?.errorDescription ?? "The invitation could not be opened"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user