117 lines
3.7 KiB
Swift
117 lines
3.7 KiB
Swift
import ApplicationLibrary
|
|
import Libbox
|
|
import Library
|
|
import SwiftUI
|
|
|
|
@MainActor
|
|
public struct MainView: View {
|
|
@Environment(\.controlActiveState) private var controlActiveState
|
|
@EnvironmentObject private var environments: ExtensionEnvironments
|
|
|
|
@State private var selection = NavigationPage.dashboard
|
|
@State private var importProfile: LibboxProfileContent?
|
|
@State private var importRemoteProfile: LibboxImportRemoteProfile?
|
|
@State private var alert: Alert?
|
|
|
|
public init() {}
|
|
|
|
public var body: some View {
|
|
NavigationSplitView {
|
|
SidebarView()
|
|
.navigationSplitViewColumnWidth(150)
|
|
} detail: {
|
|
NavigationStack {
|
|
selection.contentView
|
|
.navigationTitle(selection.title)
|
|
}
|
|
.navigationSplitViewColumnWidth(650)
|
|
}
|
|
.frame(minHeight: 500)
|
|
.onAppear {
|
|
environments.postReload()
|
|
#if !DEBUG
|
|
if Variant.useSystemExtension {
|
|
Task {
|
|
checkApplicationPath()
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
.alertBinding($alert)
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigation) {
|
|
StartStopButton()
|
|
}
|
|
}
|
|
.onChangeCompat(of: controlActiveState) { newValue in
|
|
if newValue != .inactive {
|
|
environments.postReload()
|
|
}
|
|
}
|
|
.onChangeCompat(of: selection) { value in
|
|
if value == .logs {
|
|
environments.connectLog()
|
|
}
|
|
}
|
|
.onReceive(environments.openSettings) {
|
|
selection = .settings
|
|
}
|
|
.environment(\.selection, $selection)
|
|
.environment(\.importProfile, $importProfile)
|
|
.environment(\.importRemoteProfile, $importRemoteProfile)
|
|
.handlesExternalEvents(preferring: [], allowing: ["*"])
|
|
.onOpenURL(perform: openURL)
|
|
}
|
|
|
|
private func openURL(url: URL) {
|
|
if url.host == "import-remote-profile" {
|
|
var error: NSError?
|
|
importRemoteProfile = LibboxParseRemoteProfileImportLink(url.absoluteString, &error)
|
|
if error != nil {
|
|
return
|
|
}
|
|
if selection != .profiles {
|
|
selection = .profiles
|
|
}
|
|
} else if url.pathExtension == "bpf" {
|
|
Task {
|
|
await importURLProfile(url)
|
|
}
|
|
} else {
|
|
alert = Alert(errorMessage: "Handled unknown URL \(url.absoluteString)")
|
|
}
|
|
}
|
|
|
|
private func importURLProfile(_ url: URL) async {
|
|
do {
|
|
_ = url.startAccessingSecurityScopedResource()
|
|
importProfile = try await .from(readURL(url))
|
|
url.stopAccessingSecurityScopedResource()
|
|
} catch {
|
|
alert = Alert(error)
|
|
return
|
|
}
|
|
if selection != .profiles {
|
|
selection = .profiles
|
|
}
|
|
}
|
|
|
|
private nonisolated func readURL(_ url: URL) async throws -> Data {
|
|
try Data(contentsOf: url)
|
|
}
|
|
|
|
private func checkApplicationPath() {
|
|
let directoryName = URL(filePath: Bundle.main.bundlePath).deletingLastPathComponent().pathComponents.last
|
|
if directoryName != "Applications" {
|
|
alert = Alert(
|
|
title: Text("Wrong application location"),
|
|
message: Text("This app needs to be placed under ~/Applications to work."),
|
|
dismissButton: .default(Text("Ok")) {
|
|
NSWorkspace.shared.selectFile(Bundle.main.bundlePath, inFileViewerRootedAtPath: "")
|
|
NSApp.terminate(nil)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|